diff --git a/.ci/Jenkinsfile_coverage b/.ci/Jenkinsfile_coverage index d9ec1861c9979e..01c18b10d0804b 100644 --- a/.ci/Jenkinsfile_coverage +++ b/.ci/Jenkinsfile_coverage @@ -16,14 +16,14 @@ stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a withEnv([ 'NODE_ENV=test' // Needed for jest tests only ]) { - kibanaPipeline.legacyJobRunner('kibana-intake')() + kibanaPipeline.intakeWorker('kibana-intake', './test/scripts/jenkins_unit.sh')() } }, 'x-pack-intake-agent': { withEnv([ 'NODE_ENV=test' // Needed for jest tests only ]) { - kibanaPipeline.legacyJobRunner('x-pack-intake')() + kibanaPipeline.intakeWorker('x-pack-intake', './test/scripts/jenkins_xpack.sh')() } }, 'kibana-oss-agent': kibanaPipeline.withWorkers('kibana-oss-tests', { kibanaPipeline.buildOss() }, [ diff --git a/.ci/es-snapshots/Jenkinsfile_verify_es b/.ci/es-snapshots/Jenkinsfile_verify_es index 3d5ec75fa0e72a..30d52a56547bd2 100644 --- a/.ci/es-snapshots/Jenkinsfile_verify_es +++ b/.ci/es-snapshots/Jenkinsfile_verify_es @@ -26,8 +26,8 @@ timeout(time: 120, unit: 'MINUTES') { withEnv(["ES_SNAPSHOT_MANIFEST=${SNAPSHOT_MANIFEST}"]) { parallel([ // TODO we just need to run integration tests from intake? - 'kibana-intake-agent': kibanaPipeline.legacyJobRunner('kibana-intake'), - 'x-pack-intake-agent': kibanaPipeline.legacyJobRunner('x-pack-intake'), + 'kibana-intake-agent': kibanaPipeline.intakeWorker('kibana-intake', './test/scripts/jenkins_unit.sh'), + 'x-pack-intake-agent': kibanaPipeline.intakeWorker('x-pack-intake', './test/scripts/jenkins_xpack.sh'), 'kibana-oss-agent': kibanaPipeline.withWorkers('kibana-oss-tests', { kibanaPipeline.buildOss() }, [ 'oss-ciGroup1': kibanaPipeline.getOssCiGroupWorker(1), 'oss-ciGroup2': kibanaPipeline.getOssCiGroupWorker(2), diff --git a/.ci/jobs.yml b/.ci/jobs.yml index a2d8100f78efd0..3add92aadd2561 100644 --- a/.ci/jobs.yml +++ b/.ci/jobs.yml @@ -1,3 +1,5 @@ +# This file is needed by functionalTests:ensureAllTestsInCiGroup for the list of ciGroups. That must be changed before this file can be removed + JOB: - kibana-intake - x-pack-intake diff --git a/.ci/run.sh b/.ci/run.sh deleted file mode 100755 index 9f77438be62d0f..00000000000000 --- a/.ci/run.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# move to Kibana root -cd "$(dirname "$0")/.." - -source src/dev/ci_setup/load_env_keys.sh -source src/dev/ci_setup/extract_bootstrap_cache.sh -source src/dev/ci_setup/setup.sh -source src/dev/ci_setup/checkout_sibling_es.sh - -case "$JOB" in -kibana-intake) - ./test/scripts/jenkins_unit.sh - ;; -kibana-ciGroup*) - export CI_GROUP="${JOB##kibana-ciGroup}" - ./test/scripts/jenkins_ci_group.sh - ;; -kibana-visualRegression*) - ./test/scripts/jenkins_visual_regression.sh - ;; -kibana-accessibility*) - ./test/scripts/jenkins_accessibility.sh - ;; -kibana-firefoxSmoke*) - ./test/scripts/jenkins_firefox_smoke.sh - ;; -x-pack-intake) - ./test/scripts/jenkins_xpack.sh - ;; -x-pack-ciGroup*) - export CI_GROUP="${JOB##x-pack-ciGroup}" - ./test/scripts/jenkins_xpack_ci_group.sh - ;; -x-pack-visualRegression*) - ./test/scripts/jenkins_xpack_visual_regression.sh - ;; -x-pack-accessibility*) - ./test/scripts/jenkins_xpack_accessibility.sh - ;; -x-pack-firefoxSmoke*) - ./test/scripts/jenkins_xpack_firefox_smoke.sh - ;; -*) - echo "JOB '$JOB' is not implemented." - exit 1 - ;; -esac diff --git a/.eslintignore b/.eslintignore index c4fb806b6d394c..86a01b68ecab1f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,6 +9,7 @@ bower_components /built_assets /html_docs /src/plugins/data/common/es_query/kuery/ast/_generated_/** +/src/legacy/core_plugins/vis_type_timelion/public/_generated_/** src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data /src/legacy/ui/public/angular-bootstrap /src/legacy/ui/public/flot-charts diff --git a/.eslintrc.js b/.eslintrc.js index 2c5804da053a6b..310949b23fe361 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -244,15 +244,15 @@ module.exports = { { target: [ '(src|x-pack)/plugins/**/*', - '!(src|x-pack)/plugins/*/server/**/*', + '!(src|x-pack)/plugins/**/server/**/*', 'src/legacy/core_plugins/**/*', - '!src/legacy/core_plugins/*/server/**/*', - '!src/legacy/core_plugins/*/index.{js,ts,tsx}', + '!src/legacy/core_plugins/**/server/**/*', + '!src/legacy/core_plugins/**/index.{js,ts,tsx}', 'x-pack/legacy/plugins/**/*', - '!x-pack/legacy/plugins/*/server/**/*', - '!x-pack/legacy/plugins/*/index.{js,ts,tsx}', + '!x-pack/legacy/plugins/**/server/**/*', + '!x-pack/legacy/plugins/**/index.{js,ts,tsx}', 'examples/**/*', '!examples/**/server/**/*', @@ -262,6 +262,8 @@ module.exports = { 'src/core/server/**/*', '(src|x-pack)/plugins/*/server/**/*', 'examples/**/server/**/*', + // TODO: Remove the 'joi' eslint rule once IE11 support is dropped + 'joi', ], errorMessage: 'Server modules cannot be imported into client modules or shared modules.', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 16e6059852de8c..df8c7e40a3ba8a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -15,7 +15,11 @@ /src/legacy/core_plugins/kibana/public/home/ @elastic/kibana-app /src/legacy/core_plugins/kibana/public/dev_tools/ @elastic/kibana-app /src/legacy/core_plugins/metrics/ @elastic/kibana-app -/src/plugins/home/ @elastic/kibana-app +/src/legacy/core_plugins/vis_type_vislib/ @elastic/kibana-app +# Exclude tutorials folder for now because they are not owned by Kibana app and most will move out soon +/src/plugins/home/public @elastic/kibana-app +/src/plugins/home/server/*.ts @elastic/kibana-app +/src/plugins/home/server/services/ @elastic/kibana-app /src/plugins/kibana_legacy/ @elastic/kibana-app /src/plugins/timelion/ @elastic/kibana-app /src/plugins/dev_tools/ @elastic/kibana-app @@ -44,8 +48,11 @@ # APM /x-pack/legacy/plugins/apm/ @elastic/apm-ui +/x-pack/plugins/apm/ @elastic/apm-ui /x-pack/test/functional/apps/apm/ @elastic/apm-ui /src/legacy/core_plugins/apm_oss/ @elastic/apm-ui +/src/plugins/apm_oss/ @elastic/apm-ui +/src/apm.js @watson # Beats /x-pack/legacy/plugins/beats_management/ @elastic/beats @@ -128,6 +135,7 @@ # Kibana Alerting Services /x-pack/legacy/plugins/alerting/ @elastic/kibana-alerting-services /x-pack/legacy/plugins/actions/ @elastic/kibana-alerting-services +/x-pack/plugins/event_log/ @elastic/kibana-alerting-services /x-pack/plugins/task_manager/ @elastic/kibana-alerting-services /x-pack/test/alerting_api_integration/ @elastic/kibana-alerting-services /x-pack/test/plugin_api_integration/plugins/task_manager/ @elastic/kibana-alerting-services @@ -149,6 +157,6 @@ /x-pack/legacy/plugins/license_management/ @elastic/es-ui /x-pack/legacy/plugins/remote_clusters/ @elastic/es-ui /x-pack/legacy/plugins/rollup/ @elastic/es-ui -/x-pack/legacy/plugins/searchprofiler/ @elastic/es-ui +/x-pack/plugins/searchprofiler/ @elastic/es-ui /x-pack/legacy/plugins/snapshot_restore/ @elastic/es-ui -/x-pack/legacy/plugins/watcher/ @elastic/es-ui +/x-pack/plugins/watcher/ @elastic/es-ui diff --git a/.i18nrc.json b/.i18nrc.json index 73acf92cda1491..f03ced2b85093a 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -21,7 +21,6 @@ "interpreter": "src/legacy/core_plugins/interpreter", "kbn": "src/legacy/core_plugins/kibana", "kbnDocViews": "src/legacy/core_plugins/kbn_doc_views", - "kbnVislibVisTypes": "src/legacy/core_plugins/vis_type_vislib", "management": ["src/legacy/core_plugins/management", "src/plugins/management"], "kibana_react": "src/legacy/core_plugins/kibana_react", "kibana-react": "src/plugins/kibana_react", @@ -33,7 +32,7 @@ "statusPage": "src/legacy/core_plugins/status_page", "telemetry": "src/legacy/core_plugins/telemetry", "tileMap": "src/legacy/core_plugins/tile_map", - "timelion": ["src/legacy/core_plugins/timelion", "src/legacy/core_plugins/vis_type_timelion"], + "timelion": ["src/legacy/core_plugins/timelion", "src/legacy/core_plugins/vis_type_timelion", "src/plugins/timelion"], "uiActions": "src/plugins/ui_actions", "visTypeMarkdown": "src/legacy/core_plugins/vis_type_markdown", "visTypeMetric": "src/legacy/core_plugins/vis_type_metric", @@ -41,6 +40,7 @@ "visTypeTagCloud": "src/legacy/core_plugins/vis_type_tagcloud", "visTypeTimeseries": "src/legacy/core_plugins/vis_type_timeseries", "visTypeVega": "src/legacy/core_plugins/vis_type_vega", + "visTypeVislib": "src/legacy/core_plugins/vis_type_vislib", "visualizations": [ "src/plugins/visualizations", "src/legacy/core_plugins/visualizations" @@ -50,4 +50,4 @@ "src/legacy/ui/ui_render/ui_render_mixin.js" ], "translations": [] -} \ No newline at end of file +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6ae3db559b61ba..86be6e7e971556 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -338,7 +338,7 @@ The `config/kibana.yml` file stores user configuration directives. Since this fi #### Setting Up SSL -Kibana includes a self-signed certificate that can be used for development purposes: `yarn start --ssl`. +Kibana includes self-signed certificates that can be used for development purposes in the browser and for communicating with Elasticsearch: `yarn start --ssl` & `yarn es snapshot --ssl`. ### Linting diff --git a/Jenkinsfile b/Jenkinsfile index f6844c7f03fe62..4e6f3141a12e7b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -4,16 +4,21 @@ library 'kibana-pipeline-library' kibanaLibrary.load() stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a little bit - timeout(time: 120, unit: 'MINUTES') { + timeout(time: 135, unit: 'MINUTES') { timestamps { ansiColor('xterm') { githubPr.withDefaultPrComments { catchError { + retryable.enable() parallel([ - 'kibana-intake-agent': kibanaPipeline.legacyJobRunner('kibana-intake'), - 'x-pack-intake-agent': kibanaPipeline.legacyJobRunner('x-pack-intake'), + 'kibana-intake-agent': kibanaPipeline.intakeWorker('kibana-intake', './test/scripts/jenkins_unit.sh'), + 'x-pack-intake-agent': kibanaPipeline.intakeWorker('x-pack-intake', './test/scripts/jenkins_xpack.sh'), 'kibana-oss-agent': kibanaPipeline.withWorkers('kibana-oss-tests', { kibanaPipeline.buildOss() }, [ - 'oss-firefoxSmoke': kibanaPipeline.getPostBuildWorker('firefoxSmoke', { runbld('./test/scripts/jenkins_firefox_smoke.sh', 'Execute kibana-firefoxSmoke') }), + 'oss-firefoxSmoke': kibanaPipeline.getPostBuildWorker('firefoxSmoke', { + retryable('kibana-firefoxSmoke') { + runbld('./test/scripts/jenkins_firefox_smoke.sh', 'Execute kibana-firefoxSmoke') + } + }), 'oss-ciGroup1': kibanaPipeline.getOssCiGroupWorker(1), 'oss-ciGroup2': kibanaPipeline.getOssCiGroupWorker(2), 'oss-ciGroup3': kibanaPipeline.getOssCiGroupWorker(3), @@ -26,11 +31,19 @@ stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a 'oss-ciGroup10': kibanaPipeline.getOssCiGroupWorker(10), 'oss-ciGroup11': kibanaPipeline.getOssCiGroupWorker(11), 'oss-ciGroup12': kibanaPipeline.getOssCiGroupWorker(12), - 'oss-accessibility': kibanaPipeline.getPostBuildWorker('accessibility', { runbld('./test/scripts/jenkins_accessibility.sh', 'Execute kibana-accessibility') }), + 'oss-accessibility': kibanaPipeline.getPostBuildWorker('accessibility', { + retryable('kibana-accessibility') { + runbld('./test/scripts/jenkins_accessibility.sh', 'Execute kibana-accessibility') + } + }), // 'oss-visualRegression': kibanaPipeline.getPostBuildWorker('visualRegression', { runbld('./test/scripts/jenkins_visual_regression.sh', 'Execute kibana-visualRegression') }), ]), 'kibana-xpack-agent': kibanaPipeline.withWorkers('kibana-xpack-tests', { kibanaPipeline.buildXpack() }, [ - 'xpack-firefoxSmoke': kibanaPipeline.getPostBuildWorker('xpack-firefoxSmoke', { runbld('./test/scripts/jenkins_xpack_firefox_smoke.sh', 'Execute xpack-firefoxSmoke') }), + 'xpack-firefoxSmoke': kibanaPipeline.getPostBuildWorker('xpack-firefoxSmoke', { + retryable('xpack-firefoxSmoke') { + runbld('./test/scripts/jenkins_xpack_firefox_smoke.sh', 'Execute xpack-firefoxSmoke') + } + }), 'xpack-ciGroup1': kibanaPipeline.getXpackCiGroupWorker(1), 'xpack-ciGroup2': kibanaPipeline.getXpackCiGroupWorker(2), 'xpack-ciGroup3': kibanaPipeline.getXpackCiGroupWorker(3), @@ -41,12 +54,18 @@ stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a 'xpack-ciGroup8': kibanaPipeline.getXpackCiGroupWorker(8), 'xpack-ciGroup9': kibanaPipeline.getXpackCiGroupWorker(9), 'xpack-ciGroup10': kibanaPipeline.getXpackCiGroupWorker(10), - 'xpack-accessibility': kibanaPipeline.getPostBuildWorker('xpack-accessibility', { runbld('./test/scripts/jenkins_xpack_accessibility.sh', 'Execute xpack-accessibility') }), + 'xpack-accessibility': kibanaPipeline.getPostBuildWorker('xpack-accessibility', { + retryable('xpack-accessibility') { + runbld('./test/scripts/jenkins_xpack_accessibility.sh', 'Execute xpack-accessibility') + } + }), // 'xpack-visualRegression': kibanaPipeline.getPostBuildWorker('xpack-visualRegression', { runbld('./test/scripts/jenkins_xpack_visual_regression.sh', 'Execute xpack-visualRegression') }), ]), ]) } } + + retryable.printFlakyFailures() kibanaPipeline.sendMail() } } diff --git a/api-documenter.json b/api-documenter.json new file mode 100644 index 00000000000000..a2303b939c8ec2 --- /dev/null +++ b/api-documenter.json @@ -0,0 +1,4 @@ +{ + "newlineKind": "lf", + "outputTarget": "markdown" +} diff --git a/docs/api/saved-objects/import.asciidoc b/docs/api/saved-objects/import.asciidoc index 5b4c5016be4ed3..1a380830ed21a6 100644 --- a/docs/api/saved-objects/import.asciidoc +++ b/docs/api/saved-objects/import.asciidoc @@ -57,7 +57,7 @@ Import an index pattern and dashboard: [source,js] -------------------------------------------------- -$ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson <1> +$ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson -------------------------------------------------- The `file.ndjson` file contains the following: diff --git a/docs/developer/visualize/development-create-visualization.asciidoc b/docs/developer/visualize/development-create-visualization.asciidoc index faaa9b36a7a00a..e38b76471ab251 100644 --- a/docs/developer/visualize/development-create-visualization.asciidoc +++ b/docs/developer/visualize/development-create-visualization.asciidoc @@ -62,7 +62,7 @@ The list of common parameters: - *visualization*: A constructor function for a Visualization. - *requestHandler*: one of the available request handlers or a for a custom request handler - *responseHandler*: one of the available response handlers or a for a custom response handler -- *editor*: one of the available editors or Editor class for custom one +- *editor*: Editor class for custom one - *editorConfig*: object holding editor parameters - *options.showTimePicker*: show or hide time filter (defaults to true) - *options.showQueryBar*: show or hide query bar (defaults to true) @@ -218,7 +218,6 @@ These tabs should be React components. title: 'My New Vis', icon: 'my_icon', description: 'Cool new chart', - editor: 'default', editorConfig: { optionsTemplate: MyReactComponent // or if multiple tabs are required: optionTabs: [ diff --git a/docs/development/core/public/index.md b/docs/development/core/public/index.md index 3badb447f0858a..be1aaed88696d9 100644 --- a/docs/development/core/public/index.md +++ b/docs/development/core/public/index.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) - -## API Reference - -## Packages - -| Package | Description | -| --- | --- | -| [kibana-plugin-public](./kibana-plugin-public.md) | The Kibana Core APIs for client-side plugins.A plugin's public/index file must contain a named import, plugin, that implements which returns an object that implements .The plugin integrates with the core system via lifecycle events: setup, start, and stop. In each lifecycle method, the plugin will receive the corresponding core services available (either or ) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. | - + + +[Home](./index.md) + +## API Reference + +## Packages + +| Package | Description | +| --- | --- | +| [kibana-plugin-public](./kibana-plugin-public.md) | The Kibana Core APIs for client-side plugins.A plugin's public/index file must contain a named import, plugin, that implements which returns an object that implements .The plugin integrates with the core system via lifecycle events: setup, start, and stop. In each lifecycle method, the plugin will receive the corresponding core services available (either or ) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. | + diff --git a/docs/development/core/public/kibana-plugin-public.app.approute.md b/docs/development/core/public/kibana-plugin-public.app.approute.md index 7f35f4346b6b3a..76c5b7952259fa 100644 --- a/docs/development/core/public/kibana-plugin-public.app.approute.md +++ b/docs/development/core/public/kibana-plugin-public.app.approute.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) > [appRoute](./kibana-plugin-public.app.approute.md) - -## App.appRoute property - -Override the application's routing path from `/app/${id}`. Must be unique across registered applications. Should not include the base path from HTTP. - -Signature: - -```typescript -appRoute?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) > [appRoute](./kibana-plugin-public.app.approute.md) + +## App.appRoute property + +Override the application's routing path from `/app/${id}`. Must be unique across registered applications. Should not include the base path from HTTP. + +Signature: + +```typescript +appRoute?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.app.chromeless.md b/docs/development/core/public/kibana-plugin-public.app.chromeless.md index dc1e19bab80b29..ce68c68ba8c725 100644 --- a/docs/development/core/public/kibana-plugin-public.app.chromeless.md +++ b/docs/development/core/public/kibana-plugin-public.app.chromeless.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) > [chromeless](./kibana-plugin-public.app.chromeless.md) - -## App.chromeless property - -Hide the UI chrome when the application is mounted. Defaults to `false`. Takes precedence over chrome service visibility settings. - -Signature: - -```typescript -chromeless?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) > [chromeless](./kibana-plugin-public.app.chromeless.md) + +## App.chromeless property + +Hide the UI chrome when the application is mounted. Defaults to `false`. Takes precedence over chrome service visibility settings. + +Signature: + +```typescript +chromeless?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.app.md b/docs/development/core/public/kibana-plugin-public.app.md index acf07cbf62e91e..faea94c4677266 100644 --- a/docs/development/core/public/kibana-plugin-public.app.md +++ b/docs/development/core/public/kibana-plugin-public.app.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) - -## App interface - -Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. - -Signature: - -```typescript -export interface App extends AppBase -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [appRoute](./kibana-plugin-public.app.approute.md) | string | Override the application's routing path from /app/${id}. Must be unique across registered applications. Should not include the base path from HTTP. | -| [chromeless](./kibana-plugin-public.app.chromeless.md) | boolean | Hide the UI chrome when the application is mounted. Defaults to false. Takes precedence over chrome service visibility settings. | -| [mount](./kibana-plugin-public.app.mount.md) | AppMount | AppMountDeprecated | A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md). | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) + +## App interface + +Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. + +Signature: + +```typescript +export interface App extends AppBase +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [appRoute](./kibana-plugin-public.app.approute.md) | string | Override the application's routing path from /app/${id}. Must be unique across registered applications. Should not include the base path from HTTP. | +| [chromeless](./kibana-plugin-public.app.chromeless.md) | boolean | Hide the UI chrome when the application is mounted. Defaults to false. Takes precedence over chrome service visibility settings. | +| [mount](./kibana-plugin-public.app.mount.md) | AppMount | AppMountDeprecated | A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md). | + diff --git a/docs/development/core/public/kibana-plugin-public.app.mount.md b/docs/development/core/public/kibana-plugin-public.app.mount.md index 151fb7baeb138f..2af5f0277759a7 100644 --- a/docs/development/core/public/kibana-plugin-public.app.mount.md +++ b/docs/development/core/public/kibana-plugin-public.app.mount.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) > [mount](./kibana-plugin-public.app.mount.md) - -## App.mount property - -A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md). - -Signature: - -```typescript -mount: AppMount | AppMountDeprecated; -``` - -## Remarks - -When function has two arguments, it will be called with a [context](./kibana-plugin-public.appmountcontext.md) as the first argument. This behavior is \*\*deprecated\*\*, and consumers should instead use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) > [mount](./kibana-plugin-public.app.mount.md) + +## App.mount property + +A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md). + +Signature: + +```typescript +mount: AppMount | AppMountDeprecated; +``` + +## Remarks + +When function has two arguments, it will be called with a [context](./kibana-plugin-public.appmountcontext.md) as the first argument. This behavior is \*\*deprecated\*\*, and consumers should instead use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). + diff --git a/docs/development/core/public/kibana-plugin-public.appbase.capabilities.md b/docs/development/core/public/kibana-plugin-public.appbase.capabilities.md index 450972e41bb299..4aaeaaf00f25b3 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.capabilities.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.capabilities.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [capabilities](./kibana-plugin-public.appbase.capabilities.md) - -## AppBase.capabilities property - -Custom capabilities defined by the app. - -Signature: - -```typescript -capabilities?: Partial; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [capabilities](./kibana-plugin-public.appbase.capabilities.md) + +## AppBase.capabilities property + +Custom capabilities defined by the app. + +Signature: + +```typescript +capabilities?: Partial; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.category.md b/docs/development/core/public/kibana-plugin-public.appbase.category.md new file mode 100644 index 00000000000000..d3c6e0acf5e69d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.category.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [category](./kibana-plugin-public.appbase.category.md) + +## AppBase.category property + +The category definition of the product See [AppCategory](./kibana-plugin-public.appcategory.md) See DEFAULT\_APP\_CATEGORIES for more reference + +Signature: + +```typescript +category?: AppCategory; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.chromeless.md b/docs/development/core/public/kibana-plugin-public.appbase.chromeless.md index ddbf9aafbd28a5..8763a255411992 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.chromeless.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.chromeless.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [chromeless](./kibana-plugin-public.appbase.chromeless.md) - -## AppBase.chromeless property - -Hide the UI chrome when the application is mounted. Defaults to `false`. Takes precedence over chrome service visibility settings. - -Signature: - -```typescript -chromeless?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [chromeless](./kibana-plugin-public.appbase.chromeless.md) + +## AppBase.chromeless property + +Hide the UI chrome when the application is mounted. Defaults to `false`. Takes precedence over chrome service visibility settings. + +Signature: + +```typescript +chromeless?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.euiicontype.md b/docs/development/core/public/kibana-plugin-public.appbase.euiicontype.md index 99c7e852ff9052..18ef718800772a 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.euiicontype.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.euiicontype.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [euiIconType](./kibana-plugin-public.appbase.euiicontype.md) - -## AppBase.euiIconType property - -A EUI iconType that will be used for the app's icon. This icon takes precendence over the `icon` property. - -Signature: - -```typescript -euiIconType?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [euiIconType](./kibana-plugin-public.appbase.euiicontype.md) + +## AppBase.euiIconType property + +A EUI iconType that will be used for the app's icon. This icon takes precendence over the `icon` property. + +Signature: + +```typescript +euiIconType?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.icon.md b/docs/development/core/public/kibana-plugin-public.appbase.icon.md index d94d0897bc5b75..0bf6eb22acf9d3 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.icon.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.icon.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [icon](./kibana-plugin-public.appbase.icon.md) - -## AppBase.icon property - -A URL to an image file used as an icon. Used as a fallback if `euiIconType` is not provided. - -Signature: - -```typescript -icon?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [icon](./kibana-plugin-public.appbase.icon.md) + +## AppBase.icon property + +A URL to an image file used as an icon. Used as a fallback if `euiIconType` is not provided. + +Signature: + +```typescript +icon?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.id.md b/docs/development/core/public/kibana-plugin-public.appbase.id.md index 89dd32d296104c..4c3f471a6155c6 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.id.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [id](./kibana-plugin-public.appbase.id.md) - -## AppBase.id property - -The unique identifier of the application - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [id](./kibana-plugin-public.appbase.id.md) + +## AppBase.id property + +The unique identifier of the application + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.md b/docs/development/core/public/kibana-plugin-public.appbase.md index eb6d91cb924888..194ba28e416bf1 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.md @@ -1,29 +1,30 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) - -## AppBase interface - - -Signature: - -```typescript -export interface AppBase -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [capabilities](./kibana-plugin-public.appbase.capabilities.md) | Partial<Capabilities> | Custom capabilities defined by the app. | -| [chromeless](./kibana-plugin-public.appbase.chromeless.md) | boolean | Hide the UI chrome when the application is mounted. Defaults to false. Takes precedence over chrome service visibility settings. | -| [euiIconType](./kibana-plugin-public.appbase.euiicontype.md) | string | A EUI iconType that will be used for the app's icon. This icon takes precendence over the icon property. | -| [icon](./kibana-plugin-public.appbase.icon.md) | string | A URL to an image file used as an icon. Used as a fallback if euiIconType is not provided. | -| [id](./kibana-plugin-public.appbase.id.md) | string | The unique identifier of the application | -| [navLinkStatus](./kibana-plugin-public.appbase.navlinkstatus.md) | AppNavLinkStatus | The initial status of the application's navLink. Defaulting to visible if status is accessible and hidden if status is inaccessible See [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) | -| [order](./kibana-plugin-public.appbase.order.md) | number | An ordinal used to sort nav links relative to one another for display. | -| [status](./kibana-plugin-public.appbase.status.md) | AppStatus | The initial status of the application. Defaulting to accessible | -| [title](./kibana-plugin-public.appbase.title.md) | string | The title of the application. | -| [tooltip](./kibana-plugin-public.appbase.tooltip.md) | string | A tooltip shown when hovering over app link. | -| [updater$](./kibana-plugin-public.appbase.updater_.md) | Observable<AppUpdater> | An [AppUpdater](./kibana-plugin-public.appupdater.md) observable that can be used to update the application [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) at runtime. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) + +## AppBase interface + + +Signature: + +```typescript +export interface AppBase +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [capabilities](./kibana-plugin-public.appbase.capabilities.md) | Partial<Capabilities> | Custom capabilities defined by the app. | +| [category](./kibana-plugin-public.appbase.category.md) | AppCategory | The category definition of the product See [AppCategory](./kibana-plugin-public.appcategory.md) See DEFAULT\_APP\_CATEGORIES for more reference | +| [chromeless](./kibana-plugin-public.appbase.chromeless.md) | boolean | Hide the UI chrome when the application is mounted. Defaults to false. Takes precedence over chrome service visibility settings. | +| [euiIconType](./kibana-plugin-public.appbase.euiicontype.md) | string | A EUI iconType that will be used for the app's icon. This icon takes precendence over the icon property. | +| [icon](./kibana-plugin-public.appbase.icon.md) | string | A URL to an image file used as an icon. Used as a fallback if euiIconType is not provided. | +| [id](./kibana-plugin-public.appbase.id.md) | string | The unique identifier of the application | +| [navLinkStatus](./kibana-plugin-public.appbase.navlinkstatus.md) | AppNavLinkStatus | The initial status of the application's navLink. Defaulting to visible if status is accessible and hidden if status is inaccessible See [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) | +| [order](./kibana-plugin-public.appbase.order.md) | number | An ordinal used to sort nav links relative to one another for display. | +| [status](./kibana-plugin-public.appbase.status.md) | AppStatus | The initial status of the application. Defaulting to accessible | +| [title](./kibana-plugin-public.appbase.title.md) | string | The title of the application. | +| [tooltip](./kibana-plugin-public.appbase.tooltip.md) | string | A tooltip shown when hovering over app link. | +| [updater$](./kibana-plugin-public.appbase.updater_.md) | Observable<AppUpdater> | An [AppUpdater](./kibana-plugin-public.appupdater.md) observable that can be used to update the application [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) at runtime. | + diff --git a/docs/development/core/public/kibana-plugin-public.appbase.navlinkstatus.md b/docs/development/core/public/kibana-plugin-public.appbase.navlinkstatus.md index d6744c3e757568..90a3e6dd089514 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.navlinkstatus.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.navlinkstatus.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [navLinkStatus](./kibana-plugin-public.appbase.navlinkstatus.md) - -## AppBase.navLinkStatus property - -The initial status of the application's navLink. Defaulting to `visible` if `status` is `accessible` and `hidden` if status is `inaccessible` See [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) - -Signature: - -```typescript -navLinkStatus?: AppNavLinkStatus; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [navLinkStatus](./kibana-plugin-public.appbase.navlinkstatus.md) + +## AppBase.navLinkStatus property + +The initial status of the application's navLink. Defaulting to `visible` if `status` is `accessible` and `hidden` if status is `inaccessible` See [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) + +Signature: + +```typescript +navLinkStatus?: AppNavLinkStatus; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.order.md b/docs/development/core/public/kibana-plugin-public.appbase.order.md index dc0ea14a7b860b..312e327e54f9c9 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.order.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.order.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [order](./kibana-plugin-public.appbase.order.md) - -## AppBase.order property - -An ordinal used to sort nav links relative to one another for display. - -Signature: - -```typescript -order?: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [order](./kibana-plugin-public.appbase.order.md) + +## AppBase.order property + +An ordinal used to sort nav links relative to one another for display. + +Signature: + +```typescript +order?: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.status.md b/docs/development/core/public/kibana-plugin-public.appbase.status.md index a5fbadbeea1ffc..eee3f9bdfa78fa 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.status.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.status.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [status](./kibana-plugin-public.appbase.status.md) - -## AppBase.status property - -The initial status of the application. Defaulting to `accessible` - -Signature: - -```typescript -status?: AppStatus; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [status](./kibana-plugin-public.appbase.status.md) + +## AppBase.status property + +The initial status of the application. Defaulting to `accessible` + +Signature: + +```typescript +status?: AppStatus; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.title.md b/docs/development/core/public/kibana-plugin-public.appbase.title.md index 4d0fb0c18e8143..bb9cbb7b53e842 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.title.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.title.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [title](./kibana-plugin-public.appbase.title.md) - -## AppBase.title property - -The title of the application. - -Signature: - -```typescript -title: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [title](./kibana-plugin-public.appbase.title.md) + +## AppBase.title property + +The title of the application. + +Signature: + +```typescript +title: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.tooltip.md b/docs/development/core/public/kibana-plugin-public.appbase.tooltip.md index 85921a5a321dd2..0d3bb59870c420 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.tooltip.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.tooltip.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [tooltip](./kibana-plugin-public.appbase.tooltip.md) - -## AppBase.tooltip property - -A tooltip shown when hovering over app link. - -Signature: - -```typescript -tooltip?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [tooltip](./kibana-plugin-public.appbase.tooltip.md) + +## AppBase.tooltip property + +A tooltip shown when hovering over app link. + +Signature: + +```typescript +tooltip?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.updater_.md b/docs/development/core/public/kibana-plugin-public.appbase.updater_.md index 3edd3573834491..a15a1666a4e008 100644 --- a/docs/development/core/public/kibana-plugin-public.appbase.updater_.md +++ b/docs/development/core/public/kibana-plugin-public.appbase.updater_.md @@ -1,44 +1,44 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [updater$](./kibana-plugin-public.appbase.updater_.md) - -## AppBase.updater$ property - -An [AppUpdater](./kibana-plugin-public.appupdater.md) observable that can be used to update the application [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) at runtime. - -Signature: - -```typescript -updater$?: Observable; -``` - -## Example - -How to update an application navLink at runtime - -```ts -// inside your plugin's setup function -export class MyPlugin implements Plugin { - private appUpdater = new BehaviorSubject(() => ({})); - - setup({ application }) { - application.register({ - id: 'my-app', - title: 'My App', - updater$: this.appUpdater, - async mount(params) { - const { renderApp } = await import('./application'); - return renderApp(params); - }, - }); - } - - start() { - // later, when the navlink needs to be updated - appUpdater.next(() => { - navLinkStatus: AppNavLinkStatus.disabled, - }) - } - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [updater$](./kibana-plugin-public.appbase.updater_.md) + +## AppBase.updater$ property + +An [AppUpdater](./kibana-plugin-public.appupdater.md) observable that can be used to update the application [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) at runtime. + +Signature: + +```typescript +updater$?: Observable; +``` + +## Example + +How to update an application navLink at runtime + +```ts +// inside your plugin's setup function +export class MyPlugin implements Plugin { + private appUpdater = new BehaviorSubject(() => ({})); + + setup({ application }) { + application.register({ + id: 'my-app', + title: 'My App', + updater$: this.appUpdater, + async mount(params) { + const { renderApp } = await import('./application'); + return renderApp(params); + }, + }); + } + + start() { + // later, when the navlink needs to be updated + appUpdater.next(() => { + navLinkStatus: AppNavLinkStatus.disabled, + }) + } + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.arialabel.md b/docs/development/core/public/kibana-plugin-public.appcategory.arialabel.md new file mode 100644 index 00000000000000..813174001bb036 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appcategory.arialabel.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) > [ariaLabel](./kibana-plugin-public.appcategory.arialabel.md) + +## AppCategory.ariaLabel property + +If the visual label isn't appropriate for screen readers, can override it here + +Signature: + +```typescript +ariaLabel?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.euiicontype.md b/docs/development/core/public/kibana-plugin-public.appcategory.euiicontype.md new file mode 100644 index 00000000000000..652bcb9e05edfe --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appcategory.euiicontype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) > [euiIconType](./kibana-plugin-public.appcategory.euiicontype.md) + +## AppCategory.euiIconType property + +Define an icon to be used for the category If the category is only 1 item, and no icon is defined, will default to the product icon Defaults to initials if no icon is defined + +Signature: + +```typescript +euiIconType?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.label.md b/docs/development/core/public/kibana-plugin-public.appcategory.label.md new file mode 100644 index 00000000000000..692c032b01a699 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appcategory.label.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) > [label](./kibana-plugin-public.appcategory.label.md) + +## AppCategory.label property + +Label used for cateogry name. Also used as aria-label if one isn't set. + +Signature: + +```typescript +label: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.md b/docs/development/core/public/kibana-plugin-public.appcategory.md new file mode 100644 index 00000000000000..8c40113a8c4387 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appcategory.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) + +## AppCategory interface + +A category definition for nav links to know where to sort them in the left hand nav + +Signature: + +```typescript +export interface AppCategory +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [ariaLabel](./kibana-plugin-public.appcategory.arialabel.md) | string | If the visual label isn't appropriate for screen readers, can override it here | +| [euiIconType](./kibana-plugin-public.appcategory.euiicontype.md) | string | Define an icon to be used for the category If the category is only 1 item, and no icon is defined, will default to the product icon Defaults to initials if no icon is defined | +| [label](./kibana-plugin-public.appcategory.label.md) | string | Label used for cateogry name. Also used as aria-label if one isn't set. | +| [order](./kibana-plugin-public.appcategory.order.md) | number | The order that categories will be sorted in Prefer large steps between categories to allow for further editing (Default categories are in steps of 1000) | + diff --git a/docs/development/core/public/kibana-plugin-public.appcategory.order.md b/docs/development/core/public/kibana-plugin-public.appcategory.order.md new file mode 100644 index 00000000000000..170d3d9559e937 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appcategory.order.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppCategory](./kibana-plugin-public.appcategory.md) > [order](./kibana-plugin-public.appcategory.order.md) + +## AppCategory.order property + +The order that categories will be sorted in Prefer large steps between categories to allow for further editing (Default categories are in steps of 1000) + +Signature: + +```typescript +order?: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appleaveaction.md b/docs/development/core/public/kibana-plugin-public.appleaveaction.md index ae56205f5e45ca..e81b925feaee87 100644 --- a/docs/development/core/public/kibana-plugin-public.appleaveaction.md +++ b/docs/development/core/public/kibana-plugin-public.appleaveaction.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveAction](./kibana-plugin-public.appleaveaction.md) - -## AppLeaveAction type - -Possible actions to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) - -See [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) and [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) - -Signature: - -```typescript -export declare type AppLeaveAction = AppLeaveDefaultAction | AppLeaveConfirmAction; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveAction](./kibana-plugin-public.appleaveaction.md) + +## AppLeaveAction type + +Possible actions to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) + +See [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) and [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) + +Signature: + +```typescript +export declare type AppLeaveAction = AppLeaveDefaultAction | AppLeaveConfirmAction; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appleaveactiontype.md b/docs/development/core/public/kibana-plugin-public.appleaveactiontype.md index 482b2e489b33e4..3ee49d60eb1c76 100644 --- a/docs/development/core/public/kibana-plugin-public.appleaveactiontype.md +++ b/docs/development/core/public/kibana-plugin-public.appleaveactiontype.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveActionType](./kibana-plugin-public.appleaveactiontype.md) - -## AppLeaveActionType enum - -Possible type of actions on application leave. - -Signature: - -```typescript -export declare enum AppLeaveActionType -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| confirm | "confirm" | | -| default | "default" | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveActionType](./kibana-plugin-public.appleaveactiontype.md) + +## AppLeaveActionType enum + +Possible type of actions on application leave. + +Signature: + +```typescript +export declare enum AppLeaveActionType +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| confirm | "confirm" | | +| default | "default" | | + diff --git a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.md b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.md index 4cd99dd2a3fb3f..ea3c0dbba7ec47 100644 --- a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.md +++ b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) - -## AppLeaveConfirmAction interface - -Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to show a confirmation message when trying to leave an application. - -See - -Signature: - -```typescript -export interface AppLeaveConfirmAction -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [text](./kibana-plugin-public.appleaveconfirmaction.text.md) | string | | -| [title](./kibana-plugin-public.appleaveconfirmaction.title.md) | string | | -| [type](./kibana-plugin-public.appleaveconfirmaction.type.md) | AppLeaveActionType.confirm | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) + +## AppLeaveConfirmAction interface + +Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to show a confirmation message when trying to leave an application. + +See + +Signature: + +```typescript +export interface AppLeaveConfirmAction +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [text](./kibana-plugin-public.appleaveconfirmaction.text.md) | string | | +| [title](./kibana-plugin-public.appleaveconfirmaction.title.md) | string | | +| [type](./kibana-plugin-public.appleaveconfirmaction.type.md) | AppLeaveActionType.confirm | | + diff --git a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.text.md b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.text.md index dbbd11c6f71f88..6b572b6bd98459 100644 --- a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.text.md +++ b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.text.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [text](./kibana-plugin-public.appleaveconfirmaction.text.md) - -## AppLeaveConfirmAction.text property - -Signature: - -```typescript -text: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [text](./kibana-plugin-public.appleaveconfirmaction.text.md) + +## AppLeaveConfirmAction.text property + +Signature: + +```typescript +text: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.title.md b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.title.md index 684ef384a37c35..47b15dd32efcfb 100644 --- a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.title.md +++ b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.title.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [title](./kibana-plugin-public.appleaveconfirmaction.title.md) - -## AppLeaveConfirmAction.title property - -Signature: - -```typescript -title?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [title](./kibana-plugin-public.appleaveconfirmaction.title.md) + +## AppLeaveConfirmAction.title property + +Signature: + +```typescript +title?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.type.md b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.type.md index 926cecf893cc85..e8e34c446ff53a 100644 --- a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.type.md +++ b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [type](./kibana-plugin-public.appleaveconfirmaction.type.md) - -## AppLeaveConfirmAction.type property - -Signature: - -```typescript -type: AppLeaveActionType.confirm; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [type](./kibana-plugin-public.appleaveconfirmaction.type.md) + +## AppLeaveConfirmAction.type property + +Signature: + +```typescript +type: AppLeaveActionType.confirm; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.md b/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.md index ed2f729a0c6482..5682dc88119e2f 100644 --- a/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.md +++ b/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) - -## AppLeaveDefaultAction interface - -Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to execute the default behaviour when leaving the application. - -See - -Signature: - -```typescript -export interface AppLeaveDefaultAction -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [type](./kibana-plugin-public.appleavedefaultaction.type.md) | AppLeaveActionType.default | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) + +## AppLeaveDefaultAction interface + +Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to execute the default behaviour when leaving the application. + +See + +Signature: + +```typescript +export interface AppLeaveDefaultAction +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [type](./kibana-plugin-public.appleavedefaultaction.type.md) | AppLeaveActionType.default | | + diff --git a/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.type.md b/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.type.md index ee12393121a5a4..8db979b1bba5cf 100644 --- a/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.type.md +++ b/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) > [type](./kibana-plugin-public.appleavedefaultaction.type.md) - -## AppLeaveDefaultAction.type property - -Signature: - -```typescript -type: AppLeaveActionType.default; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) > [type](./kibana-plugin-public.appleavedefaultaction.type.md) + +## AppLeaveDefaultAction.type property + +Signature: + +```typescript +type: AppLeaveActionType.default; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appleavehandler.md b/docs/development/core/public/kibana-plugin-public.appleavehandler.md index e879227961bc6f..8f4bad65a6cd6b 100644 --- a/docs/development/core/public/kibana-plugin-public.appleavehandler.md +++ b/docs/development/core/public/kibana-plugin-public.appleavehandler.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) - -## AppLeaveHandler type - -A handler that will be executed before leaving the application, either when going to another application or when closing the browser tab or manually changing the url. Should return `confirm` to to prompt a message to the user before leaving the page, or `default` to keep the default behavior (doing nothing). - -See [AppMountParameters](./kibana-plugin-public.appmountparameters.md) for detailed usage examples. - -Signature: - -```typescript -export declare type AppLeaveHandler = (factory: AppLeaveActionFactory) => AppLeaveAction; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) + +## AppLeaveHandler type + +A handler that will be executed before leaving the application, either when going to another application or when closing the browser tab or manually changing the url. Should return `confirm` to to prompt a message to the user before leaving the page, or `default` to keep the default behavior (doing nothing). + +See [AppMountParameters](./kibana-plugin-public.appmountparameters.md) for detailed usage examples. + +Signature: + +```typescript +export declare type AppLeaveHandler = (factory: AppLeaveActionFactory) => AppLeaveAction; +``` diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.md index cf9bc5189af409..7497752ac386e1 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationsetup.md +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) - -## ApplicationSetup interface - - -Signature: - -```typescript -export interface ApplicationSetup -``` - -## Methods - -| Method | Description | -| --- | --- | -| [register(app)](./kibana-plugin-public.applicationsetup.register.md) | Register an mountable application to the system. | -| [registerAppUpdater(appUpdater$)](./kibana-plugin-public.applicationsetup.registerappupdater.md) | Register an application updater that can be used to change the [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) fields of all applications at runtime.This is meant to be used by plugins that needs to updates the whole list of applications. To only updates a specific application, use the updater$ property of the registered application instead. | -| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationsetup.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) + +## ApplicationSetup interface + + +Signature: + +```typescript +export interface ApplicationSetup +``` + +## Methods + +| Method | Description | +| --- | --- | +| [register(app)](./kibana-plugin-public.applicationsetup.register.md) | Register an mountable application to the system. | +| [registerAppUpdater(appUpdater$)](./kibana-plugin-public.applicationsetup.registerappupdater.md) | Register an application updater that can be used to change the [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) fields of all applications at runtime.This is meant to be used by plugins that needs to updates the whole list of applications. To only updates a specific application, use the updater$ property of the registered application instead. | +| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationsetup.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). | + diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md index b4ccb6a01c6001..5c6c7cd252b0a7 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [register](./kibana-plugin-public.applicationsetup.register.md) - -## ApplicationSetup.register() method - -Register an mountable application to the system. - -Signature: - -```typescript -register(app: App): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| app | App | an [App](./kibana-plugin-public.app.md) | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [register](./kibana-plugin-public.applicationsetup.register.md) + +## ApplicationSetup.register() method + +Register an mountable application to the system. + +Signature: + +```typescript +register(app: App): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| app | App | an [App](./kibana-plugin-public.app.md) | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.registerappupdater.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.registerappupdater.md index 39b4f878a3f795..b3a2dcb2b7de12 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationsetup.registerappupdater.md +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.registerappupdater.md @@ -1,47 +1,47 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [registerAppUpdater](./kibana-plugin-public.applicationsetup.registerappupdater.md) - -## ApplicationSetup.registerAppUpdater() method - -Register an application updater that can be used to change the [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) fields of all applications at runtime. - -This is meant to be used by plugins that needs to updates the whole list of applications. To only updates a specific application, use the `updater$` property of the registered application instead. - -Signature: - -```typescript -registerAppUpdater(appUpdater$: Observable): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| appUpdater$ | Observable<AppUpdater> | | - -Returns: - -`void` - -## Example - -How to register an application updater that disables some applications: - -```ts -// inside your plugin's setup function -export class MyPlugin implements Plugin { - setup({ application }) { - application.registerAppUpdater( - new BehaviorSubject(app => { - if (myPluginApi.shouldDisable(app)) - return { - status: AppStatus.inaccessible, - }; - }) - ); - } -} - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [registerAppUpdater](./kibana-plugin-public.applicationsetup.registerappupdater.md) + +## ApplicationSetup.registerAppUpdater() method + +Register an application updater that can be used to change the [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) fields of all applications at runtime. + +This is meant to be used by plugins that needs to updates the whole list of applications. To only updates a specific application, use the `updater$` property of the registered application instead. + +Signature: + +```typescript +registerAppUpdater(appUpdater$: Observable): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| appUpdater$ | Observable<AppUpdater> | | + +Returns: + +`void` + +## Example + +How to register an application updater that disables some applications: + +```ts +// inside your plugin's setup function +export class MyPlugin implements Plugin { + setup({ application }) { + application.registerAppUpdater( + new BehaviorSubject(app => { + if (myPluginApi.shouldDisable(app)) + return { + status: AppStatus.inaccessible, + }; + }) + ); + } +} + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md index 275ba431bc7e7c..e1d28bbdb70308 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md @@ -1,29 +1,29 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [registerMountContext](./kibana-plugin-public.applicationsetup.registermountcontext.md) - -## ApplicationSetup.registerMountContext() method - -> Warning: This API is now obsolete. -> -> - -Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). - -Signature: - -```typescript -registerMountContext(contextName: T, provider: IContextProvider): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| contextName | T | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. | -| provider | IContextProvider<AppMountDeprecated, T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [registerMountContext](./kibana-plugin-public.applicationsetup.registermountcontext.md) + +## ApplicationSetup.registerMountContext() method + +> Warning: This API is now obsolete. +> +> + +Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). + +Signature: + +```typescript +registerMountContext(contextName: T, provider: IContextProvider): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| contextName | T | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. | +| provider | IContextProvider<AppMountDeprecated, T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.capabilities.md b/docs/development/core/public/kibana-plugin-public.applicationstart.capabilities.md index 14326197ea5490..ef61b32d9b7f23 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationstart.capabilities.md +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.capabilities.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [capabilities](./kibana-plugin-public.applicationstart.capabilities.md) - -## ApplicationStart.capabilities property - -Gets the read-only capabilities. - -Signature: - -```typescript -capabilities: RecursiveReadonly; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [capabilities](./kibana-plugin-public.applicationstart.capabilities.md) + +## ApplicationStart.capabilities property + +Gets the read-only capabilities. + +Signature: + +```typescript +capabilities: RecursiveReadonly; +``` diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.geturlforapp.md b/docs/development/core/public/kibana-plugin-public.applicationstart.geturlforapp.md index 422fbdf7418c23..7eadd4d4e9d440 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationstart.geturlforapp.md +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.geturlforapp.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [getUrlForApp](./kibana-plugin-public.applicationstart.geturlforapp.md) - -## ApplicationStart.getUrlForApp() method - -Returns a relative URL to a given app, including the global base path. - -Signature: - -```typescript -getUrlForApp(appId: string, options?: { - path?: string; - }): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| appId | string | | -| options | {
path?: string;
} | | - -Returns: - -`string` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [getUrlForApp](./kibana-plugin-public.applicationstart.geturlforapp.md) + +## ApplicationStart.getUrlForApp() method + +Returns a relative URL to a given app, including the global base path. + +Signature: + +```typescript +getUrlForApp(appId: string, options?: { + path?: string; + }): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| appId | string | | +| options | {
path?: string;
} | | + +Returns: + +`string` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.md b/docs/development/core/public/kibana-plugin-public.applicationstart.md index e36ef3f14f87e8..3ad7e3b1656d80 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationstart.md +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) - -## ApplicationStart interface - - -Signature: - -```typescript -export interface ApplicationStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [capabilities](./kibana-plugin-public.applicationstart.capabilities.md) | RecursiveReadonly<Capabilities> | Gets the read-only capabilities. | - -## Methods - -| Method | Description | -| --- | --- | -| [getUrlForApp(appId, options)](./kibana-plugin-public.applicationstart.geturlforapp.md) | Returns a relative URL to a given app, including the global base path. | -| [navigateToApp(appId, options)](./kibana-plugin-public.applicationstart.navigatetoapp.md) | Navigate to a given app | -| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationstart.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) + +## ApplicationStart interface + + +Signature: + +```typescript +export interface ApplicationStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [capabilities](./kibana-plugin-public.applicationstart.capabilities.md) | RecursiveReadonly<Capabilities> | Gets the read-only capabilities. | + +## Methods + +| Method | Description | +| --- | --- | +| [getUrlForApp(appId, options)](./kibana-plugin-public.applicationstart.geturlforapp.md) | Returns a relative URL to a given app, including the global base path. | +| [navigateToApp(appId, options)](./kibana-plugin-public.applicationstart.navigatetoapp.md) | Navigate to a given app | +| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationstart.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). | + diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md b/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md index 3e29d09ea4cd56..9a1f1da689584b 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [navigateToApp](./kibana-plugin-public.applicationstart.navigatetoapp.md) - -## ApplicationStart.navigateToApp() method - -Navigate to a given app - -Signature: - -```typescript -navigateToApp(appId: string, options?: { - path?: string; - state?: any; - }): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| appId | string | | -| options | {
path?: string;
state?: any;
} | | - -Returns: - -`Promise` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [navigateToApp](./kibana-plugin-public.applicationstart.navigatetoapp.md) + +## ApplicationStart.navigateToApp() method + +Navigate to a given app + +Signature: + +```typescript +navigateToApp(appId: string, options?: { + path?: string; + state?: any; + }): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| appId | string | | +| options | {
path?: string;
state?: any;
} | | + +Returns: + +`Promise` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md b/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md index c15a23fe82b21d..0eb1cb60ec5fd6 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md @@ -1,29 +1,29 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [registerMountContext](./kibana-plugin-public.applicationstart.registermountcontext.md) - -## ApplicationStart.registerMountContext() method - -> Warning: This API is now obsolete. -> -> - -Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). - -Signature: - -```typescript -registerMountContext(contextName: T, provider: IContextProvider): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| contextName | T | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. | -| provider | IContextProvider<AppMountDeprecated, T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [registerMountContext](./kibana-plugin-public.applicationstart.registermountcontext.md) + +## ApplicationStart.registerMountContext() method + +> Warning: This API is now obsolete. +> +> + +Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). + +Signature: + +```typescript +registerMountContext(contextName: T, provider: IContextProvider): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| contextName | T | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. | +| provider | IContextProvider<AppMountDeprecated, T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.appmount.md b/docs/development/core/public/kibana-plugin-public.appmount.md index 25faa7be30b68f..84a52b09a119cb 100644 --- a/docs/development/core/public/kibana-plugin-public.appmount.md +++ b/docs/development/core/public/kibana-plugin-public.appmount.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMount](./kibana-plugin-public.appmount.md) - -## AppMount type - -A mount function called when the user navigates to this app's route. - -Signature: - -```typescript -export declare type AppMount = (params: AppMountParameters) => AppUnmount | Promise; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMount](./kibana-plugin-public.appmount.md) + +## AppMount type + +A mount function called when the user navigates to this app's route. + +Signature: + +```typescript +export declare type AppMount = (params: AppMountParameters) => AppUnmount | Promise; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appmountcontext.core.md b/docs/development/core/public/kibana-plugin-public.appmountcontext.core.md index e01a5e9da50d54..6ec2d18f33d80f 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountcontext.core.md +++ b/docs/development/core/public/kibana-plugin-public.appmountcontext.core.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountContext](./kibana-plugin-public.appmountcontext.md) > [core](./kibana-plugin-public.appmountcontext.core.md) - -## AppMountContext.core property - -Core service APIs available to mounted applications. - -Signature: - -```typescript -core: { - application: Pick; - chrome: ChromeStart; - docLinks: DocLinksStart; - http: HttpStart; - i18n: I18nStart; - notifications: NotificationsStart; - overlays: OverlayStart; - savedObjects: SavedObjectsStart; - uiSettings: IUiSettingsClient; - injectedMetadata: { - getInjectedVar: (name: string, defaultValue?: any) => unknown; - }; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountContext](./kibana-plugin-public.appmountcontext.md) > [core](./kibana-plugin-public.appmountcontext.core.md) + +## AppMountContext.core property + +Core service APIs available to mounted applications. + +Signature: + +```typescript +core: { + application: Pick; + chrome: ChromeStart; + docLinks: DocLinksStart; + http: HttpStart; + i18n: I18nStart; + notifications: NotificationsStart; + overlays: OverlayStart; + savedObjects: SavedObjectsStart; + uiSettings: IUiSettingsClient; + injectedMetadata: { + getInjectedVar: (name: string, defaultValue?: any) => unknown; + }; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appmountcontext.md b/docs/development/core/public/kibana-plugin-public.appmountcontext.md index 2f8c0553d0b382..6c0860ad9f6b74 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountcontext.md +++ b/docs/development/core/public/kibana-plugin-public.appmountcontext.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountContext](./kibana-plugin-public.appmountcontext.md) - -## AppMountContext interface - -> Warning: This API is now obsolete. -> -> - -The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). - -Signature: - -```typescript -export interface AppMountContext -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [core](./kibana-plugin-public.appmountcontext.core.md) | {
application: Pick<ApplicationStart, 'capabilities' | 'navigateToApp'>;
chrome: ChromeStart;
docLinks: DocLinksStart;
http: HttpStart;
i18n: I18nStart;
notifications: NotificationsStart;
overlays: OverlayStart;
savedObjects: SavedObjectsStart;
uiSettings: IUiSettingsClient;
injectedMetadata: {
getInjectedVar: (name: string, defaultValue?: any) => unknown;
};
} | Core service APIs available to mounted applications. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountContext](./kibana-plugin-public.appmountcontext.md) + +## AppMountContext interface + +> Warning: This API is now obsolete. +> +> + +The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). + +Signature: + +```typescript +export interface AppMountContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [core](./kibana-plugin-public.appmountcontext.core.md) | {
application: Pick<ApplicationStart, 'capabilities' | 'navigateToApp'>;
chrome: ChromeStart;
docLinks: DocLinksStart;
http: HttpStart;
i18n: I18nStart;
notifications: NotificationsStart;
overlays: OverlayStart;
savedObjects: SavedObjectsStart;
uiSettings: IUiSettingsClient;
injectedMetadata: {
getInjectedVar: (name: string, defaultValue?: any) => unknown;
};
} | Core service APIs available to mounted applications. | + diff --git a/docs/development/core/public/kibana-plugin-public.appmountdeprecated.md b/docs/development/core/public/kibana-plugin-public.appmountdeprecated.md index 936642abcc97a3..8c8114182b60fc 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountdeprecated.md +++ b/docs/development/core/public/kibana-plugin-public.appmountdeprecated.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md) - -## AppMountDeprecated type - -> Warning: This API is now obsolete. -> -> - -A mount function called when the user navigates to this app's route. - -Signature: - -```typescript -export declare type AppMountDeprecated = (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; -``` - -## Remarks - -When function has two arguments, it will be called with a [context](./kibana-plugin-public.appmountcontext.md) as the first argument. This behavior is \*\*deprecated\*\*, and consumers should instead use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md) + +## AppMountDeprecated type + +> Warning: This API is now obsolete. +> +> + +A mount function called when the user navigates to this app's route. + +Signature: + +```typescript +export declare type AppMountDeprecated = (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; +``` + +## Remarks + +When function has two arguments, it will be called with a [context](./kibana-plugin-public.appmountcontext.md) as the first argument. This behavior is \*\*deprecated\*\*, and consumers should instead use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). + diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md index 7cd709d615729f..041d976aa42a2f 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md @@ -1,58 +1,58 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [appBasePath](./kibana-plugin-public.appmountparameters.appbasepath.md) - -## AppMountParameters.appBasePath property - -The route path for configuring navigation to the application. This string should not include the base path from HTTP. - -Signature: - -```typescript -appBasePath: string; -``` - -## Example - -How to configure react-router with a base path: - -```ts -// inside your plugin's setup function -export class MyPlugin implements Plugin { - setup({ application }) { - application.register({ - id: 'my-app', - appRoute: '/my-app', - async mount(params) { - const { renderApp } = await import('./application'); - return renderApp(params); - }, - }); - } -} - -``` - -```ts -// application.tsx -import React from 'react'; -import ReactDOM from 'react-dom'; -import { BrowserRouter, Route } from 'react-router-dom'; - -import { CoreStart, AppMountParams } from 'src/core/public'; -import { MyPluginDepsStart } from './plugin'; - -export renderApp = ({ appBasePath, element }: AppMountParams) => { - ReactDOM.render( - // pass `appBasePath` to `basename` - - - , - element - ); - - return () => ReactDOM.unmountComponentAtNode(element); -} - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [appBasePath](./kibana-plugin-public.appmountparameters.appbasepath.md) + +## AppMountParameters.appBasePath property + +The route path for configuring navigation to the application. This string should not include the base path from HTTP. + +Signature: + +```typescript +appBasePath: string; +``` + +## Example + +How to configure react-router with a base path: + +```ts +// inside your plugin's setup function +export class MyPlugin implements Plugin { + setup({ application }) { + application.register({ + id: 'my-app', + appRoute: '/my-app', + async mount(params) { + const { renderApp } = await import('./application'); + return renderApp(params); + }, + }); + } +} + +``` + +```ts +// application.tsx +import React from 'react'; +import ReactDOM from 'react-dom'; +import { BrowserRouter, Route } from 'react-router-dom'; + +import { CoreStart, AppMountParams } from 'src/core/public'; +import { MyPluginDepsStart } from './plugin'; + +export renderApp = ({ appBasePath, element }: AppMountParams) => { + ReactDOM.render( + // pass `appBasePath` to `basename` + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +} + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.element.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.element.md index dbe496c01c2150..0c6759df8197cf 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountparameters.element.md +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.element.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [element](./kibana-plugin-public.appmountparameters.element.md) - -## AppMountParameters.element property - -The container element to render the application into. - -Signature: - -```typescript -element: HTMLElement; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [element](./kibana-plugin-public.appmountparameters.element.md) + +## AppMountParameters.element property + +The container element to render the application into. + +Signature: + +```typescript +element: HTMLElement; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.md index 9586eba96a697b..c21889c28bda4f 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountparameters.md +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) - -## AppMountParameters interface - - -Signature: - -```typescript -export interface AppMountParameters -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [appBasePath](./kibana-plugin-public.appmountparameters.appbasepath.md) | string | The route path for configuring navigation to the application. This string should not include the base path from HTTP. | -| [element](./kibana-plugin-public.appmountparameters.element.md) | HTMLElement | The container element to render the application into. | -| [onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md) | (handler: AppLeaveHandler) => void | A function that can be used to register a handler that will be called when the user is leaving the current application, allowing to prompt a confirmation message before actually changing the page.This will be called either when the user goes to another application, or when trying to close the tab or manually changing the url. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) + +## AppMountParameters interface + + +Signature: + +```typescript +export interface AppMountParameters +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [appBasePath](./kibana-plugin-public.appmountparameters.appbasepath.md) | string | The route path for configuring navigation to the application. This string should not include the base path from HTTP. | +| [element](./kibana-plugin-public.appmountparameters.element.md) | HTMLElement | The container element to render the application into. | +| [onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md) | (handler: AppLeaveHandler) => void | A function that can be used to register a handler that will be called when the user is leaving the current application, allowing to prompt a confirmation message before actually changing the page.This will be called either when the user goes to another application, or when trying to close the tab or manually changing the url. | + diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.onappleave.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.onappleave.md index 55eb840ce1cf68..283ae34f14c545 100644 --- a/docs/development/core/public/kibana-plugin-public.appmountparameters.onappleave.md +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.onappleave.md @@ -1,41 +1,41 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md) - -## AppMountParameters.onAppLeave property - -A function that can be used to register a handler that will be called when the user is leaving the current application, allowing to prompt a confirmation message before actually changing the page. - -This will be called either when the user goes to another application, or when trying to close the tab or manually changing the url. - -Signature: - -```typescript -onAppLeave: (handler: AppLeaveHandler) => void; -``` - -## Example - - -```ts -// application.tsx -import React from 'react'; -import ReactDOM from 'react-dom'; -import { BrowserRouter, Route } from 'react-router-dom'; - -import { CoreStart, AppMountParams } from 'src/core/public'; -import { MyPluginDepsStart } from './plugin'; - -export renderApp = ({ appBasePath, element, onAppLeave }: AppMountParams) => { - const { renderApp, hasUnsavedChanges } = await import('./application'); - onAppLeave(actions => { - if(hasUnsavedChanges()) { - return actions.confirm('Some changes were not saved. Are you sure you want to leave?'); - } - return actions.default(); - }); - return renderApp(params); -} - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md) + +## AppMountParameters.onAppLeave property + +A function that can be used to register a handler that will be called when the user is leaving the current application, allowing to prompt a confirmation message before actually changing the page. + +This will be called either when the user goes to another application, or when trying to close the tab or manually changing the url. + +Signature: + +```typescript +onAppLeave: (handler: AppLeaveHandler) => void; +``` + +## Example + + +```ts +// application.tsx +import React from 'react'; +import ReactDOM from 'react-dom'; +import { BrowserRouter, Route } from 'react-router-dom'; + +import { CoreStart, AppMountParams } from 'src/core/public'; +import { MyPluginDepsStart } from './plugin'; + +export renderApp = ({ appBasePath, element, onAppLeave }: AppMountParams) => { + const { renderApp, hasUnsavedChanges } = await import('./application'); + onAppLeave(actions => { + if(hasUnsavedChanges()) { + return actions.confirm('Some changes were not saved. Are you sure you want to leave?'); + } + return actions.default(); + }); + return renderApp(params); +} + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.appnavlinkstatus.md b/docs/development/core/public/kibana-plugin-public.appnavlinkstatus.md index d6b22ac2b92178..be6953c6f3667e 100644 --- a/docs/development/core/public/kibana-plugin-public.appnavlinkstatus.md +++ b/docs/development/core/public/kibana-plugin-public.appnavlinkstatus.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) - -## AppNavLinkStatus enum - -Status of the application's navLink. - -Signature: - -```typescript -export declare enum AppNavLinkStatus -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| default | 0 | The application navLink will be visible if the application's [AppStatus](./kibana-plugin-public.appstatus.md) is set to accessible and hidden if the application status is set to inaccessible. | -| disabled | 2 | The application navLink is visible but inactive and not clickable in the navigation bar. | -| hidden | 3 | The application navLink does not appear in the navigation bar. | -| visible | 1 | The application navLink is visible and clickable in the navigation bar. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) + +## AppNavLinkStatus enum + +Status of the application's navLink. + +Signature: + +```typescript +export declare enum AppNavLinkStatus +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| default | 0 | The application navLink will be visible if the application's [AppStatus](./kibana-plugin-public.appstatus.md) is set to accessible and hidden if the application status is set to inaccessible. | +| disabled | 2 | The application navLink is visible but inactive and not clickable in the navigation bar. | +| hidden | 3 | The application navLink does not appear in the navigation bar. | +| visible | 1 | The application navLink is visible and clickable in the navigation bar. | + diff --git a/docs/development/core/public/kibana-plugin-public.appstatus.md b/docs/development/core/public/kibana-plugin-public.appstatus.md index 23fb7186569dad..35b7b4cb224d90 100644 --- a/docs/development/core/public/kibana-plugin-public.appstatus.md +++ b/docs/development/core/public/kibana-plugin-public.appstatus.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppStatus](./kibana-plugin-public.appstatus.md) - -## AppStatus enum - -Accessibility status of an application. - -Signature: - -```typescript -export declare enum AppStatus -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| accessible | 0 | Application is accessible. | -| inaccessible | 1 | Application is not accessible. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppStatus](./kibana-plugin-public.appstatus.md) + +## AppStatus enum + +Accessibility status of an application. + +Signature: + +```typescript +export declare enum AppStatus +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| accessible | 0 | Application is accessible. | +| inaccessible | 1 | Application is not accessible. | + diff --git a/docs/development/core/public/kibana-plugin-public.appunmount.md b/docs/development/core/public/kibana-plugin-public.appunmount.md index 61782d19ca8c58..041a9ab3dbc0ba 100644 --- a/docs/development/core/public/kibana-plugin-public.appunmount.md +++ b/docs/development/core/public/kibana-plugin-public.appunmount.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUnmount](./kibana-plugin-public.appunmount.md) - -## AppUnmount type - -A function called when an application should be unmounted from the page. This function should be synchronous. - -Signature: - -```typescript -export declare type AppUnmount = () => void; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUnmount](./kibana-plugin-public.appunmount.md) + +## AppUnmount type + +A function called when an application should be unmounted from the page. This function should be synchronous. + +Signature: + +```typescript +export declare type AppUnmount = () => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appupdatablefields.md b/docs/development/core/public/kibana-plugin-public.appupdatablefields.md index b9260c79cd972b..f588773976143b 100644 --- a/docs/development/core/public/kibana-plugin-public.appupdatablefields.md +++ b/docs/development/core/public/kibana-plugin-public.appupdatablefields.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) - -## AppUpdatableFields type - -Defines the list of fields that can be updated via an [AppUpdater](./kibana-plugin-public.appupdater.md). - -Signature: - -```typescript -export declare type AppUpdatableFields = Pick; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) + +## AppUpdatableFields type + +Defines the list of fields that can be updated via an [AppUpdater](./kibana-plugin-public.appupdater.md). + +Signature: + +```typescript +export declare type AppUpdatableFields = Pick; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appupdater.md b/docs/development/core/public/kibana-plugin-public.appupdater.md index f1b965cc2fc22f..75f489e6346f32 100644 --- a/docs/development/core/public/kibana-plugin-public.appupdater.md +++ b/docs/development/core/public/kibana-plugin-public.appupdater.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUpdater](./kibana-plugin-public.appupdater.md) - -## AppUpdater type - -Updater for applications. see [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) - -Signature: - -```typescript -export declare type AppUpdater = (app: AppBase) => Partial | undefined; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUpdater](./kibana-plugin-public.appupdater.md) + +## AppUpdater type + +Updater for applications. see [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) + +Signature: + +```typescript +export declare type AppUpdater = (app: AppBase) => Partial | undefined; +``` diff --git a/docs/development/core/public/kibana-plugin-public.capabilities.catalogue.md b/docs/development/core/public/kibana-plugin-public.capabilities.catalogue.md index ea3380d70053b3..8f46a42dc3b78b 100644 --- a/docs/development/core/public/kibana-plugin-public.capabilities.catalogue.md +++ b/docs/development/core/public/kibana-plugin-public.capabilities.catalogue.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Capabilities](./kibana-plugin-public.capabilities.md) > [catalogue](./kibana-plugin-public.capabilities.catalogue.md) - -## Capabilities.catalogue property - -Catalogue capabilities. Catalogue entries drive the visibility of the Kibana homepage options. - -Signature: - -```typescript -catalogue: Record; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Capabilities](./kibana-plugin-public.capabilities.md) > [catalogue](./kibana-plugin-public.capabilities.catalogue.md) + +## Capabilities.catalogue property + +Catalogue capabilities. Catalogue entries drive the visibility of the Kibana homepage options. + +Signature: + +```typescript +catalogue: Record; +``` diff --git a/docs/development/core/public/kibana-plugin-public.capabilities.management.md b/docs/development/core/public/kibana-plugin-public.capabilities.management.md index 5f4c159aef974b..59037240382b42 100644 --- a/docs/development/core/public/kibana-plugin-public.capabilities.management.md +++ b/docs/development/core/public/kibana-plugin-public.capabilities.management.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Capabilities](./kibana-plugin-public.capabilities.md) > [management](./kibana-plugin-public.capabilities.management.md) - -## Capabilities.management property - -Management section capabilities. - -Signature: - -```typescript -management: { - [sectionId: string]: Record; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Capabilities](./kibana-plugin-public.capabilities.md) > [management](./kibana-plugin-public.capabilities.management.md) + +## Capabilities.management property + +Management section capabilities. + +Signature: + +```typescript +management: { + [sectionId: string]: Record; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.capabilities.md b/docs/development/core/public/kibana-plugin-public.capabilities.md index e7dc542e6ed5ed..5a6d611f8afb70 100644 --- a/docs/development/core/public/kibana-plugin-public.capabilities.md +++ b/docs/development/core/public/kibana-plugin-public.capabilities.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Capabilities](./kibana-plugin-public.capabilities.md) - -## Capabilities interface - -The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. - -Signature: - -```typescript -export interface Capabilities -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [catalogue](./kibana-plugin-public.capabilities.catalogue.md) | Record<string, boolean> | Catalogue capabilities. Catalogue entries drive the visibility of the Kibana homepage options. | -| [management](./kibana-plugin-public.capabilities.management.md) | {
[sectionId: string]: Record<string, boolean>;
} | Management section capabilities. | -| [navLinks](./kibana-plugin-public.capabilities.navlinks.md) | Record<string, boolean> | Navigation link capabilities. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Capabilities](./kibana-plugin-public.capabilities.md) + +## Capabilities interface + +The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. + +Signature: + +```typescript +export interface Capabilities +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [catalogue](./kibana-plugin-public.capabilities.catalogue.md) | Record<string, boolean> | Catalogue capabilities. Catalogue entries drive the visibility of the Kibana homepage options. | +| [management](./kibana-plugin-public.capabilities.management.md) | {
[sectionId: string]: Record<string, boolean>;
} | Management section capabilities. | +| [navLinks](./kibana-plugin-public.capabilities.navlinks.md) | Record<string, boolean> | Navigation link capabilities. | + diff --git a/docs/development/core/public/kibana-plugin-public.capabilities.navlinks.md b/docs/development/core/public/kibana-plugin-public.capabilities.navlinks.md index a6c337ef702775..804ff1fef534ae 100644 --- a/docs/development/core/public/kibana-plugin-public.capabilities.navlinks.md +++ b/docs/development/core/public/kibana-plugin-public.capabilities.navlinks.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Capabilities](./kibana-plugin-public.capabilities.md) > [navLinks](./kibana-plugin-public.capabilities.navlinks.md) - -## Capabilities.navLinks property - -Navigation link capabilities. - -Signature: - -```typescript -navLinks: Record; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Capabilities](./kibana-plugin-public.capabilities.md) > [navLinks](./kibana-plugin-public.capabilities.navlinks.md) + +## Capabilities.navLinks property + +Navigation link capabilities. + +Signature: + +```typescript +navLinks: Record; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromebadge.icontype.md b/docs/development/core/public/kibana-plugin-public.chromebadge.icontype.md index 535b0cb627e7e9..cfb129b3f47964 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebadge.icontype.md +++ b/docs/development/core/public/kibana-plugin-public.chromebadge.icontype.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBadge](./kibana-plugin-public.chromebadge.md) > [iconType](./kibana-plugin-public.chromebadge.icontype.md) - -## ChromeBadge.iconType property - -Signature: - -```typescript -iconType?: IconType; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBadge](./kibana-plugin-public.chromebadge.md) > [iconType](./kibana-plugin-public.chromebadge.icontype.md) + +## ChromeBadge.iconType property + +Signature: + +```typescript +iconType?: IconType; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromebadge.md b/docs/development/core/public/kibana-plugin-public.chromebadge.md index 5323193dcdd0e3..b2286986926ed3 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebadge.md +++ b/docs/development/core/public/kibana-plugin-public.chromebadge.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBadge](./kibana-plugin-public.chromebadge.md) - -## ChromeBadge interface - - -Signature: - -```typescript -export interface ChromeBadge -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [iconType](./kibana-plugin-public.chromebadge.icontype.md) | IconType | | -| [text](./kibana-plugin-public.chromebadge.text.md) | string | | -| [tooltip](./kibana-plugin-public.chromebadge.tooltip.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBadge](./kibana-plugin-public.chromebadge.md) + +## ChromeBadge interface + + +Signature: + +```typescript +export interface ChromeBadge +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [iconType](./kibana-plugin-public.chromebadge.icontype.md) | IconType | | +| [text](./kibana-plugin-public.chromebadge.text.md) | string | | +| [tooltip](./kibana-plugin-public.chromebadge.tooltip.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.chromebadge.text.md b/docs/development/core/public/kibana-plugin-public.chromebadge.text.md index 5b334a8440ee2e..59c5aedeaa44ef 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebadge.text.md +++ b/docs/development/core/public/kibana-plugin-public.chromebadge.text.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBadge](./kibana-plugin-public.chromebadge.md) > [text](./kibana-plugin-public.chromebadge.text.md) - -## ChromeBadge.text property - -Signature: - -```typescript -text: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBadge](./kibana-plugin-public.chromebadge.md) > [text](./kibana-plugin-public.chromebadge.text.md) + +## ChromeBadge.text property + +Signature: + +```typescript +text: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromebadge.tooltip.md b/docs/development/core/public/kibana-plugin-public.chromebadge.tooltip.md index a1a0590cf093d9..d37fdb5bdaf30e 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebadge.tooltip.md +++ b/docs/development/core/public/kibana-plugin-public.chromebadge.tooltip.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBadge](./kibana-plugin-public.chromebadge.md) > [tooltip](./kibana-plugin-public.chromebadge.tooltip.md) - -## ChromeBadge.tooltip property - -Signature: - -```typescript -tooltip: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBadge](./kibana-plugin-public.chromebadge.md) > [tooltip](./kibana-plugin-public.chromebadge.tooltip.md) + +## ChromeBadge.tooltip property + +Signature: + +```typescript +tooltip: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromebrand.logo.md b/docs/development/core/public/kibana-plugin-public.chromebrand.logo.md index 7edbfb97fba951..99eaf8e2228552 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebrand.logo.md +++ b/docs/development/core/public/kibana-plugin-public.chromebrand.logo.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBrand](./kibana-plugin-public.chromebrand.md) > [logo](./kibana-plugin-public.chromebrand.logo.md) - -## ChromeBrand.logo property - -Signature: - -```typescript -logo?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBrand](./kibana-plugin-public.chromebrand.md) > [logo](./kibana-plugin-public.chromebrand.logo.md) + +## ChromeBrand.logo property + +Signature: + +```typescript +logo?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromebrand.md b/docs/development/core/public/kibana-plugin-public.chromebrand.md index 42af5255c00422..87c146b2b4c28e 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebrand.md +++ b/docs/development/core/public/kibana-plugin-public.chromebrand.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBrand](./kibana-plugin-public.chromebrand.md) - -## ChromeBrand interface - - -Signature: - -```typescript -export interface ChromeBrand -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [logo](./kibana-plugin-public.chromebrand.logo.md) | string | | -| [smallLogo](./kibana-plugin-public.chromebrand.smalllogo.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBrand](./kibana-plugin-public.chromebrand.md) + +## ChromeBrand interface + + +Signature: + +```typescript +export interface ChromeBrand +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [logo](./kibana-plugin-public.chromebrand.logo.md) | string | | +| [smallLogo](./kibana-plugin-public.chromebrand.smalllogo.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.chromebrand.smalllogo.md b/docs/development/core/public/kibana-plugin-public.chromebrand.smalllogo.md index 53d05ed89144ae..85c933ac5814ec 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebrand.smalllogo.md +++ b/docs/development/core/public/kibana-plugin-public.chromebrand.smalllogo.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBrand](./kibana-plugin-public.chromebrand.md) > [smallLogo](./kibana-plugin-public.chromebrand.smalllogo.md) - -## ChromeBrand.smallLogo property - -Signature: - -```typescript -smallLogo?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBrand](./kibana-plugin-public.chromebrand.md) > [smallLogo](./kibana-plugin-public.chromebrand.smalllogo.md) + +## ChromeBrand.smallLogo property + +Signature: + +```typescript +smallLogo?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md index 9350b56ce5f60e..4738487d6674a8 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md +++ b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) - -## ChromeBreadcrumb type - - -Signature: - -```typescript -export declare type ChromeBreadcrumb = EuiBreadcrumb; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) + +## ChromeBreadcrumb type + + +Signature: + +```typescript +export declare type ChromeBreadcrumb = EuiBreadcrumb; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md index eba149bf93a4c2..c132b4b54337ed 100644 --- a/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md @@ -1,34 +1,34 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [change](./kibana-plugin-public.chromedoctitle.change.md) - -## ChromeDocTitle.change() method - -Changes the current document title. - -Signature: - -```typescript -change(newTitle: string | string[]): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| newTitle | string | string[] | | - -Returns: - -`void` - -## Example - -How to change the title of the document - -```ts -chrome.docTitle.change('My application title') -chrome.docTitle.change(['My application', 'My section']) - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [change](./kibana-plugin-public.chromedoctitle.change.md) + +## ChromeDocTitle.change() method + +Changes the current document title. + +Signature: + +```typescript +change(newTitle: string | string[]): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| newTitle | string | string[] | | + +Returns: + +`void` + +## Example + +How to change the title of the document + +```ts +chrome.docTitle.change('My application title') +chrome.docTitle.change(['My application', 'My section']) + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.md index feb3b3ab966ef0..624940b612ddb2 100644 --- a/docs/development/core/public/kibana-plugin-public.chromedoctitle.md +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.md @@ -1,39 +1,39 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) - -## ChromeDocTitle interface - -APIs for accessing and updating the document title. - -Signature: - -```typescript -export interface ChromeDocTitle -``` - -## Example 1 - -How to change the title of the document - -```ts -chrome.docTitle.change('My application') - -``` - -## Example 2 - -How to reset the title of the document to it's initial value - -```ts -chrome.docTitle.reset() - -``` - -## Methods - -| Method | Description | -| --- | --- | -| [change(newTitle)](./kibana-plugin-public.chromedoctitle.change.md) | Changes the current document title. | -| [reset()](./kibana-plugin-public.chromedoctitle.reset.md) | Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) + +## ChromeDocTitle interface + +APIs for accessing and updating the document title. + +Signature: + +```typescript +export interface ChromeDocTitle +``` + +## Example 1 + +How to change the title of the document + +```ts +chrome.docTitle.change('My application') + +``` + +## Example 2 + +How to reset the title of the document to it's initial value + +```ts +chrome.docTitle.reset() + +``` + +## Methods + +| Method | Description | +| --- | --- | +| [change(newTitle)](./kibana-plugin-public.chromedoctitle.change.md) | Changes the current document title. | +| [reset()](./kibana-plugin-public.chromedoctitle.reset.md) | Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) | + diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md index 4b4c6f573e0061..97933c443125a5 100644 --- a/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [reset](./kibana-plugin-public.chromedoctitle.reset.md) - -## ChromeDocTitle.reset() method - -Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) - -Signature: - -```typescript -reset(): void; -``` -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [reset](./kibana-plugin-public.chromedoctitle.reset.md) + +## ChromeDocTitle.reset() method + +Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) + +Signature: + +```typescript +reset(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md index d817238c9287d3..e5bb6c19a807ba 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [appName](./kibana-plugin-public.chromehelpextension.appname.md) - -## ChromeHelpExtension.appName property - -Provide your plugin's name to create a header for separation - -Signature: - -```typescript -appName: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [appName](./kibana-plugin-public.chromehelpextension.appname.md) + +## ChromeHelpExtension.appName property + +Provide your plugin's name to create a header for separation + +Signature: + +```typescript +appName: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md index b51d4928e991dc..b9b38dc20774f3 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [content](./kibana-plugin-public.chromehelpextension.content.md) - -## ChromeHelpExtension.content property - -Custom content to occur below the list of links - -Signature: - -```typescript -content?: (element: HTMLDivElement) => () => void; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [content](./kibana-plugin-public.chromehelpextension.content.md) + +## ChromeHelpExtension.content property + +Custom content to occur below the list of links + +Signature: + +```typescript +content?: (element: HTMLDivElement) => () => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md index de17ca8d86e379..76e805eb993ad5 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [links](./kibana-plugin-public.chromehelpextension.links.md) - -## ChromeHelpExtension.links property - -Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button - -Signature: - -```typescript -links?: ChromeHelpExtensionMenuLink[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [links](./kibana-plugin-public.chromehelpextension.links.md) + +## ChromeHelpExtension.links property + +Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button + +Signature: + +```typescript +links?: ChromeHelpExtensionMenuLink[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.md index 6f0007335c5558..4c870ef9afba04 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextension.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) - -## ChromeHelpExtension interface - - -Signature: - -```typescript -export interface ChromeHelpExtension -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [appName](./kibana-plugin-public.chromehelpextension.appname.md) | string | Provide your plugin's name to create a header for separation | -| [content](./kibana-plugin-public.chromehelpextension.content.md) | (element: HTMLDivElement) => () => void | Custom content to occur below the list of links | -| [links](./kibana-plugin-public.chromehelpextension.links.md) | ChromeHelpExtensionMenuLink[] | Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) + +## ChromeHelpExtension interface + + +Signature: + +```typescript +export interface ChromeHelpExtension +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [appName](./kibana-plugin-public.chromehelpextension.appname.md) | string | Provide your plugin's name to create a header for separation | +| [content](./kibana-plugin-public.chromehelpextension.content.md) | (element: HTMLDivElement) => () => void | Custom content to occur below the list of links | +| [links](./kibana-plugin-public.chromehelpextension.links.md) | ChromeHelpExtensionMenuLink[] | Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button | + diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md index daca70f3b79c1e..3eed2ad36dc034 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) - -## ChromeHelpExtensionMenuCustomLink type - - -Signature: - -```typescript -export declare type ChromeHelpExtensionMenuCustomLink = EuiButtonEmptyProps & { - linkType: 'custom'; - content: React.ReactNode; -}; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) + +## ChromeHelpExtensionMenuCustomLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuCustomLink = EuiButtonEmptyProps & { + linkType: 'custom'; + content: React.ReactNode; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md index 8dd1c796bebf17..3885712ce94205 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) - -## ChromeHelpExtensionMenuDiscussLink type - - -Signature: - -```typescript -export declare type ChromeHelpExtensionMenuDiscussLink = EuiButtonEmptyProps & { - linkType: 'discuss'; - href: string; -}; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) + +## ChromeHelpExtensionMenuDiscussLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuDiscussLink = EuiButtonEmptyProps & { + linkType: 'discuss'; + href: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md index 0114cc245a8747..25ea1690154c2a 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) - -## ChromeHelpExtensionMenuDocumentationLink type - - -Signature: - -```typescript -export declare type ChromeHelpExtensionMenuDocumentationLink = EuiButtonEmptyProps & { - linkType: 'documentation'; - href: string; -}; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) + +## ChromeHelpExtensionMenuDocumentationLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuDocumentationLink = EuiButtonEmptyProps & { + linkType: 'documentation'; + href: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md index 5dd33f1a05a7fa..2dc1b5b4cee5ba 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) - -## ChromeHelpExtensionMenuGitHubLink type - - -Signature: - -```typescript -export declare type ChromeHelpExtensionMenuGitHubLink = EuiButtonEmptyProps & { - linkType: 'github'; - labels: string[]; - title?: string; -}; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) + +## ChromeHelpExtensionMenuGitHubLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuGitHubLink = EuiButtonEmptyProps & { + linkType: 'github'; + labels: string[]; + title?: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md index 072ce165e23c5e..ce55fdedab1555 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) - -## ChromeHelpExtensionMenuLink type - - -Signature: - -```typescript -export declare type ChromeHelpExtensionMenuLink = ExclusiveUnion>>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) + +## ChromeHelpExtensionMenuLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuLink = ExclusiveUnion>>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavcontrol.md b/docs/development/core/public/kibana-plugin-public.chromenavcontrol.md index fdf56012e4729c..afaef974117740 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavcontrol.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavcontrol.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) - -## ChromeNavControl interface - - -Signature: - -```typescript -export interface ChromeNavControl -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [mount](./kibana-plugin-public.chromenavcontrol.mount.md) | MountPoint | | -| [order](./kibana-plugin-public.chromenavcontrol.order.md) | number | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) + +## ChromeNavControl interface + + +Signature: + +```typescript +export interface ChromeNavControl +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [mount](./kibana-plugin-public.chromenavcontrol.mount.md) | MountPoint | | +| [order](./kibana-plugin-public.chromenavcontrol.order.md) | number | | + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavcontrol.mount.md b/docs/development/core/public/kibana-plugin-public.chromenavcontrol.mount.md index 3e1f5a1f78f89b..6d574900fd16ae 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavcontrol.mount.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavcontrol.mount.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) > [mount](./kibana-plugin-public.chromenavcontrol.mount.md) - -## ChromeNavControl.mount property - -Signature: - -```typescript -mount: MountPoint; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) > [mount](./kibana-plugin-public.chromenavcontrol.mount.md) + +## ChromeNavControl.mount property + +Signature: + +```typescript +mount: MountPoint; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavcontrol.order.md b/docs/development/core/public/kibana-plugin-public.chromenavcontrol.order.md index 22e84cebab63ab..10ad35c602d219 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavcontrol.order.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavcontrol.order.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) > [order](./kibana-plugin-public.chromenavcontrol.order.md) - -## ChromeNavControl.order property - -Signature: - -```typescript -order?: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) > [order](./kibana-plugin-public.chromenavcontrol.order.md) + +## ChromeNavControl.order property + +Signature: + +```typescript +order?: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavcontrols.md b/docs/development/core/public/kibana-plugin-public.chromenavcontrols.md index 30b9a6869d1ff7..f70e63ff0f2c27 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavcontrols.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavcontrols.md @@ -1,35 +1,35 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) - -## ChromeNavControls interface - -[APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. - -Signature: - -```typescript -export interface ChromeNavControls -``` - -## Example - -Register a left-side nav control rendered with React. - -```jsx -chrome.navControls.registerLeft({ - mount(targetDomElement) { - ReactDOM.mount(, targetDomElement); - return () => ReactDOM.unmountComponentAtNode(targetDomElement); - } -}) - -``` - -## Methods - -| Method | Description | -| --- | --- | -| [registerLeft(navControl)](./kibana-plugin-public.chromenavcontrols.registerleft.md) | Register a nav control to be presented on the left side of the chrome header. | -| [registerRight(navControl)](./kibana-plugin-public.chromenavcontrols.registerright.md) | Register a nav control to be presented on the right side of the chrome header. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) + +## ChromeNavControls interface + +[APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. + +Signature: + +```typescript +export interface ChromeNavControls +``` + +## Example + +Register a left-side nav control rendered with React. + +```jsx +chrome.navControls.registerLeft({ + mount(targetDomElement) { + ReactDOM.mount(, targetDomElement); + return () => ReactDOM.unmountComponentAtNode(targetDomElement); + } +}) + +``` + +## Methods + +| Method | Description | +| --- | --- | +| [registerLeft(navControl)](./kibana-plugin-public.chromenavcontrols.registerleft.md) | Register a nav control to be presented on the left side of the chrome header. | +| [registerRight(navControl)](./kibana-plugin-public.chromenavcontrols.registerright.md) | Register a nav control to be presented on the right side of the chrome header. | + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavcontrols.registerleft.md b/docs/development/core/public/kibana-plugin-public.chromenavcontrols.registerleft.md index 31867991fc0410..72cf45deaa52f3 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavcontrols.registerleft.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavcontrols.registerleft.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) > [registerLeft](./kibana-plugin-public.chromenavcontrols.registerleft.md) - -## ChromeNavControls.registerLeft() method - -Register a nav control to be presented on the left side of the chrome header. - -Signature: - -```typescript -registerLeft(navControl: ChromeNavControl): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| navControl | ChromeNavControl | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) > [registerLeft](./kibana-plugin-public.chromenavcontrols.registerleft.md) + +## ChromeNavControls.registerLeft() method + +Register a nav control to be presented on the left side of the chrome header. + +Signature: + +```typescript +registerLeft(navControl: ChromeNavControl): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| navControl | ChromeNavControl | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavcontrols.registerright.md b/docs/development/core/public/kibana-plugin-public.chromenavcontrols.registerright.md index a6c17803561b28..6e5dab83e6b53f 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavcontrols.registerright.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavcontrols.registerright.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) > [registerRight](./kibana-plugin-public.chromenavcontrols.registerright.md) - -## ChromeNavControls.registerRight() method - -Register a nav control to be presented on the right side of the chrome header. - -Signature: - -```typescript -registerRight(navControl: ChromeNavControl): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| navControl | ChromeNavControl | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) > [registerRight](./kibana-plugin-public.chromenavcontrols.registerright.md) + +## ChromeNavControls.registerRight() method + +Register a nav control to be presented on the right side of the chrome header. + +Signature: + +```typescript +registerRight(navControl: ChromeNavControl): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| navControl | ChromeNavControl | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.active.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.active.md index 9cb278916dc4a0..115dadaaeb31a5 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.active.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.active.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [active](./kibana-plugin-public.chromenavlink.active.md) - -## ChromeNavLink.active property - -> Warning: This API is now obsolete. -> -> - -Indicates whether or not this app is currently on the screen. - -Signature: - -```typescript -readonly active?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [active](./kibana-plugin-public.chromenavlink.active.md) + +## ChromeNavLink.active property + +> Warning: This API is now obsolete. +> +> + +Indicates whether or not this app is currently on the screen. + +Signature: + +```typescript +readonly active?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.baseurl.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.baseurl.md index 780a17617be049..995cf040d9b80e 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.baseurl.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.baseurl.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [baseUrl](./kibana-plugin-public.chromenavlink.baseurl.md) - -## ChromeNavLink.baseUrl property - -The base route used to open the root of an application. - -Signature: - -```typescript -readonly baseUrl: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [baseUrl](./kibana-plugin-public.chromenavlink.baseurl.md) + +## ChromeNavLink.baseUrl property + +The base route used to open the root of an application. + +Signature: + +```typescript +readonly baseUrl: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.category.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.category.md new file mode 100644 index 00000000000000..231bbcddc16c47 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.category.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [category](./kibana-plugin-public.chromenavlink.category.md) + +## ChromeNavLink.category property + +The category the app lives in + +Signature: + +```typescript +readonly category?: AppCategory; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.disabled.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.disabled.md index d2b30530dd5516..c232b095d4047a 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.disabled.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.disabled.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [disabled](./kibana-plugin-public.chromenavlink.disabled.md) - -## ChromeNavLink.disabled property - -> Warning: This API is now obsolete. -> -> - -Disables a link from being clickable. - -Signature: - -```typescript -readonly disabled?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [disabled](./kibana-plugin-public.chromenavlink.disabled.md) + +## ChromeNavLink.disabled property + +> Warning: This API is now obsolete. +> +> + +Disables a link from being clickable. + +Signature: + +```typescript +readonly disabled?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.euiicontype.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.euiicontype.md index 5373e4705d1b3e..2c9f872a97ff26 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.euiicontype.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.euiicontype.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [euiIconType](./kibana-plugin-public.chromenavlink.euiicontype.md) - -## ChromeNavLink.euiIconType property - -A EUI iconType that will be used for the app's icon. This icon takes precendence over the `icon` property. - -Signature: - -```typescript -readonly euiIconType?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [euiIconType](./kibana-plugin-public.chromenavlink.euiicontype.md) + +## ChromeNavLink.euiIconType property + +A EUI iconType that will be used for the app's icon. This icon takes precendence over the `icon` property. + +Signature: + +```typescript +readonly euiIconType?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.hidden.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.hidden.md index 6d04ab6d788517..e3071ce3f161e9 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.hidden.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.hidden.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [hidden](./kibana-plugin-public.chromenavlink.hidden.md) - -## ChromeNavLink.hidden property - -Hides a link from the navigation. - -Signature: - -```typescript -readonly hidden?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [hidden](./kibana-plugin-public.chromenavlink.hidden.md) + +## ChromeNavLink.hidden property + +Hides a link from the navigation. + +Signature: + +```typescript +readonly hidden?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.icon.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.icon.md index dadb2ab0446406..0bad3ba8e192d1 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.icon.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.icon.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [icon](./kibana-plugin-public.chromenavlink.icon.md) - -## ChromeNavLink.icon property - -A URL to an image file used as an icon. Used as a fallback if `euiIconType` is not provided. - -Signature: - -```typescript -readonly icon?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [icon](./kibana-plugin-public.chromenavlink.icon.md) + +## ChromeNavLink.icon property + +A URL to an image file used as an icon. Used as a fallback if `euiIconType` is not provided. + +Signature: + +```typescript +readonly icon?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.id.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.id.md index 7fbabc4a420329..a06a9465d19d10 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.id.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [id](./kibana-plugin-public.chromenavlink.id.md) - -## ChromeNavLink.id property - -A unique identifier for looking up links. - -Signature: - -```typescript -readonly id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [id](./kibana-plugin-public.chromenavlink.id.md) + +## ChromeNavLink.id property + +A unique identifier for looking up links. + +Signature: + +```typescript +readonly id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.linktolastsuburl.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.linktolastsuburl.md index 7d76f4dc62be4b..826762a29c30fd 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.linktolastsuburl.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.linktolastsuburl.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [linkToLastSubUrl](./kibana-plugin-public.chromenavlink.linktolastsuburl.md) - -## ChromeNavLink.linkToLastSubUrl property - -> Warning: This API is now obsolete. -> -> - -Whether or not the subUrl feature should be enabled. - -Signature: - -```typescript -readonly linkToLastSubUrl?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [linkToLastSubUrl](./kibana-plugin-public.chromenavlink.linktolastsuburl.md) + +## ChromeNavLink.linkToLastSubUrl property + +> Warning: This API is now obsolete. +> +> + +Whether or not the subUrl feature should be enabled. + +Signature: + +```typescript +readonly linkToLastSubUrl?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.md index 4cb9080222ac54..7e7849b1a1358c 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.md @@ -1,31 +1,32 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) - -## ChromeNavLink interface - - -Signature: - -```typescript -export interface ChromeNavLink -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [active](./kibana-plugin-public.chromenavlink.active.md) | boolean | Indicates whether or not this app is currently on the screen. | -| [baseUrl](./kibana-plugin-public.chromenavlink.baseurl.md) | string | The base route used to open the root of an application. | -| [disabled](./kibana-plugin-public.chromenavlink.disabled.md) | boolean | Disables a link from being clickable. | -| [euiIconType](./kibana-plugin-public.chromenavlink.euiicontype.md) | string | A EUI iconType that will be used for the app's icon. This icon takes precendence over the icon property. | -| [hidden](./kibana-plugin-public.chromenavlink.hidden.md) | boolean | Hides a link from the navigation. | -| [icon](./kibana-plugin-public.chromenavlink.icon.md) | string | A URL to an image file used as an icon. Used as a fallback if euiIconType is not provided. | -| [id](./kibana-plugin-public.chromenavlink.id.md) | string | A unique identifier for looking up links. | -| [linkToLastSubUrl](./kibana-plugin-public.chromenavlink.linktolastsuburl.md) | boolean | Whether or not the subUrl feature should be enabled. | -| [order](./kibana-plugin-public.chromenavlink.order.md) | number | An ordinal used to sort nav links relative to one another for display. | -| [subUrlBase](./kibana-plugin-public.chromenavlink.suburlbase.md) | string | A url base that legacy apps can set to match deep URLs to an application. | -| [title](./kibana-plugin-public.chromenavlink.title.md) | string | The title of the application. | -| [tooltip](./kibana-plugin-public.chromenavlink.tooltip.md) | string | A tooltip shown when hovering over an app link. | -| [url](./kibana-plugin-public.chromenavlink.url.md) | string | A url that legacy apps can set to deep link into their applications. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) + +## ChromeNavLink interface + + +Signature: + +```typescript +export interface ChromeNavLink +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [active](./kibana-plugin-public.chromenavlink.active.md) | boolean | Indicates whether or not this app is currently on the screen. | +| [baseUrl](./kibana-plugin-public.chromenavlink.baseurl.md) | string | The base route used to open the root of an application. | +| [category](./kibana-plugin-public.chromenavlink.category.md) | AppCategory | The category the app lives in | +| [disabled](./kibana-plugin-public.chromenavlink.disabled.md) | boolean | Disables a link from being clickable. | +| [euiIconType](./kibana-plugin-public.chromenavlink.euiicontype.md) | string | A EUI iconType that will be used for the app's icon. This icon takes precendence over the icon property. | +| [hidden](./kibana-plugin-public.chromenavlink.hidden.md) | boolean | Hides a link from the navigation. | +| [icon](./kibana-plugin-public.chromenavlink.icon.md) | string | A URL to an image file used as an icon. Used as a fallback if euiIconType is not provided. | +| [id](./kibana-plugin-public.chromenavlink.id.md) | string | A unique identifier for looking up links. | +| [linkToLastSubUrl](./kibana-plugin-public.chromenavlink.linktolastsuburl.md) | boolean | Whether or not the subUrl feature should be enabled. | +| [order](./kibana-plugin-public.chromenavlink.order.md) | number | An ordinal used to sort nav links relative to one another for display. | +| [subUrlBase](./kibana-plugin-public.chromenavlink.suburlbase.md) | string | A url base that legacy apps can set to match deep URLs to an application. | +| [title](./kibana-plugin-public.chromenavlink.title.md) | string | The title of the application. | +| [tooltip](./kibana-plugin-public.chromenavlink.tooltip.md) | string | A tooltip shown when hovering over an app link. | +| [url](./kibana-plugin-public.chromenavlink.url.md) | string | A url that legacy apps can set to deep link into their applications. | + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.order.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.order.md index 1fef9fc1dc359d..6716d4ce8668d8 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.order.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.order.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [order](./kibana-plugin-public.chromenavlink.order.md) - -## ChromeNavLink.order property - -An ordinal used to sort nav links relative to one another for display. - -Signature: - -```typescript -readonly order?: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [order](./kibana-plugin-public.chromenavlink.order.md) + +## ChromeNavLink.order property + +An ordinal used to sort nav links relative to one another for display. + +Signature: + +```typescript +readonly order?: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.suburlbase.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.suburlbase.md index 1b8fb0574cf8be..055b39e996880f 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.suburlbase.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.suburlbase.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [subUrlBase](./kibana-plugin-public.chromenavlink.suburlbase.md) - -## ChromeNavLink.subUrlBase property - -> Warning: This API is now obsolete. -> -> - -A url base that legacy apps can set to match deep URLs to an application. - -Signature: - -```typescript -readonly subUrlBase?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [subUrlBase](./kibana-plugin-public.chromenavlink.suburlbase.md) + +## ChromeNavLink.subUrlBase property + +> Warning: This API is now obsolete. +> +> + +A url base that legacy apps can set to match deep URLs to an application. + +Signature: + +```typescript +readonly subUrlBase?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.title.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.title.md index a693b971d51785..6129165a0bce1c 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.title.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.title.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [title](./kibana-plugin-public.chromenavlink.title.md) - -## ChromeNavLink.title property - -The title of the application. - -Signature: - -```typescript -readonly title: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [title](./kibana-plugin-public.chromenavlink.title.md) + +## ChromeNavLink.title property + +The title of the application. + +Signature: + +```typescript +readonly title: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.tooltip.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.tooltip.md index e1ff92d8d74427..4df513f9866806 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.tooltip.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.tooltip.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [tooltip](./kibana-plugin-public.chromenavlink.tooltip.md) - -## ChromeNavLink.tooltip property - -A tooltip shown when hovering over an app link. - -Signature: - -```typescript -readonly tooltip?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [tooltip](./kibana-plugin-public.chromenavlink.tooltip.md) + +## ChromeNavLink.tooltip property + +A tooltip shown when hovering over an app link. + +Signature: + +```typescript +readonly tooltip?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.url.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.url.md index 33bd8fa3411d41..d8589cf3e52238 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.url.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.url.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [url](./kibana-plugin-public.chromenavlink.url.md) - -## ChromeNavLink.url property - -> Warning: This API is now obsolete. -> -> - -A url that legacy apps can set to deep link into their applications. - -Signature: - -```typescript -readonly url?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) > [url](./kibana-plugin-public.chromenavlink.url.md) + +## ChromeNavLink.url property + +> Warning: This API is now obsolete. +> +> + +A url that legacy apps can set to deep link into their applications. + +Signature: + +```typescript +readonly url?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinks.enableforcedappswitchernavigation.md b/docs/development/core/public/kibana-plugin-public.chromenavlinks.enableforcedappswitchernavigation.md index 3a057f096959a3..768b3a977928ac 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinks.enableforcedappswitchernavigation.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinks.enableforcedappswitchernavigation.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [enableForcedAppSwitcherNavigation](./kibana-plugin-public.chromenavlinks.enableforcedappswitchernavigation.md) - -## ChromeNavLinks.enableForcedAppSwitcherNavigation() method - -Enable forced navigation mode, which will trigger a page refresh when a nav link is clicked and only the hash is updated. - -Signature: - -```typescript -enableForcedAppSwitcherNavigation(): void; -``` -Returns: - -`void` - -## Remarks - -This is only necessary when rendering the status page in place of another app, as links to that app will set the current URL and change the hash, but the routes for the correct are not loaded so nothing will happen. https://github.com/elastic/kibana/pull/29770 - -Used only by status\_page plugin - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [enableForcedAppSwitcherNavigation](./kibana-plugin-public.chromenavlinks.enableforcedappswitchernavigation.md) + +## ChromeNavLinks.enableForcedAppSwitcherNavigation() method + +Enable forced navigation mode, which will trigger a page refresh when a nav link is clicked and only the hash is updated. + +Signature: + +```typescript +enableForcedAppSwitcherNavigation(): void; +``` +Returns: + +`void` + +## Remarks + +This is only necessary when rendering the status page in place of another app, as links to that app will set the current URL and change the hash, but the routes for the correct are not loaded so nothing will happen. https://github.com/elastic/kibana/pull/29770 + +Used only by status\_page plugin + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinks.get.md b/docs/development/core/public/kibana-plugin-public.chromenavlinks.get.md index fb20c3eaeb43af..3018a31ea43fab 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinks.get.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinks.get.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [get](./kibana-plugin-public.chromenavlinks.get.md) - -## ChromeNavLinks.get() method - -Get the state of a navlink at this point in time. - -Signature: - -```typescript -get(id: string): ChromeNavLink | undefined; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| id | string | | - -Returns: - -`ChromeNavLink | undefined` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [get](./kibana-plugin-public.chromenavlinks.get.md) + +## ChromeNavLinks.get() method + +Get the state of a navlink at this point in time. + +Signature: + +```typescript +get(id: string): ChromeNavLink | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`ChromeNavLink | undefined` + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinks.getall.md b/docs/development/core/public/kibana-plugin-public.chromenavlinks.getall.md index b483ba485139ed..c80cf764927f56 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinks.getall.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinks.getall.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [getAll](./kibana-plugin-public.chromenavlinks.getall.md) - -## ChromeNavLinks.getAll() method - -Get the current state of all navlinks. - -Signature: - -```typescript -getAll(): Array>; -``` -Returns: - -`Array>` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [getAll](./kibana-plugin-public.chromenavlinks.getall.md) + +## ChromeNavLinks.getAll() method + +Get the current state of all navlinks. + +Signature: + +```typescript +getAll(): Array>; +``` +Returns: + +`Array>` + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinks.getforceappswitchernavigation_.md b/docs/development/core/public/kibana-plugin-public.chromenavlinks.getforceappswitchernavigation_.md index f31e30fbda3faa..3f8cf7118172ef 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinks.getforceappswitchernavigation_.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinks.getforceappswitchernavigation_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [getForceAppSwitcherNavigation$](./kibana-plugin-public.chromenavlinks.getforceappswitchernavigation_.md) - -## ChromeNavLinks.getForceAppSwitcherNavigation$() method - -An observable of the forced app switcher state. - -Signature: - -```typescript -getForceAppSwitcherNavigation$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [getForceAppSwitcherNavigation$](./kibana-plugin-public.chromenavlinks.getforceappswitchernavigation_.md) + +## ChromeNavLinks.getForceAppSwitcherNavigation$() method + +An observable of the forced app switcher state. + +Signature: + +```typescript +getForceAppSwitcherNavigation$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinks.getnavlinks_.md b/docs/development/core/public/kibana-plugin-public.chromenavlinks.getnavlinks_.md index c455b1c6c1446d..628544c2b00814 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinks.getnavlinks_.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinks.getnavlinks_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [getNavLinks$](./kibana-plugin-public.chromenavlinks.getnavlinks_.md) - -## ChromeNavLinks.getNavLinks$() method - -Get an observable for a sorted list of navlinks. - -Signature: - -```typescript -getNavLinks$(): Observable>>; -``` -Returns: - -`Observable>>` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [getNavLinks$](./kibana-plugin-public.chromenavlinks.getnavlinks_.md) + +## ChromeNavLinks.getNavLinks$() method + +Get an observable for a sorted list of navlinks. + +Signature: + +```typescript +getNavLinks$(): Observable>>; +``` +Returns: + +`Observable>>` + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinks.has.md b/docs/development/core/public/kibana-plugin-public.chromenavlinks.has.md index 6deb57d9548c60..9f0267a3d09d49 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinks.has.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinks.has.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [has](./kibana-plugin-public.chromenavlinks.has.md) - -## ChromeNavLinks.has() method - -Check whether or not a navlink exists. - -Signature: - -```typescript -has(id: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| id | string | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [has](./kibana-plugin-public.chromenavlinks.has.md) + +## ChromeNavLinks.has() method + +Check whether or not a navlink exists. + +Signature: + +```typescript +has(id: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinks.md b/docs/development/core/public/kibana-plugin-public.chromenavlinks.md index 280277911c6958..3a8222c97cd97c 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinks.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinks.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) - -## ChromeNavLinks interface - -[APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. - -Signature: - -```typescript -export interface ChromeNavLinks -``` - -## Methods - -| Method | Description | -| --- | --- | -| [enableForcedAppSwitcherNavigation()](./kibana-plugin-public.chromenavlinks.enableforcedappswitchernavigation.md) | Enable forced navigation mode, which will trigger a page refresh when a nav link is clicked and only the hash is updated. | -| [get(id)](./kibana-plugin-public.chromenavlinks.get.md) | Get the state of a navlink at this point in time. | -| [getAll()](./kibana-plugin-public.chromenavlinks.getall.md) | Get the current state of all navlinks. | -| [getForceAppSwitcherNavigation$()](./kibana-plugin-public.chromenavlinks.getforceappswitchernavigation_.md) | An observable of the forced app switcher state. | -| [getNavLinks$()](./kibana-plugin-public.chromenavlinks.getnavlinks_.md) | Get an observable for a sorted list of navlinks. | -| [has(id)](./kibana-plugin-public.chromenavlinks.has.md) | Check whether or not a navlink exists. | -| [showOnly(id)](./kibana-plugin-public.chromenavlinks.showonly.md) | Remove all navlinks except the one matching the given id. | -| [update(id, values)](./kibana-plugin-public.chromenavlinks.update.md) | Update the navlink for the given id with the updated attributes. Returns the updated navlink or undefined if it does not exist. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) + +## ChromeNavLinks interface + +[APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. + +Signature: + +```typescript +export interface ChromeNavLinks +``` + +## Methods + +| Method | Description | +| --- | --- | +| [enableForcedAppSwitcherNavigation()](./kibana-plugin-public.chromenavlinks.enableforcedappswitchernavigation.md) | Enable forced navigation mode, which will trigger a page refresh when a nav link is clicked and only the hash is updated. | +| [get(id)](./kibana-plugin-public.chromenavlinks.get.md) | Get the state of a navlink at this point in time. | +| [getAll()](./kibana-plugin-public.chromenavlinks.getall.md) | Get the current state of all navlinks. | +| [getForceAppSwitcherNavigation$()](./kibana-plugin-public.chromenavlinks.getforceappswitchernavigation_.md) | An observable of the forced app switcher state. | +| [getNavLinks$()](./kibana-plugin-public.chromenavlinks.getnavlinks_.md) | Get an observable for a sorted list of navlinks. | +| [has(id)](./kibana-plugin-public.chromenavlinks.has.md) | Check whether or not a navlink exists. | +| [showOnly(id)](./kibana-plugin-public.chromenavlinks.showonly.md) | Remove all navlinks except the one matching the given id. | +| [update(id, values)](./kibana-plugin-public.chromenavlinks.update.md) | Update the navlink for the given id with the updated attributes. Returns the updated navlink or undefined if it does not exist. | + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinks.showonly.md b/docs/development/core/public/kibana-plugin-public.chromenavlinks.showonly.md index 0fdb0bba0faa89..3746f3491844bb 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinks.showonly.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinks.showonly.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [showOnly](./kibana-plugin-public.chromenavlinks.showonly.md) - -## ChromeNavLinks.showOnly() method - -Remove all navlinks except the one matching the given id. - -Signature: - -```typescript -showOnly(id: string): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| id | string | | - -Returns: - -`void` - -## Remarks - -NOTE: this is not reversible. - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) > [showOnly](./kibana-plugin-public.chromenavlinks.showonly.md) + +## ChromeNavLinks.showOnly() method + +Remove all navlinks except the one matching the given id. + +Signature: + +```typescript +showOnly(id: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`void` + +## Remarks + +NOTE: this is not reversible. + diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlinkupdateablefields.md b/docs/development/core/public/kibana-plugin-public.chromenavlinkupdateablefields.md index f8be488c170a24..6b17174975db92 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlinkupdateablefields.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlinkupdateablefields.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) - -## ChromeNavLinkUpdateableFields type - - -Signature: - -```typescript -export declare type ChromeNavLinkUpdateableFields = Partial>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) + +## ChromeNavLinkUpdateableFields type + + +Signature: + +```typescript +export declare type ChromeNavLinkUpdateableFields = Partial>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.add.md b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.add.md index 428f9a0d990bcd..8d780f3c5d5371 100644 --- a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.add.md +++ b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.add.md @@ -1,34 +1,34 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) > [add](./kibana-plugin-public.chromerecentlyaccessed.add.md) - -## ChromeRecentlyAccessed.add() method - -Adds a new item to the recently accessed history. - -Signature: - -```typescript -add(link: string, label: string, id: string): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| link | string | | -| label | string | | -| id | string | | - -Returns: - -`void` - -## Example - - -```js -chrome.recentlyAccessed.add('/app/map/1234', 'Map 1234', '1234'); - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) > [add](./kibana-plugin-public.chromerecentlyaccessed.add.md) + +## ChromeRecentlyAccessed.add() method + +Adds a new item to the recently accessed history. + +Signature: + +```typescript +add(link: string, label: string, id: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| link | string | | +| label | string | | +| id | string | | + +Returns: + +`void` + +## Example + + +```js +chrome.recentlyAccessed.add('/app/map/1234', 'Map 1234', '1234'); + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.get.md b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.get.md index 39f2ac6003a576..b176abb44a002e 100644 --- a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.get.md +++ b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.get.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) > [get](./kibana-plugin-public.chromerecentlyaccessed.get.md) - -## ChromeRecentlyAccessed.get() method - -Gets an Array of the current recently accessed history. - -Signature: - -```typescript -get(): ChromeRecentlyAccessedHistoryItem[]; -``` -Returns: - -`ChromeRecentlyAccessedHistoryItem[]` - -## Example - - -```js -chrome.recentlyAccessed.get().forEach(console.log); - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) > [get](./kibana-plugin-public.chromerecentlyaccessed.get.md) + +## ChromeRecentlyAccessed.get() method + +Gets an Array of the current recently accessed history. + +Signature: + +```typescript +get(): ChromeRecentlyAccessedHistoryItem[]; +``` +Returns: + +`ChromeRecentlyAccessedHistoryItem[]` + +## Example + + +```js +chrome.recentlyAccessed.get().forEach(console.log); + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.get_.md b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.get_.md index 92452b185d6733..d6b4e9f6b4f915 100644 --- a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.get_.md +++ b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.get_.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) > [get$](./kibana-plugin-public.chromerecentlyaccessed.get_.md) - -## ChromeRecentlyAccessed.get$() method - -Gets an Observable of the array of recently accessed history. - -Signature: - -```typescript -get$(): Observable; -``` -Returns: - -`Observable` - -## Example - - -```js -chrome.recentlyAccessed.get$().subscribe(console.log); - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) > [get$](./kibana-plugin-public.chromerecentlyaccessed.get_.md) + +## ChromeRecentlyAccessed.get$() method + +Gets an Observable of the array of recently accessed history. + +Signature: + +```typescript +get$(): Observable; +``` +Returns: + +`Observable` + +## Example + + +```js +chrome.recentlyAccessed.get$().subscribe(console.log); + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.md b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.md index 014435b6bc6ef8..ed395ae3e7a0e9 100644 --- a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.md +++ b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) - -## ChromeRecentlyAccessed interface - -[APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. - -Signature: - -```typescript -export interface ChromeRecentlyAccessed -``` - -## Methods - -| Method | Description | -| --- | --- | -| [add(link, label, id)](./kibana-plugin-public.chromerecentlyaccessed.add.md) | Adds a new item to the recently accessed history. | -| [get()](./kibana-plugin-public.chromerecentlyaccessed.get.md) | Gets an Array of the current recently accessed history. | -| [get$()](./kibana-plugin-public.chromerecentlyaccessed.get_.md) | Gets an Observable of the array of recently accessed history. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) + +## ChromeRecentlyAccessed interface + +[APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. + +Signature: + +```typescript +export interface ChromeRecentlyAccessed +``` + +## Methods + +| Method | Description | +| --- | --- | +| [add(link, label, id)](./kibana-plugin-public.chromerecentlyaccessed.add.md) | Adds a new item to the recently accessed history. | +| [get()](./kibana-plugin-public.chromerecentlyaccessed.get.md) | Gets an Array of the current recently accessed history. | +| [get$()](./kibana-plugin-public.chromerecentlyaccessed.get_.md) | Gets an Observable of the array of recently accessed history. | + diff --git a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.id.md b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.id.md index b95ac60ce91dfb..ea35caaae183b8 100644 --- a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.id.md +++ b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) > [id](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.id.md) - -## ChromeRecentlyAccessedHistoryItem.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) > [id](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.id.md) + +## ChromeRecentlyAccessedHistoryItem.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.label.md b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.label.md index 2d289ad1687212..6649890acfd0df 100644 --- a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.label.md +++ b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.label.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) > [label](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.label.md) - -## ChromeRecentlyAccessedHistoryItem.label property - -Signature: - -```typescript -label: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) > [label](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.label.md) + +## ChromeRecentlyAccessedHistoryItem.label property + +Signature: + +```typescript +label: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.link.md b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.link.md index 3123d6a5e0d79f..ef4c494474c885 100644 --- a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.link.md +++ b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.link.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) > [link](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.link.md) - -## ChromeRecentlyAccessedHistoryItem.link property - -Signature: - -```typescript -link: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) > [link](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.link.md) + +## ChromeRecentlyAccessedHistoryItem.link property + +Signature: + +```typescript +link: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.md b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.md index 1f74608e4e0f53..6c526296f12788 100644 --- a/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.md +++ b/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessedhistoryitem.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) - -## ChromeRecentlyAccessedHistoryItem interface - - -Signature: - -```typescript -export interface ChromeRecentlyAccessedHistoryItem -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [id](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.id.md) | string | | -| [label](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.label.md) | string | | -| [link](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.link.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) + +## ChromeRecentlyAccessedHistoryItem interface + + +Signature: + +```typescript +export interface ChromeRecentlyAccessedHistoryItem +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.id.md) | string | | +| [label](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.label.md) | string | | +| [link](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.link.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.addapplicationclass.md b/docs/development/core/public/kibana-plugin-public.chromestart.addapplicationclass.md index b74542014b89ca..31729f6320d130 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.addapplicationclass.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.addapplicationclass.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [addApplicationClass](./kibana-plugin-public.chromestart.addapplicationclass.md) - -## ChromeStart.addApplicationClass() method - -Add a className that should be set on the application container. - -Signature: - -```typescript -addApplicationClass(className: string): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| className | string | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [addApplicationClass](./kibana-plugin-public.chromestart.addapplicationclass.md) + +## ChromeStart.addApplicationClass() method + +Add a className that should be set on the application container. + +Signature: + +```typescript +addApplicationClass(className: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| className | string | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md b/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md index 71eda64c24646e..100afe2ae0c6e7 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [docTitle](./kibana-plugin-public.chromestart.doctitle.md) - -## ChromeStart.docTitle property - -APIs for accessing and updating the document title. - -Signature: - -```typescript -docTitle: ChromeDocTitle; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [docTitle](./kibana-plugin-public.chromestart.doctitle.md) + +## ChromeStart.docTitle property + +APIs for accessing and updating the document title. + +Signature: + +```typescript +docTitle: ChromeDocTitle; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.getapplicationclasses_.md b/docs/development/core/public/kibana-plugin-public.chromestart.getapplicationclasses_.md index f01710478c635d..51f5253ede161a 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.getapplicationclasses_.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.getapplicationclasses_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getApplicationClasses$](./kibana-plugin-public.chromestart.getapplicationclasses_.md) - -## ChromeStart.getApplicationClasses$() method - -Get the current set of classNames that will be set on the application container. - -Signature: - -```typescript -getApplicationClasses$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getApplicationClasses$](./kibana-plugin-public.chromestart.getapplicationclasses_.md) + +## ChromeStart.getApplicationClasses$() method + +Get the current set of classNames that will be set on the application container. + +Signature: + +```typescript +getApplicationClasses$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.getbadge_.md b/docs/development/core/public/kibana-plugin-public.chromestart.getbadge_.md index 36f98defeb51e9..36b5c942e8dc28 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.getbadge_.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.getbadge_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getBadge$](./kibana-plugin-public.chromestart.getbadge_.md) - -## ChromeStart.getBadge$() method - -Get an observable of the current badge - -Signature: - -```typescript -getBadge$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getBadge$](./kibana-plugin-public.chromestart.getbadge_.md) + +## ChromeStart.getBadge$() method + +Get an observable of the current badge + +Signature: + +```typescript +getBadge$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.getbrand_.md b/docs/development/core/public/kibana-plugin-public.chromestart.getbrand_.md index aab0f13070fbc9..7010ccd632f4aa 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.getbrand_.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.getbrand_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getBrand$](./kibana-plugin-public.chromestart.getbrand_.md) - -## ChromeStart.getBrand$() method - -Get an observable of the current brand information. - -Signature: - -```typescript -getBrand$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getBrand$](./kibana-plugin-public.chromestart.getbrand_.md) + +## ChromeStart.getBrand$() method + +Get an observable of the current brand information. + +Signature: + +```typescript +getBrand$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.getbreadcrumbs_.md b/docs/development/core/public/kibana-plugin-public.chromestart.getbreadcrumbs_.md index 38fc384d6a704b..ac97863f16ad0f 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.getbreadcrumbs_.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.getbreadcrumbs_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getBreadcrumbs$](./kibana-plugin-public.chromestart.getbreadcrumbs_.md) - -## ChromeStart.getBreadcrumbs$() method - -Get an observable of the current list of breadcrumbs - -Signature: - -```typescript -getBreadcrumbs$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getBreadcrumbs$](./kibana-plugin-public.chromestart.getbreadcrumbs_.md) + +## ChromeStart.getBreadcrumbs$() method + +Get an observable of the current list of breadcrumbs + +Signature: + +```typescript +getBreadcrumbs$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.gethelpextension_.md b/docs/development/core/public/kibana-plugin-public.chromestart.gethelpextension_.md index 6008a4f29506d2..ff642651cedefb 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.gethelpextension_.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.gethelpextension_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getHelpExtension$](./kibana-plugin-public.chromestart.gethelpextension_.md) - -## ChromeStart.getHelpExtension$() method - -Get an observable of the current custom help conttent - -Signature: - -```typescript -getHelpExtension$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getHelpExtension$](./kibana-plugin-public.chromestart.gethelpextension_.md) + +## ChromeStart.getHelpExtension$() method + +Get an observable of the current custom help conttent + +Signature: + +```typescript +getHelpExtension$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.getiscollapsed_.md b/docs/development/core/public/kibana-plugin-public.chromestart.getiscollapsed_.md index 59871a78c4100e..98a1d3bfdd42e0 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.getiscollapsed_.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.getiscollapsed_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getIsCollapsed$](./kibana-plugin-public.chromestart.getiscollapsed_.md) - -## ChromeStart.getIsCollapsed$() method - -Get an observable of the current collapsed state of the chrome. - -Signature: - -```typescript -getIsCollapsed$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getIsCollapsed$](./kibana-plugin-public.chromestart.getiscollapsed_.md) + +## ChromeStart.getIsCollapsed$() method + +Get an observable of the current collapsed state of the chrome. + +Signature: + +```typescript +getIsCollapsed$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.getisvisible_.md b/docs/development/core/public/kibana-plugin-public.chromestart.getisvisible_.md index f597dbd1941097..8772b30cf8c8ed 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.getisvisible_.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.getisvisible_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getIsVisible$](./kibana-plugin-public.chromestart.getisvisible_.md) - -## ChromeStart.getIsVisible$() method - -Get an observable of the current visibility state of the chrome. - -Signature: - -```typescript -getIsVisible$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [getIsVisible$](./kibana-plugin-public.chromestart.getisvisible_.md) + +## ChromeStart.getIsVisible$() method + +Get an observable of the current visibility state of the chrome. + +Signature: + +```typescript +getIsVisible$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.md b/docs/development/core/public/kibana-plugin-public.chromestart.md index 4e44e5bf050742..4b79f682d4e40d 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.md @@ -1,70 +1,70 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) - -## ChromeStart interface - -ChromeStart allows plugins to customize the global chrome header UI and enrich the UX with additional information about the current location of the browser. - -Signature: - -```typescript -export interface ChromeStart -``` - -## Remarks - -While ChromeStart exposes many APIs, they should be used sparingly and the developer should understand how they affect other plugins and applications. - -## Example 1 - -How to add a recently accessed item to the sidebar: - -```ts -core.chrome.recentlyAccessed.add('/app/map/1234', 'Map 1234', '1234'); - -``` - -## Example 2 - -How to set the help dropdown extension: - -```tsx -core.chrome.setHelpExtension(elem => { - ReactDOM.render(, elem); - return () => ReactDOM.unmountComponentAtNode(elem); -}); - -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [docTitle](./kibana-plugin-public.chromestart.doctitle.md) | ChromeDocTitle | APIs for accessing and updating the document title. | -| [navControls](./kibana-plugin-public.chromestart.navcontrols.md) | ChromeNavControls | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | -| [navLinks](./kibana-plugin-public.chromestart.navlinks.md) | ChromeNavLinks | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. | -| [recentlyAccessed](./kibana-plugin-public.chromestart.recentlyaccessed.md) | ChromeRecentlyAccessed | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. | - -## Methods - -| Method | Description | -| --- | --- | -| [addApplicationClass(className)](./kibana-plugin-public.chromestart.addapplicationclass.md) | Add a className that should be set on the application container. | -| [getApplicationClasses$()](./kibana-plugin-public.chromestart.getapplicationclasses_.md) | Get the current set of classNames that will be set on the application container. | -| [getBadge$()](./kibana-plugin-public.chromestart.getbadge_.md) | Get an observable of the current badge | -| [getBrand$()](./kibana-plugin-public.chromestart.getbrand_.md) | Get an observable of the current brand information. | -| [getBreadcrumbs$()](./kibana-plugin-public.chromestart.getbreadcrumbs_.md) | Get an observable of the current list of breadcrumbs | -| [getHelpExtension$()](./kibana-plugin-public.chromestart.gethelpextension_.md) | Get an observable of the current custom help conttent | -| [getIsCollapsed$()](./kibana-plugin-public.chromestart.getiscollapsed_.md) | Get an observable of the current collapsed state of the chrome. | -| [getIsVisible$()](./kibana-plugin-public.chromestart.getisvisible_.md) | Get an observable of the current visibility state of the chrome. | -| [removeApplicationClass(className)](./kibana-plugin-public.chromestart.removeapplicationclass.md) | Remove a className added with addApplicationClass(). If className is unknown it is ignored. | -| [setAppTitle(appTitle)](./kibana-plugin-public.chromestart.setapptitle.md) | Sets the current app's title | -| [setBadge(badge)](./kibana-plugin-public.chromestart.setbadge.md) | Override the current badge | -| [setBrand(brand)](./kibana-plugin-public.chromestart.setbrand.md) | Set the brand configuration. | -| [setBreadcrumbs(newBreadcrumbs)](./kibana-plugin-public.chromestart.setbreadcrumbs.md) | Override the current set of breadcrumbs | -| [setHelpExtension(helpExtension)](./kibana-plugin-public.chromestart.sethelpextension.md) | Override the current set of custom help content | -| [setHelpSupportUrl(url)](./kibana-plugin-public.chromestart.sethelpsupporturl.md) | Override the default support URL shown in the help menu | -| [setIsCollapsed(isCollapsed)](./kibana-plugin-public.chromestart.setiscollapsed.md) | Set the collapsed state of the chrome navigation. | -| [setIsVisible(isVisible)](./kibana-plugin-public.chromestart.setisvisible.md) | Set the temporary visibility for the chrome. This does nothing if the chrome is hidden by default and should be used to hide the chrome for things like full-screen modes with an exit button. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) + +## ChromeStart interface + +ChromeStart allows plugins to customize the global chrome header UI and enrich the UX with additional information about the current location of the browser. + +Signature: + +```typescript +export interface ChromeStart +``` + +## Remarks + +While ChromeStart exposes many APIs, they should be used sparingly and the developer should understand how they affect other plugins and applications. + +## Example 1 + +How to add a recently accessed item to the sidebar: + +```ts +core.chrome.recentlyAccessed.add('/app/map/1234', 'Map 1234', '1234'); + +``` + +## Example 2 + +How to set the help dropdown extension: + +```tsx +core.chrome.setHelpExtension(elem => { + ReactDOM.render(, elem); + return () => ReactDOM.unmountComponentAtNode(elem); +}); + +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [docTitle](./kibana-plugin-public.chromestart.doctitle.md) | ChromeDocTitle | APIs for accessing and updating the document title. | +| [navControls](./kibana-plugin-public.chromestart.navcontrols.md) | ChromeNavControls | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | +| [navLinks](./kibana-plugin-public.chromestart.navlinks.md) | ChromeNavLinks | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. | +| [recentlyAccessed](./kibana-plugin-public.chromestart.recentlyaccessed.md) | ChromeRecentlyAccessed | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. | + +## Methods + +| Method | Description | +| --- | --- | +| [addApplicationClass(className)](./kibana-plugin-public.chromestart.addapplicationclass.md) | Add a className that should be set on the application container. | +| [getApplicationClasses$()](./kibana-plugin-public.chromestart.getapplicationclasses_.md) | Get the current set of classNames that will be set on the application container. | +| [getBadge$()](./kibana-plugin-public.chromestart.getbadge_.md) | Get an observable of the current badge | +| [getBrand$()](./kibana-plugin-public.chromestart.getbrand_.md) | Get an observable of the current brand information. | +| [getBreadcrumbs$()](./kibana-plugin-public.chromestart.getbreadcrumbs_.md) | Get an observable of the current list of breadcrumbs | +| [getHelpExtension$()](./kibana-plugin-public.chromestart.gethelpextension_.md) | Get an observable of the current custom help conttent | +| [getIsCollapsed$()](./kibana-plugin-public.chromestart.getiscollapsed_.md) | Get an observable of the current collapsed state of the chrome. | +| [getIsVisible$()](./kibana-plugin-public.chromestart.getisvisible_.md) | Get an observable of the current visibility state of the chrome. | +| [removeApplicationClass(className)](./kibana-plugin-public.chromestart.removeapplicationclass.md) | Remove a className added with addApplicationClass(). If className is unknown it is ignored. | +| [setAppTitle(appTitle)](./kibana-plugin-public.chromestart.setapptitle.md) | Sets the current app's title | +| [setBadge(badge)](./kibana-plugin-public.chromestart.setbadge.md) | Override the current badge | +| [setBrand(brand)](./kibana-plugin-public.chromestart.setbrand.md) | Set the brand configuration. | +| [setBreadcrumbs(newBreadcrumbs)](./kibana-plugin-public.chromestart.setbreadcrumbs.md) | Override the current set of breadcrumbs | +| [setHelpExtension(helpExtension)](./kibana-plugin-public.chromestart.sethelpextension.md) | Override the current set of custom help content | +| [setHelpSupportUrl(url)](./kibana-plugin-public.chromestart.sethelpsupporturl.md) | Override the default support URL shown in the help menu | +| [setIsCollapsed(isCollapsed)](./kibana-plugin-public.chromestart.setiscollapsed.md) | Set the collapsed state of the chrome navigation. | +| [setIsVisible(isVisible)](./kibana-plugin-public.chromestart.setisvisible.md) | Set the temporary visibility for the chrome. This does nothing if the chrome is hidden by default and should be used to hide the chrome for things like full-screen modes with an exit button. | + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.navcontrols.md b/docs/development/core/public/kibana-plugin-public.chromestart.navcontrols.md index 0a8e0e5c6da2b5..0ba72348499d21 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.navcontrols.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.navcontrols.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [navControls](./kibana-plugin-public.chromestart.navcontrols.md) - -## ChromeStart.navControls property - -[APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. - -Signature: - -```typescript -navControls: ChromeNavControls; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [navControls](./kibana-plugin-public.chromestart.navcontrols.md) + +## ChromeStart.navControls property + +[APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. + +Signature: + +```typescript +navControls: ChromeNavControls; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.navlinks.md b/docs/development/core/public/kibana-plugin-public.chromestart.navlinks.md index 047e72d9ce8198..db512ed83942d9 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.navlinks.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.navlinks.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [navLinks](./kibana-plugin-public.chromestart.navlinks.md) - -## ChromeStart.navLinks property - -[APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. - -Signature: - -```typescript -navLinks: ChromeNavLinks; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [navLinks](./kibana-plugin-public.chromestart.navlinks.md) + +## ChromeStart.navLinks property + +[APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. + +Signature: + +```typescript +navLinks: ChromeNavLinks; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.recentlyaccessed.md b/docs/development/core/public/kibana-plugin-public.chromestart.recentlyaccessed.md index d2e54ca956cae0..14b85cea366ec0 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.recentlyaccessed.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.recentlyaccessed.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [recentlyAccessed](./kibana-plugin-public.chromestart.recentlyaccessed.md) - -## ChromeStart.recentlyAccessed property - -[APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. - -Signature: - -```typescript -recentlyAccessed: ChromeRecentlyAccessed; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [recentlyAccessed](./kibana-plugin-public.chromestart.recentlyaccessed.md) + +## ChromeStart.recentlyAccessed property + +[APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. + +Signature: + +```typescript +recentlyAccessed: ChromeRecentlyAccessed; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.removeapplicationclass.md b/docs/development/core/public/kibana-plugin-public.chromestart.removeapplicationclass.md index 73a0f65449a20c..3b5ca813218dcd 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.removeapplicationclass.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.removeapplicationclass.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [removeApplicationClass](./kibana-plugin-public.chromestart.removeapplicationclass.md) - -## ChromeStart.removeApplicationClass() method - -Remove a className added with `addApplicationClass()`. If className is unknown it is ignored. - -Signature: - -```typescript -removeApplicationClass(className: string): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| className | string | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [removeApplicationClass](./kibana-plugin-public.chromestart.removeapplicationclass.md) + +## ChromeStart.removeApplicationClass() method + +Remove a className added with `addApplicationClass()`. If className is unknown it is ignored. + +Signature: + +```typescript +removeApplicationClass(className: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| className | string | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.setapptitle.md b/docs/development/core/public/kibana-plugin-public.chromestart.setapptitle.md index ec24b77f127fe3..4927bd58b19afa 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.setapptitle.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.setapptitle.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setAppTitle](./kibana-plugin-public.chromestart.setapptitle.md) - -## ChromeStart.setAppTitle() method - -Sets the current app's title - -Signature: - -```typescript -setAppTitle(appTitle: string): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| appTitle | string | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setAppTitle](./kibana-plugin-public.chromestart.setapptitle.md) + +## ChromeStart.setAppTitle() method + +Sets the current app's title + +Signature: + +```typescript +setAppTitle(appTitle: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| appTitle | string | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.setbadge.md b/docs/development/core/public/kibana-plugin-public.chromestart.setbadge.md index a9da8e2fec641d..cbbe408c1a7910 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.setbadge.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.setbadge.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setBadge](./kibana-plugin-public.chromestart.setbadge.md) - -## ChromeStart.setBadge() method - -Override the current badge - -Signature: - -```typescript -setBadge(badge?: ChromeBadge): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| badge | ChromeBadge | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setBadge](./kibana-plugin-public.chromestart.setbadge.md) + +## ChromeStart.setBadge() method + +Override the current badge + +Signature: + +```typescript +setBadge(badge?: ChromeBadge): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| badge | ChromeBadge | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.setbrand.md b/docs/development/core/public/kibana-plugin-public.chromestart.setbrand.md index 3fcf9df6125946..487dcb227ba239 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.setbrand.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.setbrand.md @@ -1,39 +1,39 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setBrand](./kibana-plugin-public.chromestart.setbrand.md) - -## ChromeStart.setBrand() method - -Set the brand configuration. - -Signature: - -```typescript -setBrand(brand: ChromeBrand): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| brand | ChromeBrand | | - -Returns: - -`void` - -## Remarks - -Normally the `logo` property will be rendered as the CSS background for the home link in the chrome navigation, but when the page is rendered in a small window the `smallLogo` will be used and rendered at about 45px wide. - -## Example - - -```js -chrome.setBrand({ - logo: 'url(/plugins/app/logo.png) center no-repeat' - smallLogo: 'url(/plugins/app/logo-small.png) center no-repeat' -}) - -``` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setBrand](./kibana-plugin-public.chromestart.setbrand.md) + +## ChromeStart.setBrand() method + +Set the brand configuration. + +Signature: + +```typescript +setBrand(brand: ChromeBrand): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| brand | ChromeBrand | | + +Returns: + +`void` + +## Remarks + +Normally the `logo` property will be rendered as the CSS background for the home link in the chrome navigation, but when the page is rendered in a small window the `smallLogo` will be used and rendered at about 45px wide. + +## Example + + +```js +chrome.setBrand({ + logo: 'url(/plugins/app/logo.png) center no-repeat' + smallLogo: 'url(/plugins/app/logo-small.png) center no-repeat' +}) + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.setbreadcrumbs.md b/docs/development/core/public/kibana-plugin-public.chromestart.setbreadcrumbs.md index a533ea34a91068..0c54d123454e0b 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.setbreadcrumbs.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.setbreadcrumbs.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setBreadcrumbs](./kibana-plugin-public.chromestart.setbreadcrumbs.md) - -## ChromeStart.setBreadcrumbs() method - -Override the current set of breadcrumbs - -Signature: - -```typescript -setBreadcrumbs(newBreadcrumbs: ChromeBreadcrumb[]): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| newBreadcrumbs | ChromeBreadcrumb[] | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setBreadcrumbs](./kibana-plugin-public.chromestart.setbreadcrumbs.md) + +## ChromeStart.setBreadcrumbs() method + +Override the current set of breadcrumbs + +Signature: + +```typescript +setBreadcrumbs(newBreadcrumbs: ChromeBreadcrumb[]): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| newBreadcrumbs | ChromeBreadcrumb[] | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.sethelpextension.md b/docs/development/core/public/kibana-plugin-public.chromestart.sethelpextension.md index 900848e7756e21..1cfa1b19cb0fe7 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.sethelpextension.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.sethelpextension.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setHelpExtension](./kibana-plugin-public.chromestart.sethelpextension.md) - -## ChromeStart.setHelpExtension() method - -Override the current set of custom help content - -Signature: - -```typescript -setHelpExtension(helpExtension?: ChromeHelpExtension): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| helpExtension | ChromeHelpExtension | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setHelpExtension](./kibana-plugin-public.chromestart.sethelpextension.md) + +## ChromeStart.setHelpExtension() method + +Override the current set of custom help content + +Signature: + +```typescript +setHelpExtension(helpExtension?: ChromeHelpExtension): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| helpExtension | ChromeHelpExtension | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.sethelpsupporturl.md b/docs/development/core/public/kibana-plugin-public.chromestart.sethelpsupporturl.md index 975283ce59cb75..9f1869bf3f9508 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.sethelpsupporturl.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.sethelpsupporturl.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setHelpSupportUrl](./kibana-plugin-public.chromestart.sethelpsupporturl.md) - -## ChromeStart.setHelpSupportUrl() method - -Override the default support URL shown in the help menu - -Signature: - -```typescript -setHelpSupportUrl(url: string): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | string | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setHelpSupportUrl](./kibana-plugin-public.chromestart.sethelpsupporturl.md) + +## ChromeStart.setHelpSupportUrl() method + +Override the default support URL shown in the help menu + +Signature: + +```typescript +setHelpSupportUrl(url: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| url | string | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.setiscollapsed.md b/docs/development/core/public/kibana-plugin-public.chromestart.setiscollapsed.md index 59732bf103acc2..8cfa2bd9ba6d94 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.setiscollapsed.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.setiscollapsed.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setIsCollapsed](./kibana-plugin-public.chromestart.setiscollapsed.md) - -## ChromeStart.setIsCollapsed() method - -Set the collapsed state of the chrome navigation. - -Signature: - -```typescript -setIsCollapsed(isCollapsed: boolean): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| isCollapsed | boolean | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setIsCollapsed](./kibana-plugin-public.chromestart.setiscollapsed.md) + +## ChromeStart.setIsCollapsed() method + +Set the collapsed state of the chrome navigation. + +Signature: + +```typescript +setIsCollapsed(isCollapsed: boolean): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| isCollapsed | boolean | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.setisvisible.md b/docs/development/core/public/kibana-plugin-public.chromestart.setisvisible.md index 1536c82f000866..471efb270416a3 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.setisvisible.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.setisvisible.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setIsVisible](./kibana-plugin-public.chromestart.setisvisible.md) - -## ChromeStart.setIsVisible() method - -Set the temporary visibility for the chrome. This does nothing if the chrome is hidden by default and should be used to hide the chrome for things like full-screen modes with an exit button. - -Signature: - -```typescript -setIsVisible(isVisible: boolean): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| isVisible | boolean | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [setIsVisible](./kibana-plugin-public.chromestart.setisvisible.md) + +## ChromeStart.setIsVisible() method + +Set the temporary visibility for the chrome. This does nothing if the chrome is hidden by default and should be used to hide the chrome for things like full-screen modes with an exit button. + +Signature: + +```typescript +setIsVisible(isVisible: boolean): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| isVisible | boolean | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md b/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md index 5334eee8425779..e1bb5bedd5a7ea 100644 --- a/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md +++ b/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ContextSetup](./kibana-plugin-public.contextsetup.md) > [createContextContainer](./kibana-plugin-public.contextsetup.createcontextcontainer.md) - -## ContextSetup.createContextContainer() method - -Creates a new [IContextContainer](./kibana-plugin-public.icontextcontainer.md) for a service owner. - -Signature: - -```typescript -createContextContainer>(): IContextContainer; -``` -Returns: - -`IContextContainer` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ContextSetup](./kibana-plugin-public.contextsetup.md) > [createContextContainer](./kibana-plugin-public.contextsetup.createcontextcontainer.md) + +## ContextSetup.createContextContainer() method + +Creates a new [IContextContainer](./kibana-plugin-public.icontextcontainer.md) for a service owner. + +Signature: + +```typescript +createContextContainer>(): IContextContainer; +``` +Returns: + +`IContextContainer` + diff --git a/docs/development/core/public/kibana-plugin-public.contextsetup.md b/docs/development/core/public/kibana-plugin-public.contextsetup.md index d4399b6ba70c46..fe9a2e3004708f 100644 --- a/docs/development/core/public/kibana-plugin-public.contextsetup.md +++ b/docs/development/core/public/kibana-plugin-public.contextsetup.md @@ -1,138 +1,138 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ContextSetup](./kibana-plugin-public.contextsetup.md) - -## ContextSetup interface - -An object that handles registration of context providers and configuring handlers with context. - -Signature: - -```typescript -export interface ContextSetup -``` - -## Remarks - -A [IContextContainer](./kibana-plugin-public.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. - -Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. - -In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-public.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. - -When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. - -```ts -// Correct -class MyPlugin { - private readonly handlers = new Map(); - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - return { - registerContext(pluginOpaqueId, contextName, provider) { - this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); - }, - registerRoute(pluginOpaqueId, path, handler) { - this.handlers.set( - path, - this.contextContainer.createHandler(pluginOpaqueId, handler) - ); - } - } - } -} - -// Incorrect -class MyPlugin { - private readonly handlers = new Map(); - - constructor(private readonly initContext: PluginInitializerContext) {} - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - return { - registerContext(contextName, provider) { - // BUG! - // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. - this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); - }, - registerRoute(path, handler) { - this.handlers.set( - path, - // BUG! - // This handler will not receive any contexts provided by other dependencies of the calling plugin. - this.contextContainer.createHandler(this.initContext.opaqueId, handler) - ); - } - } - } -} - -``` - -## Example - -Say we're creating a plugin for rendering visualizations that allows new rendering methods to be registered. If we want to offer context to these rendering methods, we can leverage the ContextService to manage these contexts. - -```ts -export interface VizRenderContext { - core: { - i18n: I18nStart; - uiSettings: IUiSettingsClient; - } - [contextName: string]: unknown; -} - -export type VizRenderer = (context: VizRenderContext, domElement: HTMLElement) => () => void; -// When a renderer is bound via `contextContainer.createHandler` this is the type that will be returned. -type BoundVizRenderer = (domElement: HTMLElement) => () => void; - -class VizRenderingPlugin { - private readonly contextContainer?: IContextContainer; - private readonly vizRenderers = new Map(); - - constructor(private readonly initContext: PluginInitializerContext) {} - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - - return { - registerContext: this.contextContainer.registerContext, - registerVizRenderer: (plugin: PluginOpaqueId, renderMethod: string, renderer: VizTypeRenderer) => - this.vizRenderers.set(renderMethod, this.contextContainer.createHandler(plugin, renderer)), - }; - } - - start(core) { - // Register the core context available to all renderers. Use the VizRendererContext's opaqueId as the first arg. - this.contextContainer.registerContext(this.initContext.opaqueId, 'core', () => ({ - i18n: core.i18n, - uiSettings: core.uiSettings - })); - - return { - registerContext: this.contextContainer.registerContext, - - renderVizualization: (renderMethod: string, domElement: HTMLElement) => { - if (!this.vizRenderer.has(renderMethod)) { - throw new Error(`Render method '${renderMethod}' has not been registered`); - } - - // The handler can now be called directly with only an `HTMLElement` and will automatically - // have a new `context` object created and populated by the context container. - const handler = this.vizRenderers.get(renderMethod) - return handler(domElement); - } - }; - } -} - -``` - -## Methods - -| Method | Description | -| --- | --- | -| [createContextContainer()](./kibana-plugin-public.contextsetup.createcontextcontainer.md) | Creates a new [IContextContainer](./kibana-plugin-public.icontextcontainer.md) for a service owner. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ContextSetup](./kibana-plugin-public.contextsetup.md) + +## ContextSetup interface + +An object that handles registration of context providers and configuring handlers with context. + +Signature: + +```typescript +export interface ContextSetup +``` + +## Remarks + +A [IContextContainer](./kibana-plugin-public.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. + +Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. + +In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-public.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. + +When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. + +```ts +// Correct +class MyPlugin { + private readonly handlers = new Map(); + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(pluginOpaqueId, contextName, provider) { + this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); + }, + registerRoute(pluginOpaqueId, path, handler) { + this.handlers.set( + path, + this.contextContainer.createHandler(pluginOpaqueId, handler) + ); + } + } + } +} + +// Incorrect +class MyPlugin { + private readonly handlers = new Map(); + + constructor(private readonly initContext: PluginInitializerContext) {} + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(contextName, provider) { + // BUG! + // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. + this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); + }, + registerRoute(path, handler) { + this.handlers.set( + path, + // BUG! + // This handler will not receive any contexts provided by other dependencies of the calling plugin. + this.contextContainer.createHandler(this.initContext.opaqueId, handler) + ); + } + } + } +} + +``` + +## Example + +Say we're creating a plugin for rendering visualizations that allows new rendering methods to be registered. If we want to offer context to these rendering methods, we can leverage the ContextService to manage these contexts. + +```ts +export interface VizRenderContext { + core: { + i18n: I18nStart; + uiSettings: IUiSettingsClient; + } + [contextName: string]: unknown; +} + +export type VizRenderer = (context: VizRenderContext, domElement: HTMLElement) => () => void; +// When a renderer is bound via `contextContainer.createHandler` this is the type that will be returned. +type BoundVizRenderer = (domElement: HTMLElement) => () => void; + +class VizRenderingPlugin { + private readonly contextContainer?: IContextContainer; + private readonly vizRenderers = new Map(); + + constructor(private readonly initContext: PluginInitializerContext) {} + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + + return { + registerContext: this.contextContainer.registerContext, + registerVizRenderer: (plugin: PluginOpaqueId, renderMethod: string, renderer: VizTypeRenderer) => + this.vizRenderers.set(renderMethod, this.contextContainer.createHandler(plugin, renderer)), + }; + } + + start(core) { + // Register the core context available to all renderers. Use the VizRendererContext's opaqueId as the first arg. + this.contextContainer.registerContext(this.initContext.opaqueId, 'core', () => ({ + i18n: core.i18n, + uiSettings: core.uiSettings + })); + + return { + registerContext: this.contextContainer.registerContext, + + renderVizualization: (renderMethod: string, domElement: HTMLElement) => { + if (!this.vizRenderer.has(renderMethod)) { + throw new Error(`Render method '${renderMethod}' has not been registered`); + } + + // The handler can now be called directly with only an `HTMLElement` and will automatically + // have a new `context` object created and populated by the context container. + const handler = this.vizRenderers.get(renderMethod) + return handler(domElement); + } + }; + } +} + +``` + +## Methods + +| Method | Description | +| --- | --- | +| [createContextContainer()](./kibana-plugin-public.contextsetup.createcontextcontainer.md) | Creates a new [IContextContainer](./kibana-plugin-public.icontextcontainer.md) for a service owner. | + diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.application.md b/docs/development/core/public/kibana-plugin-public.coresetup.application.md index 4b39b2c76802b1..2b4b54b0023eeb 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.application.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.application.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [application](./kibana-plugin-public.coresetup.application.md) - -## CoreSetup.application property - -[ApplicationSetup](./kibana-plugin-public.applicationsetup.md) - -Signature: - -```typescript -application: ApplicationSetup; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [application](./kibana-plugin-public.coresetup.application.md) + +## CoreSetup.application property + +[ApplicationSetup](./kibana-plugin-public.applicationsetup.md) + +Signature: + +```typescript +application: ApplicationSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.context.md b/docs/development/core/public/kibana-plugin-public.coresetup.context.md index f2a891c6c674eb..12f82554823857 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.context.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.context.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [context](./kibana-plugin-public.coresetup.context.md) - -## CoreSetup.context property - -> Warning: This API is now obsolete. -> -> - -[ContextSetup](./kibana-plugin-public.contextsetup.md) - -Signature: - -```typescript -context: ContextSetup; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [context](./kibana-plugin-public.coresetup.context.md) + +## CoreSetup.context property + +> Warning: This API is now obsolete. +> +> + +[ContextSetup](./kibana-plugin-public.contextsetup.md) + +Signature: + +```typescript +context: ContextSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.fatalerrors.md b/docs/development/core/public/kibana-plugin-public.coresetup.fatalerrors.md index 5d51af0898e4f4..8f96ffd2c15e8e 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.fatalerrors.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.fatalerrors.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [fatalErrors](./kibana-plugin-public.coresetup.fatalerrors.md) - -## CoreSetup.fatalErrors property - -[FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) - -Signature: - -```typescript -fatalErrors: FatalErrorsSetup; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [fatalErrors](./kibana-plugin-public.coresetup.fatalerrors.md) + +## CoreSetup.fatalErrors property + +[FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) + +Signature: + +```typescript +fatalErrors: FatalErrorsSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.getstartservices.md b/docs/development/core/public/kibana-plugin-public.coresetup.getstartservices.md index b89d98b0a9ed53..188e4664934ff6 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.getstartservices.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.getstartservices.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [getStartServices](./kibana-plugin-public.coresetup.getstartservices.md) - -## CoreSetup.getStartServices() method - -Allows plugins to get access to APIs available in start inside async handlers, such as [App.mount](./kibana-plugin-public.app.mount.md). Promise will not resolve until Core and plugin dependencies have completed `start`. - -Signature: - -```typescript -getStartServices(): Promise<[CoreStart, TPluginsStart]>; -``` -Returns: - -`Promise<[CoreStart, TPluginsStart]>` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [getStartServices](./kibana-plugin-public.coresetup.getstartservices.md) + +## CoreSetup.getStartServices() method + +Allows plugins to get access to APIs available in start inside async handlers, such as [App.mount](./kibana-plugin-public.app.mount.md). Promise will not resolve until Core and plugin dependencies have completed `start`. + +Signature: + +```typescript +getStartServices(): Promise<[CoreStart, TPluginsStart]>; +``` +Returns: + +`Promise<[CoreStart, TPluginsStart]>` + diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.http.md b/docs/development/core/public/kibana-plugin-public.coresetup.http.md index 7471f7daa668d4..112f80093361c6 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.http.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.http.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [http](./kibana-plugin-public.coresetup.http.md) - -## CoreSetup.http property - -[HttpSetup](./kibana-plugin-public.httpsetup.md) - -Signature: - -```typescript -http: HttpSetup; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [http](./kibana-plugin-public.coresetup.http.md) + +## CoreSetup.http property + +[HttpSetup](./kibana-plugin-public.httpsetup.md) + +Signature: + +```typescript +http: HttpSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.injectedmetadata.md b/docs/development/core/public/kibana-plugin-public.coresetup.injectedmetadata.md index f9c1a283e38089..a62b8b99ee1319 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.injectedmetadata.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.injectedmetadata.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [injectedMetadata](./kibana-plugin-public.coresetup.injectedmetadata.md) - -## CoreSetup.injectedMetadata property - -> Warning: This API is now obsolete. -> -> - -exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. - -Signature: - -```typescript -injectedMetadata: { - getInjectedVar: (name: string, defaultValue?: any) => unknown; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [injectedMetadata](./kibana-plugin-public.coresetup.injectedmetadata.md) + +## CoreSetup.injectedMetadata property + +> Warning: This API is now obsolete. +> +> + +exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. + +Signature: + +```typescript +injectedMetadata: { + getInjectedVar: (name: string, defaultValue?: any) => unknown; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.md b/docs/development/core/public/kibana-plugin-public.coresetup.md index 7d75782df2e321..ae423c6e8d79c0 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.md @@ -1,32 +1,32 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) - -## CoreSetup interface - -Core services exposed to the `Plugin` setup lifecycle - -Signature: - -```typescript -export interface CoreSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [application](./kibana-plugin-public.coresetup.application.md) | ApplicationSetup | [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | -| [context](./kibana-plugin-public.coresetup.context.md) | ContextSetup | [ContextSetup](./kibana-plugin-public.contextsetup.md) | -| [fatalErrors](./kibana-plugin-public.coresetup.fatalerrors.md) | FatalErrorsSetup | [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | -| [http](./kibana-plugin-public.coresetup.http.md) | HttpSetup | [HttpSetup](./kibana-plugin-public.httpsetup.md) | -| [injectedMetadata](./kibana-plugin-public.coresetup.injectedmetadata.md) | {
getInjectedVar: (name: string, defaultValue?: any) => unknown;
} | exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. | -| [notifications](./kibana-plugin-public.coresetup.notifications.md) | NotificationsSetup | [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) | -| [uiSettings](./kibana-plugin-public.coresetup.uisettings.md) | IUiSettingsClient | [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | - -## Methods - -| Method | Description | -| --- | --- | -| [getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md) | Allows plugins to get access to APIs available in start inside async handlers, such as [App.mount](./kibana-plugin-public.app.mount.md). Promise will not resolve until Core and plugin dependencies have completed start. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) + +## CoreSetup interface + +Core services exposed to the `Plugin` setup lifecycle + +Signature: + +```typescript +export interface CoreSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [application](./kibana-plugin-public.coresetup.application.md) | ApplicationSetup | [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | +| [context](./kibana-plugin-public.coresetup.context.md) | ContextSetup | [ContextSetup](./kibana-plugin-public.contextsetup.md) | +| [fatalErrors](./kibana-plugin-public.coresetup.fatalerrors.md) | FatalErrorsSetup | [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | +| [http](./kibana-plugin-public.coresetup.http.md) | HttpSetup | [HttpSetup](./kibana-plugin-public.httpsetup.md) | +| [injectedMetadata](./kibana-plugin-public.coresetup.injectedmetadata.md) | {
getInjectedVar: (name: string, defaultValue?: any) => unknown;
} | exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. | +| [notifications](./kibana-plugin-public.coresetup.notifications.md) | NotificationsSetup | [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) | +| [uiSettings](./kibana-plugin-public.coresetup.uisettings.md) | IUiSettingsClient | [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | + +## Methods + +| Method | Description | +| --- | --- | +| [getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md) | Allows plugins to get access to APIs available in start inside async handlers, such as [App.mount](./kibana-plugin-public.app.mount.md). Promise will not resolve until Core and plugin dependencies have completed start. | + diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.notifications.md b/docs/development/core/public/kibana-plugin-public.coresetup.notifications.md index ea050925bbafc4..52808b860a9e63 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.notifications.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.notifications.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [notifications](./kibana-plugin-public.coresetup.notifications.md) - -## CoreSetup.notifications property - -[NotificationsSetup](./kibana-plugin-public.notificationssetup.md) - -Signature: - -```typescript -notifications: NotificationsSetup; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [notifications](./kibana-plugin-public.coresetup.notifications.md) + +## CoreSetup.notifications property + +[NotificationsSetup](./kibana-plugin-public.notificationssetup.md) + +Signature: + +```typescript +notifications: NotificationsSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.uisettings.md b/docs/development/core/public/kibana-plugin-public.coresetup.uisettings.md index bf9ec12e3eea23..51aa9916f7f07e 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.uisettings.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.uisettings.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [uiSettings](./kibana-plugin-public.coresetup.uisettings.md) - -## CoreSetup.uiSettings property - -[IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) - -Signature: - -```typescript -uiSettings: IUiSettingsClient; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [uiSettings](./kibana-plugin-public.coresetup.uisettings.md) + +## CoreSetup.uiSettings property + +[IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) + +Signature: + +```typescript +uiSettings: IUiSettingsClient; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.application.md b/docs/development/core/public/kibana-plugin-public.corestart.application.md index c26701ca80529a..b8565c5812aaf9 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.application.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.application.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [application](./kibana-plugin-public.corestart.application.md) - -## CoreStart.application property - -[ApplicationStart](./kibana-plugin-public.applicationstart.md) - -Signature: - -```typescript -application: ApplicationStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [application](./kibana-plugin-public.corestart.application.md) + +## CoreStart.application property + +[ApplicationStart](./kibana-plugin-public.applicationstart.md) + +Signature: + +```typescript +application: ApplicationStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.chrome.md b/docs/development/core/public/kibana-plugin-public.corestart.chrome.md index 390bde25bae93d..02f410b08b024c 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.chrome.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.chrome.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [chrome](./kibana-plugin-public.corestart.chrome.md) - -## CoreStart.chrome property - -[ChromeStart](./kibana-plugin-public.chromestart.md) - -Signature: - -```typescript -chrome: ChromeStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [chrome](./kibana-plugin-public.corestart.chrome.md) + +## CoreStart.chrome property + +[ChromeStart](./kibana-plugin-public.chromestart.md) + +Signature: + +```typescript +chrome: ChromeStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.doclinks.md b/docs/development/core/public/kibana-plugin-public.corestart.doclinks.md index 7f9e4ea10baac8..641b9520be1a43 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.doclinks.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.doclinks.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [docLinks](./kibana-plugin-public.corestart.doclinks.md) - -## CoreStart.docLinks property - -[DocLinksStart](./kibana-plugin-public.doclinksstart.md) - -Signature: - -```typescript -docLinks: DocLinksStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [docLinks](./kibana-plugin-public.corestart.doclinks.md) + +## CoreStart.docLinks property + +[DocLinksStart](./kibana-plugin-public.doclinksstart.md) + +Signature: + +```typescript +docLinks: DocLinksStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.fatalerrors.md b/docs/development/core/public/kibana-plugin-public.corestart.fatalerrors.md new file mode 100644 index 00000000000000..890fcac5a768bf --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.corestart.fatalerrors.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [fatalErrors](./kibana-plugin-public.corestart.fatalerrors.md) + +## CoreStart.fatalErrors property + +[FatalErrorsStart](./kibana-plugin-public.fatalerrorsstart.md) + +Signature: + +```typescript +fatalErrors: FatalErrorsStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.http.md b/docs/development/core/public/kibana-plugin-public.corestart.http.md index 6af183480c663a..12fca537745321 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.http.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.http.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [http](./kibana-plugin-public.corestart.http.md) - -## CoreStart.http property - -[HttpStart](./kibana-plugin-public.httpstart.md) - -Signature: - -```typescript -http: HttpStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [http](./kibana-plugin-public.corestart.http.md) + +## CoreStart.http property + +[HttpStart](./kibana-plugin-public.httpstart.md) + +Signature: + +```typescript +http: HttpStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.i18n.md b/docs/development/core/public/kibana-plugin-public.corestart.i18n.md index 6a62025874aa9d..75baf18a482e1e 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.i18n.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.i18n.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [i18n](./kibana-plugin-public.corestart.i18n.md) - -## CoreStart.i18n property - -[I18nStart](./kibana-plugin-public.i18nstart.md) - -Signature: - -```typescript -i18n: I18nStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [i18n](./kibana-plugin-public.corestart.i18n.md) + +## CoreStart.i18n property + +[I18nStart](./kibana-plugin-public.i18nstart.md) + +Signature: + +```typescript +i18n: I18nStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.injectedmetadata.md b/docs/development/core/public/kibana-plugin-public.corestart.injectedmetadata.md index 9224b97bc43004..b3f6361d3a8c33 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.injectedmetadata.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.injectedmetadata.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [injectedMetadata](./kibana-plugin-public.corestart.injectedmetadata.md) - -## CoreStart.injectedMetadata property - -> Warning: This API is now obsolete. -> -> - -exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. - -Signature: - -```typescript -injectedMetadata: { - getInjectedVar: (name: string, defaultValue?: any) => unknown; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [injectedMetadata](./kibana-plugin-public.corestart.injectedmetadata.md) + +## CoreStart.injectedMetadata property + +> Warning: This API is now obsolete. +> +> + +exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. + +Signature: + +```typescript +injectedMetadata: { + getInjectedVar: (name: string, defaultValue?: any) => unknown; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.md b/docs/development/core/public/kibana-plugin-public.corestart.md index e561ee313f1000..c0a326b3b01cbe 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.md @@ -1,29 +1,30 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) - -## CoreStart interface - -Core services exposed to the `Plugin` start lifecycle - -Signature: - -```typescript -export interface CoreStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [application](./kibana-plugin-public.corestart.application.md) | ApplicationStart | [ApplicationStart](./kibana-plugin-public.applicationstart.md) | -| [chrome](./kibana-plugin-public.corestart.chrome.md) | ChromeStart | [ChromeStart](./kibana-plugin-public.chromestart.md) | -| [docLinks](./kibana-plugin-public.corestart.doclinks.md) | DocLinksStart | [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | -| [http](./kibana-plugin-public.corestart.http.md) | HttpStart | [HttpStart](./kibana-plugin-public.httpstart.md) | -| [i18n](./kibana-plugin-public.corestart.i18n.md) | I18nStart | [I18nStart](./kibana-plugin-public.i18nstart.md) | -| [injectedMetadata](./kibana-plugin-public.corestart.injectedmetadata.md) | {
getInjectedVar: (name: string, defaultValue?: any) => unknown;
} | exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. | -| [notifications](./kibana-plugin-public.corestart.notifications.md) | NotificationsStart | [NotificationsStart](./kibana-plugin-public.notificationsstart.md) | -| [overlays](./kibana-plugin-public.corestart.overlays.md) | OverlayStart | [OverlayStart](./kibana-plugin-public.overlaystart.md) | -| [savedObjects](./kibana-plugin-public.corestart.savedobjects.md) | SavedObjectsStart | [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) | -| [uiSettings](./kibana-plugin-public.corestart.uisettings.md) | IUiSettingsClient | [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) + +## CoreStart interface + +Core services exposed to the `Plugin` start lifecycle + +Signature: + +```typescript +export interface CoreStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [application](./kibana-plugin-public.corestart.application.md) | ApplicationStart | [ApplicationStart](./kibana-plugin-public.applicationstart.md) | +| [chrome](./kibana-plugin-public.corestart.chrome.md) | ChromeStart | [ChromeStart](./kibana-plugin-public.chromestart.md) | +| [docLinks](./kibana-plugin-public.corestart.doclinks.md) | DocLinksStart | [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | +| [fatalErrors](./kibana-plugin-public.corestart.fatalerrors.md) | FatalErrorsStart | [FatalErrorsStart](./kibana-plugin-public.fatalerrorsstart.md) | +| [http](./kibana-plugin-public.corestart.http.md) | HttpStart | [HttpStart](./kibana-plugin-public.httpstart.md) | +| [i18n](./kibana-plugin-public.corestart.i18n.md) | I18nStart | [I18nStart](./kibana-plugin-public.i18nstart.md) | +| [injectedMetadata](./kibana-plugin-public.corestart.injectedmetadata.md) | {
getInjectedVar: (name: string, defaultValue?: any) => unknown;
} | exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. | +| [notifications](./kibana-plugin-public.corestart.notifications.md) | NotificationsStart | [NotificationsStart](./kibana-plugin-public.notificationsstart.md) | +| [overlays](./kibana-plugin-public.corestart.overlays.md) | OverlayStart | [OverlayStart](./kibana-plugin-public.overlaystart.md) | +| [savedObjects](./kibana-plugin-public.corestart.savedobjects.md) | SavedObjectsStart | [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) | +| [uiSettings](./kibana-plugin-public.corestart.uisettings.md) | IUiSettingsClient | [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | + diff --git a/docs/development/core/public/kibana-plugin-public.corestart.notifications.md b/docs/development/core/public/kibana-plugin-public.corestart.notifications.md index c9533a1ec2f10a..b9c75a19890964 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.notifications.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.notifications.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [notifications](./kibana-plugin-public.corestart.notifications.md) - -## CoreStart.notifications property - -[NotificationsStart](./kibana-plugin-public.notificationsstart.md) - -Signature: - -```typescript -notifications: NotificationsStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [notifications](./kibana-plugin-public.corestart.notifications.md) + +## CoreStart.notifications property + +[NotificationsStart](./kibana-plugin-public.notificationsstart.md) + +Signature: + +```typescript +notifications: NotificationsStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.overlays.md b/docs/development/core/public/kibana-plugin-public.corestart.overlays.md index 53d20b994f43d4..9f2bf269884a12 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.overlays.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.overlays.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [overlays](./kibana-plugin-public.corestart.overlays.md) - -## CoreStart.overlays property - -[OverlayStart](./kibana-plugin-public.overlaystart.md) - -Signature: - -```typescript -overlays: OverlayStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [overlays](./kibana-plugin-public.corestart.overlays.md) + +## CoreStart.overlays property + +[OverlayStart](./kibana-plugin-public.overlaystart.md) + +Signature: + +```typescript +overlays: OverlayStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.savedobjects.md b/docs/development/core/public/kibana-plugin-public.corestart.savedobjects.md index 5e6e0e33c7f801..80ba416ec5e0cb 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.savedobjects.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.savedobjects.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [savedObjects](./kibana-plugin-public.corestart.savedobjects.md) - -## CoreStart.savedObjects property - -[SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) - -Signature: - -```typescript -savedObjects: SavedObjectsStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [savedObjects](./kibana-plugin-public.corestart.savedobjects.md) + +## CoreStart.savedObjects property + +[SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) + +Signature: + +```typescript +savedObjects: SavedObjectsStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.uisettings.md b/docs/development/core/public/kibana-plugin-public.corestart.uisettings.md index 2ee405591dc08d..2831e4da135780 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.uisettings.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.uisettings.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [uiSettings](./kibana-plugin-public.corestart.uisettings.md) - -## CoreStart.uiSettings property - -[IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) - -Signature: - -```typescript -uiSettings: IUiSettingsClient; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreStart](./kibana-plugin-public.corestart.md) > [uiSettings](./kibana-plugin-public.corestart.uisettings.md) + +## CoreStart.uiSettings property + +[IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) + +Signature: + +```typescript +uiSettings: IUiSettingsClient; +``` diff --git a/docs/development/core/public/kibana-plugin-public.doclinksstart.doc_link_version.md b/docs/development/core/public/kibana-plugin-public.doclinksstart.doc_link_version.md index 5e7f9f9e486871..453d358710f2de 100644 --- a/docs/development/core/public/kibana-plugin-public.doclinksstart.doc_link_version.md +++ b/docs/development/core/public/kibana-plugin-public.doclinksstart.doc_link_version.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [DocLinksStart](./kibana-plugin-public.doclinksstart.md) > [DOC\_LINK\_VERSION](./kibana-plugin-public.doclinksstart.doc_link_version.md) - -## DocLinksStart.DOC\_LINK\_VERSION property - -Signature: - -```typescript -readonly DOC_LINK_VERSION: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [DocLinksStart](./kibana-plugin-public.doclinksstart.md) > [DOC\_LINK\_VERSION](./kibana-plugin-public.doclinksstart.doc_link_version.md) + +## DocLinksStart.DOC\_LINK\_VERSION property + +Signature: + +```typescript +readonly DOC_LINK_VERSION: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.doclinksstart.elastic_website_url.md b/docs/development/core/public/kibana-plugin-public.doclinksstart.elastic_website_url.md index b4967038b35d7c..9ef871e776996f 100644 --- a/docs/development/core/public/kibana-plugin-public.doclinksstart.elastic_website_url.md +++ b/docs/development/core/public/kibana-plugin-public.doclinksstart.elastic_website_url.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [DocLinksStart](./kibana-plugin-public.doclinksstart.md) > [ELASTIC\_WEBSITE\_URL](./kibana-plugin-public.doclinksstart.elastic_website_url.md) - -## DocLinksStart.ELASTIC\_WEBSITE\_URL property - -Signature: - -```typescript -readonly ELASTIC_WEBSITE_URL: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [DocLinksStart](./kibana-plugin-public.doclinksstart.md) > [ELASTIC\_WEBSITE\_URL](./kibana-plugin-public.doclinksstart.elastic_website_url.md) + +## DocLinksStart.ELASTIC\_WEBSITE\_URL property + +Signature: + +```typescript +readonly ELASTIC_WEBSITE_URL: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-public.doclinksstart.links.md index 9e662c543eb56d..bb59d2eabefa2b 100644 --- a/docs/development/core/public/kibana-plugin-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-public.doclinksstart.links.md @@ -1,95 +1,96 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [DocLinksStart](./kibana-plugin-public.doclinksstart.md) > [links](./kibana-plugin-public.doclinksstart.links.md) - -## DocLinksStart.links property - -Signature: - -```typescript -readonly links: { - readonly filebeat: { - readonly base: string; - readonly installation: string; - readonly configuration: string; - readonly elasticsearchOutput: string; - readonly startup: string; - readonly exportedFields: string; - }; - readonly auditbeat: { - readonly base: string; - }; - readonly metricbeat: { - readonly base: string; - }; - readonly heartbeat: { - readonly base: string; - }; - readonly logstash: { - readonly base: string; - }; - readonly functionbeat: { - readonly base: string; - }; - readonly winlogbeat: { - readonly base: string; - }; - readonly aggs: { - readonly date_histogram: string; - readonly date_range: 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 scriptedFields: { - readonly scriptFields: string; - readonly scriptAggs: string; - readonly painless: string; - readonly painlessApi: string; - readonly painlessSyntax: string; - readonly luceneExpressions: string; - }; - readonly indexPatterns: { - readonly loadingData: string; - readonly introduction: string; - }; - readonly kibana: string; - readonly siem: { - readonly guide: string; - readonly gettingStarted: string; - }; - readonly query: { - readonly luceneQuerySyntax: string; - readonly queryDsl: string; - readonly kueryQuerySyntax: string; - }; - readonly date: { - readonly dateMath: string; - }; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [DocLinksStart](./kibana-plugin-public.doclinksstart.md) > [links](./kibana-plugin-public.doclinksstart.links.md) + +## DocLinksStart.links property + +Signature: + +```typescript +readonly links: { + readonly filebeat: { + readonly base: string; + readonly installation: string; + readonly configuration: string; + readonly elasticsearchOutput: string; + readonly startup: string; + readonly exportedFields: string; + }; + readonly auditbeat: { + readonly base: string; + }; + readonly metricbeat: { + readonly base: string; + }; + readonly heartbeat: { + readonly base: string; + }; + readonly logstash: { + readonly base: string; + }; + readonly functionbeat: { + readonly base: string; + }; + readonly winlogbeat: { + readonly base: string; + }; + readonly aggs: { + readonly date_histogram: string; + readonly date_range: 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 scriptedFields: { + readonly scriptFields: string; + readonly scriptAggs: string; + readonly painless: string; + readonly painlessApi: string; + readonly painlessSyntax: string; + readonly luceneExpressions: string; + }; + readonly indexPatterns: { + readonly loadingData: string; + readonly introduction: string; + }; + readonly kibana: string; + readonly siem: { + readonly guide: string; + readonly gettingStarted: string; + }; + readonly query: { + readonly luceneQuerySyntax: string; + readonly queryDsl: string; + readonly kueryQuerySyntax: string; + }; + readonly date: { + readonly dateMath: string; + }; + readonly management: Record; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-public.doclinksstart.md index cefac180d88c5b..c9d9c0f06ecb36 100644 --- a/docs/development/core/public/kibana-plugin-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-public.doclinksstart.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [DocLinksStart](./kibana-plugin-public.doclinksstart.md) - -## DocLinksStart interface - - -Signature: - -```typescript -export interface DocLinksStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [DOC\_LINK\_VERSION](./kibana-plugin-public.doclinksstart.doc_link_version.md) | string | | -| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-public.doclinksstart.links.md) | {
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: 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 scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
} | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [DocLinksStart](./kibana-plugin-public.doclinksstart.md) + +## DocLinksStart interface + + +Signature: + +```typescript +export interface DocLinksStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [DOC\_LINK\_VERSION](./kibana-plugin-public.doclinksstart.doc_link_version.md) | string | | +| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-public.doclinksstart.elastic_website_url.md) | string | | +| [links](./kibana-plugin-public.doclinksstart.links.md) | {
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: 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 scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
} | | + diff --git a/docs/development/core/public/kibana-plugin-public.environmentmode.dev.md b/docs/development/core/public/kibana-plugin-public.environmentmode.dev.md index b82e851da2b66f..1e070ba8d9884c 100644 --- a/docs/development/core/public/kibana-plugin-public.environmentmode.dev.md +++ b/docs/development/core/public/kibana-plugin-public.environmentmode.dev.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [EnvironmentMode](./kibana-plugin-public.environmentmode.md) > [dev](./kibana-plugin-public.environmentmode.dev.md) - -## EnvironmentMode.dev property - -Signature: - -```typescript -dev: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [EnvironmentMode](./kibana-plugin-public.environmentmode.md) > [dev](./kibana-plugin-public.environmentmode.dev.md) + +## EnvironmentMode.dev property + +Signature: + +```typescript +dev: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.environmentmode.md b/docs/development/core/public/kibana-plugin-public.environmentmode.md index 14ab1316f52690..e869729319b0c4 100644 --- a/docs/development/core/public/kibana-plugin-public.environmentmode.md +++ b/docs/development/core/public/kibana-plugin-public.environmentmode.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [EnvironmentMode](./kibana-plugin-public.environmentmode.md) - -## EnvironmentMode interface - - -Signature: - -```typescript -export interface EnvironmentMode -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [dev](./kibana-plugin-public.environmentmode.dev.md) | boolean | | -| [name](./kibana-plugin-public.environmentmode.name.md) | 'development' | 'production' | | -| [prod](./kibana-plugin-public.environmentmode.prod.md) | boolean | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [EnvironmentMode](./kibana-plugin-public.environmentmode.md) + +## EnvironmentMode interface + + +Signature: + +```typescript +export interface EnvironmentMode +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [dev](./kibana-plugin-public.environmentmode.dev.md) | boolean | | +| [name](./kibana-plugin-public.environmentmode.name.md) | 'development' | 'production' | | +| [prod](./kibana-plugin-public.environmentmode.prod.md) | boolean | | + diff --git a/docs/development/core/public/kibana-plugin-public.environmentmode.name.md b/docs/development/core/public/kibana-plugin-public.environmentmode.name.md index 5983fea856750f..105853c35d0ddf 100644 --- a/docs/development/core/public/kibana-plugin-public.environmentmode.name.md +++ b/docs/development/core/public/kibana-plugin-public.environmentmode.name.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [EnvironmentMode](./kibana-plugin-public.environmentmode.md) > [name](./kibana-plugin-public.environmentmode.name.md) - -## EnvironmentMode.name property - -Signature: - -```typescript -name: 'development' | 'production'; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [EnvironmentMode](./kibana-plugin-public.environmentmode.md) > [name](./kibana-plugin-public.environmentmode.name.md) + +## EnvironmentMode.name property + +Signature: + +```typescript +name: 'development' | 'production'; +``` diff --git a/docs/development/core/public/kibana-plugin-public.environmentmode.prod.md b/docs/development/core/public/kibana-plugin-public.environmentmode.prod.md index 4b46e8b9cc9f96..ebbbf7f0c25315 100644 --- a/docs/development/core/public/kibana-plugin-public.environmentmode.prod.md +++ b/docs/development/core/public/kibana-plugin-public.environmentmode.prod.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [EnvironmentMode](./kibana-plugin-public.environmentmode.md) > [prod](./kibana-plugin-public.environmentmode.prod.md) - -## EnvironmentMode.prod property - -Signature: - -```typescript -prod: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [EnvironmentMode](./kibana-plugin-public.environmentmode.md) > [prod](./kibana-plugin-public.environmentmode.prod.md) + +## EnvironmentMode.prod property + +Signature: + +```typescript +prod: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.errortoastoptions.md b/docs/development/core/public/kibana-plugin-public.errortoastoptions.md index 1755e6cbde9195..2018bcb6439063 100644 --- a/docs/development/core/public/kibana-plugin-public.errortoastoptions.md +++ b/docs/development/core/public/kibana-plugin-public.errortoastoptions.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) - -## ErrorToastOptions interface - -Options available for [IToasts](./kibana-plugin-public.itoasts.md) APIs. - -Signature: - -```typescript -export interface ErrorToastOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [title](./kibana-plugin-public.errortoastoptions.title.md) | string | The title of the toast and the dialog when expanding the message. | -| [toastMessage](./kibana-plugin-public.errortoastoptions.toastmessage.md) | string | The message to be shown in the toast. If this is not specified the error's message will be shown in the toast instead. Overwriting that message can be used to provide more user-friendly toasts. If you specify this, the error message will still be shown in the detailed error modal. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) + +## ErrorToastOptions interface + +Options available for [IToasts](./kibana-plugin-public.itoasts.md) APIs. + +Signature: + +```typescript +export interface ErrorToastOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [title](./kibana-plugin-public.errortoastoptions.title.md) | string | The title of the toast and the dialog when expanding the message. | +| [toastMessage](./kibana-plugin-public.errortoastoptions.toastmessage.md) | string | The message to be shown in the toast. If this is not specified the error's message will be shown in the toast instead. Overwriting that message can be used to provide more user-friendly toasts. If you specify this, the error message will still be shown in the detailed error modal. | + diff --git a/docs/development/core/public/kibana-plugin-public.errortoastoptions.title.md b/docs/development/core/public/kibana-plugin-public.errortoastoptions.title.md index 8c636998bcbd78..3e21fc1e7f5996 100644 --- a/docs/development/core/public/kibana-plugin-public.errortoastoptions.title.md +++ b/docs/development/core/public/kibana-plugin-public.errortoastoptions.title.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) > [title](./kibana-plugin-public.errortoastoptions.title.md) - -## ErrorToastOptions.title property - -The title of the toast and the dialog when expanding the message. - -Signature: - -```typescript -title: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) > [title](./kibana-plugin-public.errortoastoptions.title.md) + +## ErrorToastOptions.title property + +The title of the toast and the dialog when expanding the message. + +Signature: + +```typescript +title: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.errortoastoptions.toastmessage.md b/docs/development/core/public/kibana-plugin-public.errortoastoptions.toastmessage.md index 8094ed3a5bdc7c..633bff7dae7f99 100644 --- a/docs/development/core/public/kibana-plugin-public.errortoastoptions.toastmessage.md +++ b/docs/development/core/public/kibana-plugin-public.errortoastoptions.toastmessage.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) > [toastMessage](./kibana-plugin-public.errortoastoptions.toastmessage.md) - -## ErrorToastOptions.toastMessage property - -The message to be shown in the toast. If this is not specified the error's message will be shown in the toast instead. Overwriting that message can be used to provide more user-friendly toasts. If you specify this, the error message will still be shown in the detailed error modal. - -Signature: - -```typescript -toastMessage?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) > [toastMessage](./kibana-plugin-public.errortoastoptions.toastmessage.md) + +## ErrorToastOptions.toastMessage property + +The message to be shown in the toast. If this is not specified the error's message will be shown in the toast instead. Overwriting that message can be used to provide more user-friendly toasts. If you specify this, the error message will still be shown in the detailed error modal. + +Signature: + +```typescript +toastMessage?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.md b/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.md index a1e2a95ec9bb1d..9ee6ed00d897e0 100644 --- a/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.md +++ b/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) - -## FatalErrorInfo interface - -Represents the `message` and `stack` of a fatal Error - -Signature: - -```typescript -export interface FatalErrorInfo -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [message](./kibana-plugin-public.fatalerrorinfo.message.md) | string | | -| [stack](./kibana-plugin-public.fatalerrorinfo.stack.md) | string | undefined | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) + +## FatalErrorInfo interface + +Represents the `message` and `stack` of a fatal Error + +Signature: + +```typescript +export interface FatalErrorInfo +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [message](./kibana-plugin-public.fatalerrorinfo.message.md) | string | | +| [stack](./kibana-plugin-public.fatalerrorinfo.stack.md) | string | undefined | | + diff --git a/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.message.md b/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.message.md index 8eebba48f07774..29c338580ceb49 100644 --- a/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.message.md +++ b/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.message.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) > [message](./kibana-plugin-public.fatalerrorinfo.message.md) - -## FatalErrorInfo.message property - -Signature: - -```typescript -message: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) > [message](./kibana-plugin-public.fatalerrorinfo.message.md) + +## FatalErrorInfo.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.stack.md b/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.stack.md index 5578e4f8c8acd7..5d24ec6d82c593 100644 --- a/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.stack.md +++ b/docs/development/core/public/kibana-plugin-public.fatalerrorinfo.stack.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) > [stack](./kibana-plugin-public.fatalerrorinfo.stack.md) - -## FatalErrorInfo.stack property - -Signature: - -```typescript -stack: string | undefined; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) > [stack](./kibana-plugin-public.fatalerrorinfo.stack.md) + +## FatalErrorInfo.stack property + +Signature: + +```typescript +stack: string | undefined; +``` diff --git a/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.add.md b/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.add.md index 31a1c239388ee0..778b945de848ab 100644 --- a/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.add.md +++ b/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.add.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) > [add](./kibana-plugin-public.fatalerrorssetup.add.md) - -## FatalErrorsSetup.add property - -Add a new fatal error. This will stop the Kibana Public Core and display a fatal error screen with details about the Kibana build and the error. - -Signature: - -```typescript -add: (error: string | Error, source?: string) => never; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) > [add](./kibana-plugin-public.fatalerrorssetup.add.md) + +## FatalErrorsSetup.add property + +Add a new fatal error. This will stop the Kibana Public Core and display a fatal error screen with details about the Kibana build and the error. + +Signature: + +```typescript +add: (error: string | Error, source?: string) => never; +``` diff --git a/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.get_.md b/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.get_.md index a3498e58c33b6b..c99c78ef948df4 100644 --- a/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.get_.md +++ b/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.get_.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) > [get$](./kibana-plugin-public.fatalerrorssetup.get_.md) - -## FatalErrorsSetup.get$ property - -An Observable that will emit whenever a fatal error is added with `add()` - -Signature: - -```typescript -get$: () => Rx.Observable; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) > [get$](./kibana-plugin-public.fatalerrorssetup.get_.md) + +## FatalErrorsSetup.get$ property + +An Observable that will emit whenever a fatal error is added with `add()` + +Signature: + +```typescript +get$: () => Rx.Observable; +``` diff --git a/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.md b/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.md index 87d637bb521838..728723c3f9764e 100644 --- a/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.md +++ b/docs/development/core/public/kibana-plugin-public.fatalerrorssetup.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) - -## FatalErrorsSetup interface - -FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. - -Signature: - -```typescript -export interface FatalErrorsSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [add](./kibana-plugin-public.fatalerrorssetup.add.md) | (error: string | Error, source?: string) => never | Add a new fatal error. This will stop the Kibana Public Core and display a fatal error screen with details about the Kibana build and the error. | -| [get$](./kibana-plugin-public.fatalerrorssetup.get_.md) | () => Rx.Observable<FatalErrorInfo> | An Observable that will emit whenever a fatal error is added with add() | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) + +## FatalErrorsSetup interface + +FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. + +Signature: + +```typescript +export interface FatalErrorsSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [add](./kibana-plugin-public.fatalerrorssetup.add.md) | (error: string | Error, source?: string) => never | Add a new fatal error. This will stop the Kibana Public Core and display a fatal error screen with details about the Kibana build and the error. | +| [get$](./kibana-plugin-public.fatalerrorssetup.get_.md) | () => Rx.Observable<FatalErrorInfo> | An Observable that will emit whenever a fatal error is added with add() | + diff --git a/docs/development/core/public/kibana-plugin-public.fatalerrorsstart.md b/docs/development/core/public/kibana-plugin-public.fatalerrorsstart.md new file mode 100644 index 00000000000000..93579079fe9b27 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.fatalerrorsstart.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [FatalErrorsStart](./kibana-plugin-public.fatalerrorsstart.md) + +## FatalErrorsStart type + +FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. + +Signature: + +```typescript +export declare type FatalErrorsStart = FatalErrorsSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.handlercontexttype.md b/docs/development/core/public/kibana-plugin-public.handlercontexttype.md index b083449d2b703f..561b5fb483ff0e 100644 --- a/docs/development/core/public/kibana-plugin-public.handlercontexttype.md +++ b/docs/development/core/public/kibana-plugin-public.handlercontexttype.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) - -## HandlerContextType type - -Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. - -Signature: - -```typescript -export declare type HandlerContextType> = T extends HandlerFunction ? U : never; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) + +## HandlerContextType type + +Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. + +Signature: + +```typescript +export declare type HandlerContextType> = T extends HandlerFunction ? U : never; +``` diff --git a/docs/development/core/public/kibana-plugin-public.handlerfunction.md b/docs/development/core/public/kibana-plugin-public.handlerfunction.md index 98c342c17691d9..973dbc6837325b 100644 --- a/docs/development/core/public/kibana-plugin-public.handlerfunction.md +++ b/docs/development/core/public/kibana-plugin-public.handlerfunction.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerFunction](./kibana-plugin-public.handlerfunction.md) - -## HandlerFunction type - -A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) - -Signature: - -```typescript -export declare type HandlerFunction = (context: T, ...args: any[]) => any; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerFunction](./kibana-plugin-public.handlerfunction.md) + +## HandlerFunction type + +A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) + +Signature: + +```typescript +export declare type HandlerFunction = (context: T, ...args: any[]) => any; +``` diff --git a/docs/development/core/public/kibana-plugin-public.handlerparameters.md b/docs/development/core/public/kibana-plugin-public.handlerparameters.md index f46c4b649e9436..8a9e51b66e71eb 100644 --- a/docs/development/core/public/kibana-plugin-public.handlerparameters.md +++ b/docs/development/core/public/kibana-plugin-public.handlerparameters.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerParameters](./kibana-plugin-public.handlerparameters.md) - -## HandlerParameters type - -Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). - -Signature: - -```typescript -export declare type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerParameters](./kibana-plugin-public.handlerparameters.md) + +## HandlerParameters type + +Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). + +Signature: + +```typescript +export declare type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httperrorrequest.error.md b/docs/development/core/public/kibana-plugin-public.httperrorrequest.error.md deleted file mode 100644 index a8b511f889cdf5..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.httperrorrequest.error.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpErrorRequest](./kibana-plugin-public.httperrorrequest.md) > [error](./kibana-plugin-public.httperrorrequest.error.md) - -## HttpErrorRequest.error property - -Signature: - -```typescript -error: Error; -``` diff --git a/docs/development/core/public/kibana-plugin-public.httperrorrequest.md b/docs/development/core/public/kibana-plugin-public.httperrorrequest.md deleted file mode 100644 index e28d092eda71d7..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.httperrorrequest.md +++ /dev/null @@ -1,20 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpErrorRequest](./kibana-plugin-public.httperrorrequest.md) - -## HttpErrorRequest interface - - -Signature: - -```typescript -export interface HttpErrorRequest -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [error](./kibana-plugin-public.httperrorrequest.error.md) | Error | | -| [request](./kibana-plugin-public.httperrorrequest.request.md) | Request | | - diff --git a/docs/development/core/public/kibana-plugin-public.httperrorrequest.request.md b/docs/development/core/public/kibana-plugin-public.httperrorrequest.request.md deleted file mode 100644 index 7a94eeb91bbc81..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.httperrorrequest.request.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpErrorRequest](./kibana-plugin-public.httperrorrequest.md) > [request](./kibana-plugin-public.httperrorrequest.request.md) - -## HttpErrorRequest.request property - -Signature: - -```typescript -request: Request; -``` diff --git a/docs/development/core/public/kibana-plugin-public.httperrorresponse.error.md b/docs/development/core/public/kibana-plugin-public.httperrorresponse.error.md deleted file mode 100644 index 59eee87cb70ba7..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.httperrorresponse.error.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpErrorResponse](./kibana-plugin-public.httperrorresponse.md) > [error](./kibana-plugin-public.httperrorresponse.error.md) - -## HttpErrorResponse.error property - -Signature: - -```typescript -error: Error | IHttpFetchError; -``` diff --git a/docs/development/core/public/kibana-plugin-public.httperrorresponse.md b/docs/development/core/public/kibana-plugin-public.httperrorresponse.md deleted file mode 100644 index 5b1ee898a444d6..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.httperrorresponse.md +++ /dev/null @@ -1,19 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpErrorResponse](./kibana-plugin-public.httperrorresponse.md) - -## HttpErrorResponse interface - - -Signature: - -```typescript -export interface HttpErrorResponse extends IHttpResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [error](./kibana-plugin-public.httperrorresponse.error.md) | Error | IHttpFetchError | | - diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.asresponse.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.asresponse.md index 250cf83309b3c4..f1661cdb64b4a4 100644 --- a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.asresponse.md +++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.asresponse.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [asResponse](./kibana-plugin-public.httpfetchoptions.asresponse.md) - -## HttpFetchOptions.asResponse property - -When `true` the return type of [HttpHandler](./kibana-plugin-public.httphandler.md) will be an [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) with detailed request and response information. When `false`, the return type will just be the parsed response body. Defaults to `false`. - -Signature: - -```typescript -asResponse?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [asResponse](./kibana-plugin-public.httpfetchoptions.asresponse.md) + +## HttpFetchOptions.asResponse property + +When `true` the return type of [HttpHandler](./kibana-plugin-public.httphandler.md) will be an [HttpResponse](./kibana-plugin-public.httpresponse.md) with detailed request and response information. When `false`, the return type will just be the parsed response body. Defaults to `false`. + +Signature: + +```typescript +asResponse?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.assystemrequest.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.assystemrequest.md new file mode 100644 index 00000000000000..609e4dd410601b --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.assystemrequest.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [asSystemRequest](./kibana-plugin-public.httpfetchoptions.assystemrequest.md) + +## HttpFetchOptions.asSystemRequest property + +Whether or not the request should include the "system request" header to differentiate an end user request from Kibana internal request. Can be read on the server-side using KibanaRequest\#isSystemRequest. Defaults to `false`. + +Signature: + +```typescript +asSystemRequest?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.headers.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.headers.md index 232b7d3da3af42..4943f594e14cc8 100644 --- a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.headers.md +++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.headers.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [headers](./kibana-plugin-public.httpfetchoptions.headers.md) - -## HttpFetchOptions.headers property - -Headers to send with the request. See [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md). - -Signature: - -```typescript -headers?: HttpHeadersInit; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [headers](./kibana-plugin-public.httpfetchoptions.headers.md) + +## HttpFetchOptions.headers property + +Headers to send with the request. See [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md). + +Signature: + +```typescript +headers?: HttpHeadersInit; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.md index 6a0c4a8a7f1379..b7620f9e042dbc 100644 --- a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.md +++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.md @@ -1,23 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) - -## HttpFetchOptions interface - -All options that may be used with a [HttpHandler](./kibana-plugin-public.httphandler.md). - -Signature: - -```typescript -export interface HttpFetchOptions extends HttpRequestInit -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [asResponse](./kibana-plugin-public.httpfetchoptions.asresponse.md) | boolean | When true the return type of [HttpHandler](./kibana-plugin-public.httphandler.md) will be an [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) with detailed request and response information. When false, the return type will just be the parsed response body. Defaults to false. | -| [headers](./kibana-plugin-public.httpfetchoptions.headers.md) | HttpHeadersInit | Headers to send with the request. See [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md). | -| [prependBasePath](./kibana-plugin-public.httpfetchoptions.prependbasepath.md) | boolean | Whether or not the request should automatically prepend the basePath. Defaults to true. | -| [query](./kibana-plugin-public.httpfetchoptions.query.md) | HttpFetchQuery | The query string for an HTTP request. See [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md). | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) + +## HttpFetchOptions interface + +All options that may be used with a [HttpHandler](./kibana-plugin-public.httphandler.md). + +Signature: + +```typescript +export interface HttpFetchOptions extends HttpRequestInit +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [asResponse](./kibana-plugin-public.httpfetchoptions.asresponse.md) | boolean | When true the return type of [HttpHandler](./kibana-plugin-public.httphandler.md) will be an [HttpResponse](./kibana-plugin-public.httpresponse.md) with detailed request and response information. When false, the return type will just be the parsed response body. Defaults to false. | +| [asSystemRequest](./kibana-plugin-public.httpfetchoptions.assystemrequest.md) | boolean | Whether or not the request should include the "system request" header to differentiate an end user request from Kibana internal request. Can be read on the server-side using KibanaRequest\#isSystemRequest. Defaults to false. | +| [headers](./kibana-plugin-public.httpfetchoptions.headers.md) | HttpHeadersInit | Headers to send with the request. See [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md). | +| [prependBasePath](./kibana-plugin-public.httpfetchoptions.prependbasepath.md) | boolean | Whether or not the request should automatically prepend the basePath. Defaults to true. | +| [query](./kibana-plugin-public.httpfetchoptions.query.md) | HttpFetchQuery | The query string for an HTTP request. See [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md). | + diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.prependbasepath.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.prependbasepath.md index 0a6a8e195e565a..bebf99e25bbfc9 100644 --- a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.prependbasepath.md +++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.prependbasepath.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [prependBasePath](./kibana-plugin-public.httpfetchoptions.prependbasepath.md) - -## HttpFetchOptions.prependBasePath property - -Whether or not the request should automatically prepend the basePath. Defaults to `true`. - -Signature: - -```typescript -prependBasePath?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [prependBasePath](./kibana-plugin-public.httpfetchoptions.prependbasepath.md) + +## HttpFetchOptions.prependBasePath property + +Whether or not the request should automatically prepend the basePath. Defaults to `true`. + +Signature: + +```typescript +prependBasePath?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.query.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.query.md index 0f8d6ba83e7726..bae4edd22dd46e 100644 --- a/docs/development/core/public/kibana-plugin-public.httpfetchoptions.query.md +++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptions.query.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [query](./kibana-plugin-public.httpfetchoptions.query.md) - -## HttpFetchOptions.query property - -The query string for an HTTP request. See [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md). - -Signature: - -```typescript -query?: HttpFetchQuery; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) > [query](./kibana-plugin-public.httpfetchoptions.query.md) + +## HttpFetchOptions.query property + +The query string for an HTTP request. See [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md). + +Signature: + +```typescript +query?: HttpFetchQuery; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptionswithpath.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptionswithpath.md new file mode 100644 index 00000000000000..5c27122e07ba79 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptionswithpath.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptionsWithPath](./kibana-plugin-public.httpfetchoptionswithpath.md) + +## HttpFetchOptionsWithPath interface + +Similar to [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) but with the URL path included. + +Signature: + +```typescript +export interface HttpFetchOptionsWithPath extends HttpFetchOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [path](./kibana-plugin-public.httpfetchoptionswithpath.path.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchoptionswithpath.path.md b/docs/development/core/public/kibana-plugin-public.httpfetchoptionswithpath.path.md new file mode 100644 index 00000000000000..be84a6315564ee --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpfetchoptionswithpath.path.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchOptionsWithPath](./kibana-plugin-public.httpfetchoptionswithpath.md) > [path](./kibana-plugin-public.httpfetchoptionswithpath.path.md) + +## HttpFetchOptionsWithPath.path property + +Signature: + +```typescript +path: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpfetchquery.md b/docs/development/core/public/kibana-plugin-public.httpfetchquery.md index e09b22b0744535..d270ceab915324 100644 --- a/docs/development/core/public/kibana-plugin-public.httpfetchquery.md +++ b/docs/development/core/public/kibana-plugin-public.httpfetchquery.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md) - -## HttpFetchQuery interface - - -Signature: - -```typescript -export interface HttpFetchQuery -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md) + +## HttpFetchQuery interface + + +Signature: + +```typescript +export interface HttpFetchQuery +``` diff --git a/docs/development/core/public/kibana-plugin-public.httphandler.md b/docs/development/core/public/kibana-plugin-public.httphandler.md index 89458c4743cd6e..09d98fe97557f8 100644 --- a/docs/development/core/public/kibana-plugin-public.httphandler.md +++ b/docs/development/core/public/kibana-plugin-public.httphandler.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpHandler](./kibana-plugin-public.httphandler.md) - -## HttpHandler interface - -A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) for the response. - -Signature: - -```typescript -export interface HttpHandler -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpHandler](./kibana-plugin-public.httphandler.md) + +## HttpHandler interface + +A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [HttpResponse](./kibana-plugin-public.httpresponse.md) for the response. + +Signature: + +```typescript +export interface HttpHandler +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpheadersinit.md b/docs/development/core/public/kibana-plugin-public.httpheadersinit.md index 15877a55fcddc8..a0d5fec388f872 100644 --- a/docs/development/core/public/kibana-plugin-public.httpheadersinit.md +++ b/docs/development/core/public/kibana-plugin-public.httpheadersinit.md @@ -1,12 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) - -## HttpHeadersInit interface - - -Signature: - -```typescript -export interface HttpHeadersInit -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) + +## HttpHeadersInit interface + +Headers to append to the request. Any headers that begin with `kbn-` are considered private to Core and will cause [HttpHandler](./kibana-plugin-public.httphandler.md) to throw an error. + +Signature: + +```typescript +export interface HttpHeadersInit +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptor.md b/docs/development/core/public/kibana-plugin-public.httpinterceptor.md index cf7288a492ebb2..1cf782b1ba749c 100644 --- a/docs/development/core/public/kibana-plugin-public.httpinterceptor.md +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptor.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) - -## HttpInterceptor interface - -An object that may define global interceptor functions for different parts of the request and response lifecycle. See [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md). - -Signature: - -```typescript -export interface HttpInterceptor -``` - -## Methods - -| Method | Description | -| --- | --- | -| [request(request, controller)](./kibana-plugin-public.httpinterceptor.request.md) | Define an interceptor to be executed before a request is sent. | -| [requestError(httpErrorRequest, controller)](./kibana-plugin-public.httpinterceptor.requesterror.md) | Define an interceptor to be executed if a request interceptor throws an error or returns a rejected Promise. | -| [response(httpResponse, controller)](./kibana-plugin-public.httpinterceptor.response.md) | Define an interceptor to be executed after a response is received. | -| [responseError(httpErrorResponse, controller)](./kibana-plugin-public.httpinterceptor.responseerror.md) | Define an interceptor to be executed if a response interceptor throws an error or returns a rejected Promise. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) + +## HttpInterceptor interface + +An object that may define global interceptor functions for different parts of the request and response lifecycle. See [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md). + +Signature: + +```typescript +export interface HttpInterceptor +``` + +## Methods + +| Method | Description | +| --- | --- | +| [request(fetchOptions, controller)](./kibana-plugin-public.httpinterceptor.request.md) | Define an interceptor to be executed before a request is sent. | +| [requestError(httpErrorRequest, controller)](./kibana-plugin-public.httpinterceptor.requesterror.md) | Define an interceptor to be executed if a request interceptor throws an error or returns a rejected Promise. | +| [response(httpResponse, controller)](./kibana-plugin-public.httpinterceptor.response.md) | Define an interceptor to be executed after a response is received. | +| [responseError(httpErrorResponse, controller)](./kibana-plugin-public.httpinterceptor.responseerror.md) | Define an interceptor to be executed if a response interceptor throws an error or returns a rejected Promise. | + diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptor.request.md b/docs/development/core/public/kibana-plugin-public.httpinterceptor.request.md index 4254e4aa8950c1..8a6812f40e4cd2 100644 --- a/docs/development/core/public/kibana-plugin-public.httpinterceptor.request.md +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptor.request.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) > [request](./kibana-plugin-public.httpinterceptor.request.md) - -## HttpInterceptor.request() method - -Define an interceptor to be executed before a request is sent. - -Signature: - -```typescript -request?(request: Request, controller: IHttpInterceptController): Promise | Request | void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | Request | | -| controller | IHttpInterceptController | | - -Returns: - -`Promise | Request | void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) > [request](./kibana-plugin-public.httpinterceptor.request.md) + +## HttpInterceptor.request() method + +Define an interceptor to be executed before a request is sent. + +Signature: + +```typescript +request?(fetchOptions: Readonly, controller: IHttpInterceptController): MaybePromise> | void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fetchOptions | Readonly<HttpFetchOptionsWithPath> | | +| controller | IHttpInterceptController | | + +Returns: + +`MaybePromise> | void` + diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptor.requesterror.md b/docs/development/core/public/kibana-plugin-public.httpinterceptor.requesterror.md index af9b8641e74736..7bb9202aa905ec 100644 --- a/docs/development/core/public/kibana-plugin-public.httpinterceptor.requesterror.md +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptor.requesterror.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) > [requestError](./kibana-plugin-public.httpinterceptor.requesterror.md) - -## HttpInterceptor.requestError() method - -Define an interceptor to be executed if a request interceptor throws an error or returns a rejected Promise. - -Signature: - -```typescript -requestError?(httpErrorRequest: HttpErrorRequest, controller: IHttpInterceptController): Promise | Request | void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| httpErrorRequest | HttpErrorRequest | | -| controller | IHttpInterceptController | | - -Returns: - -`Promise | Request | void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) > [requestError](./kibana-plugin-public.httpinterceptor.requesterror.md) + +## HttpInterceptor.requestError() method + +Define an interceptor to be executed if a request interceptor throws an error or returns a rejected Promise. + +Signature: + +```typescript +requestError?(httpErrorRequest: HttpInterceptorRequestError, controller: IHttpInterceptController): MaybePromise> | void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| httpErrorRequest | HttpInterceptorRequestError | | +| controller | IHttpInterceptController | | + +Returns: + +`MaybePromise> | void` + diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptor.response.md b/docs/development/core/public/kibana-plugin-public.httpinterceptor.response.md index 3a67dcbad3119b..12a5b36090abc1 100644 --- a/docs/development/core/public/kibana-plugin-public.httpinterceptor.response.md +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptor.response.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) > [response](./kibana-plugin-public.httpinterceptor.response.md) - -## HttpInterceptor.response() method - -Define an interceptor to be executed after a response is received. - -Signature: - -```typescript -response?(httpResponse: IHttpResponse, controller: IHttpInterceptController): Promise | IHttpResponseInterceptorOverrides | void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| httpResponse | IHttpResponse | | -| controller | IHttpInterceptController | | - -Returns: - -`Promise | IHttpResponseInterceptorOverrides | void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) > [response](./kibana-plugin-public.httpinterceptor.response.md) + +## HttpInterceptor.response() method + +Define an interceptor to be executed after a response is received. + +Signature: + +```typescript +response?(httpResponse: HttpResponse, controller: IHttpInterceptController): MaybePromise | void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| httpResponse | HttpResponse | | +| controller | IHttpInterceptController | | + +Returns: + +`MaybePromise | void` + diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptor.responseerror.md b/docs/development/core/public/kibana-plugin-public.httpinterceptor.responseerror.md index 476ceba649d402..d3c2b6db128c15 100644 --- a/docs/development/core/public/kibana-plugin-public.httpinterceptor.responseerror.md +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptor.responseerror.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) > [responseError](./kibana-plugin-public.httpinterceptor.responseerror.md) - -## HttpInterceptor.responseError() method - -Define an interceptor to be executed if a response interceptor throws an error or returns a rejected Promise. - -Signature: - -```typescript -responseError?(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptController): Promise | IHttpResponseInterceptorOverrides | void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| httpErrorResponse | HttpErrorResponse | | -| controller | IHttpInterceptController | | - -Returns: - -`Promise | IHttpResponseInterceptorOverrides | void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) > [responseError](./kibana-plugin-public.httpinterceptor.responseerror.md) + +## HttpInterceptor.responseError() method + +Define an interceptor to be executed if a response interceptor throws an error or returns a rejected Promise. + +Signature: + +```typescript +responseError?(httpErrorResponse: HttpInterceptorResponseError, controller: IHttpInterceptController): MaybePromise | void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| httpErrorResponse | HttpInterceptorResponseError | | +| controller | IHttpInterceptController | | + +Returns: + +`MaybePromise | void` + diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.error.md b/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.error.md new file mode 100644 index 00000000000000..2eeafffb8d5566 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.error.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptorRequestError](./kibana-plugin-public.httpinterceptorrequesterror.md) > [error](./kibana-plugin-public.httpinterceptorrequesterror.error.md) + +## HttpInterceptorRequestError.error property + +Signature: + +```typescript +error: Error; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.fetchoptions.md b/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.fetchoptions.md new file mode 100644 index 00000000000000..31a7f8ef44d9f5 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.fetchoptions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptorRequestError](./kibana-plugin-public.httpinterceptorrequesterror.md) > [fetchOptions](./kibana-plugin-public.httpinterceptorrequesterror.fetchoptions.md) + +## HttpInterceptorRequestError.fetchOptions property + +Signature: + +```typescript +fetchOptions: Readonly; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.md b/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.md new file mode 100644 index 00000000000000..4174523ed5fa6a --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptorrequesterror.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptorRequestError](./kibana-plugin-public.httpinterceptorrequesterror.md) + +## HttpInterceptorRequestError interface + + +Signature: + +```typescript +export interface HttpInterceptorRequestError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [error](./kibana-plugin-public.httpinterceptorrequesterror.error.md) | Error | | +| [fetchOptions](./kibana-plugin-public.httpinterceptorrequesterror.fetchoptions.md) | Readonly<HttpFetchOptionsWithPath> | | + diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.error.md b/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.error.md new file mode 100644 index 00000000000000..c1367ccdd580e7 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.error.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptorResponseError](./kibana-plugin-public.httpinterceptorresponseerror.md) > [error](./kibana-plugin-public.httpinterceptorresponseerror.error.md) + +## HttpInterceptorResponseError.error property + +Signature: + +```typescript +error: Error | IHttpFetchError; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.md b/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.md new file mode 100644 index 00000000000000..d306f9c6096bd0 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptorResponseError](./kibana-plugin-public.httpinterceptorresponseerror.md) + +## HttpInterceptorResponseError interface + + +Signature: + +```typescript +export interface HttpInterceptorResponseError extends HttpResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [error](./kibana-plugin-public.httpinterceptorresponseerror.error.md) | Error | IHttpFetchError | | +| [request](./kibana-plugin-public.httpinterceptorresponseerror.request.md) | Readonly<Request> | | + diff --git a/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.request.md b/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.request.md new file mode 100644 index 00000000000000..d2f2826c042831 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpinterceptorresponseerror.request.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpInterceptorResponseError](./kibana-plugin-public.httpinterceptorresponseerror.md) > [request](./kibana-plugin-public.httpinterceptorresponseerror.request.md) + +## HttpInterceptorResponseError.request property + +Signature: + +```typescript +request: Readonly; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.body.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.body.md index 44b33c99175430..ba0075787e5d14 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.body.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.body.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [body](./kibana-plugin-public.httprequestinit.body.md) - -## HttpRequestInit.body property - -A BodyInit object or null to set request's body. - -Signature: - -```typescript -body?: BodyInit | null; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [body](./kibana-plugin-public.httprequestinit.body.md) + +## HttpRequestInit.body property + +A BodyInit object or null to set request's body. + +Signature: + +```typescript +body?: BodyInit | null; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.cache.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.cache.md index 0f9dff3887ccf5..bb9071aa45aec2 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.cache.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.cache.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [cache](./kibana-plugin-public.httprequestinit.cache.md) - -## HttpRequestInit.cache property - -The cache mode associated with request, which is a string indicating how the request will interact with the browser's cache when fetching. - -Signature: - -```typescript -cache?: RequestCache; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [cache](./kibana-plugin-public.httprequestinit.cache.md) + +## HttpRequestInit.cache property + +The cache mode associated with request, which is a string indicating how the request will interact with the browser's cache when fetching. + +Signature: + +```typescript +cache?: RequestCache; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.credentials.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.credentials.md index 93c624cd1980cd..55355488df792f 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.credentials.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.credentials.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [credentials](./kibana-plugin-public.httprequestinit.credentials.md) - -## HttpRequestInit.credentials property - -The credentials mode associated with request, which is a string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. - -Signature: - -```typescript -credentials?: RequestCredentials; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [credentials](./kibana-plugin-public.httprequestinit.credentials.md) + +## HttpRequestInit.credentials property + +The credentials mode associated with request, which is a string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. + +Signature: + +```typescript +credentials?: RequestCredentials; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.headers.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.headers.md index 0f885ed0df1a38..f2f98eaa4451e5 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.headers.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.headers.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [headers](./kibana-plugin-public.httprequestinit.headers.md) - -## HttpRequestInit.headers property - -[HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) - -Signature: - -```typescript -headers?: HttpHeadersInit; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [headers](./kibana-plugin-public.httprequestinit.headers.md) + +## HttpRequestInit.headers property + +[HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) + +Signature: + +```typescript +headers?: HttpHeadersInit; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.integrity.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.integrity.md index 7bb1665fdfcbe8..2da1f5827a6801 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.integrity.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.integrity.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [integrity](./kibana-plugin-public.httprequestinit.integrity.md) - -## HttpRequestInit.integrity property - -Subresource integrity metadata, which is a cryptographic hash of the resource being fetched. Its value consists of multiple hashes separated by whitespace. - -Signature: - -```typescript -integrity?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [integrity](./kibana-plugin-public.httprequestinit.integrity.md) + +## HttpRequestInit.integrity property + +Subresource integrity metadata, which is a cryptographic hash of the resource being fetched. Its value consists of multiple hashes separated by whitespace. + +Signature: + +```typescript +integrity?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.keepalive.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.keepalive.md index ba256188ce338d..35a4020485bcae 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.keepalive.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.keepalive.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [keepalive](./kibana-plugin-public.httprequestinit.keepalive.md) - -## HttpRequestInit.keepalive property - -Whether or not request can outlive the global in which it was created. - -Signature: - -```typescript -keepalive?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [keepalive](./kibana-plugin-public.httprequestinit.keepalive.md) + +## HttpRequestInit.keepalive property + +Whether or not request can outlive the global in which it was created. + +Signature: + +```typescript +keepalive?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.md index 1271e039b0713c..04b57e48109f60 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.md @@ -1,32 +1,32 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) - -## HttpRequestInit interface - -Fetch API options available to [HttpHandler](./kibana-plugin-public.httphandler.md)s. - -Signature: - -```typescript -export interface HttpRequestInit -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [body](./kibana-plugin-public.httprequestinit.body.md) | BodyInit | null | A BodyInit object or null to set request's body. | -| [cache](./kibana-plugin-public.httprequestinit.cache.md) | RequestCache | The cache mode associated with request, which is a string indicating how the request will interact with the browser's cache when fetching. | -| [credentials](./kibana-plugin-public.httprequestinit.credentials.md) | RequestCredentials | The credentials mode associated with request, which is a string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. | -| [headers](./kibana-plugin-public.httprequestinit.headers.md) | HttpHeadersInit | [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) | -| [integrity](./kibana-plugin-public.httprequestinit.integrity.md) | string | Subresource integrity metadata, which is a cryptographic hash of the resource being fetched. Its value consists of multiple hashes separated by whitespace. | -| [keepalive](./kibana-plugin-public.httprequestinit.keepalive.md) | boolean | Whether or not request can outlive the global in which it was created. | -| [method](./kibana-plugin-public.httprequestinit.method.md) | string | HTTP method, which is "GET" by default. | -| [mode](./kibana-plugin-public.httprequestinit.mode.md) | RequestMode | The mode associated with request, which is a string indicating whether the request will use CORS, or will be restricted to same-origin URLs. | -| [redirect](./kibana-plugin-public.httprequestinit.redirect.md) | RequestRedirect | The redirect mode associated with request, which is a string indicating how redirects for the request will be handled during fetching. A request will follow redirects by default. | -| [referrer](./kibana-plugin-public.httprequestinit.referrer.md) | string | The referrer of request. Its value can be a same-origin URL if explicitly set in init, the empty string to indicate no referrer, and "about:client" when defaulting to the global's default. This is used during fetching to determine the value of the Referer header of the request being made. | -| [referrerPolicy](./kibana-plugin-public.httprequestinit.referrerpolicy.md) | ReferrerPolicy | The referrer policy associated with request. This is used during fetching to compute the value of the request's referrer. | -| [signal](./kibana-plugin-public.httprequestinit.signal.md) | AbortSignal | null | Returns the signal associated with request, which is an AbortSignal object indicating whether or not request has been aborted, and its abort event handler. | -| [window](./kibana-plugin-public.httprequestinit.window.md) | null | Can only be null. Used to disassociate request from any Window. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) + +## HttpRequestInit interface + +Fetch API options available to [HttpHandler](./kibana-plugin-public.httphandler.md)s. + +Signature: + +```typescript +export interface HttpRequestInit +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-public.httprequestinit.body.md) | BodyInit | null | A BodyInit object or null to set request's body. | +| [cache](./kibana-plugin-public.httprequestinit.cache.md) | RequestCache | The cache mode associated with request, which is a string indicating how the request will interact with the browser's cache when fetching. | +| [credentials](./kibana-plugin-public.httprequestinit.credentials.md) | RequestCredentials | The credentials mode associated with request, which is a string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. | +| [headers](./kibana-plugin-public.httprequestinit.headers.md) | HttpHeadersInit | [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) | +| [integrity](./kibana-plugin-public.httprequestinit.integrity.md) | string | Subresource integrity metadata, which is a cryptographic hash of the resource being fetched. Its value consists of multiple hashes separated by whitespace. | +| [keepalive](./kibana-plugin-public.httprequestinit.keepalive.md) | boolean | Whether or not request can outlive the global in which it was created. | +| [method](./kibana-plugin-public.httprequestinit.method.md) | string | HTTP method, which is "GET" by default. | +| [mode](./kibana-plugin-public.httprequestinit.mode.md) | RequestMode | The mode associated with request, which is a string indicating whether the request will use CORS, or will be restricted to same-origin URLs. | +| [redirect](./kibana-plugin-public.httprequestinit.redirect.md) | RequestRedirect | The redirect mode associated with request, which is a string indicating how redirects for the request will be handled during fetching. A request will follow redirects by default. | +| [referrer](./kibana-plugin-public.httprequestinit.referrer.md) | string | The referrer of request. Its value can be a same-origin URL if explicitly set in init, the empty string to indicate no referrer, and "about:client" when defaulting to the global's default. This is used during fetching to determine the value of the Referer header of the request being made. | +| [referrerPolicy](./kibana-plugin-public.httprequestinit.referrerpolicy.md) | ReferrerPolicy | The referrer policy associated with request. This is used during fetching to compute the value of the request's referrer. | +| [signal](./kibana-plugin-public.httprequestinit.signal.md) | AbortSignal | null | Returns the signal associated with request, which is an AbortSignal object indicating whether or not request has been aborted, and its abort event handler. | +| [window](./kibana-plugin-public.httprequestinit.window.md) | null | Can only be null. Used to disassociate request from any Window. | + diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.method.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.method.md index c3465ae75521d8..1c14d72e5e5f98 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.method.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.method.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [method](./kibana-plugin-public.httprequestinit.method.md) - -## HttpRequestInit.method property - -HTTP method, which is "GET" by default. - -Signature: - -```typescript -method?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [method](./kibana-plugin-public.httprequestinit.method.md) + +## HttpRequestInit.method property + +HTTP method, which is "GET" by default. + +Signature: + +```typescript +method?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.mode.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.mode.md index 5ba625318eb271..d3358a3a6b0680 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.mode.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.mode.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [mode](./kibana-plugin-public.httprequestinit.mode.md) - -## HttpRequestInit.mode property - -The mode associated with request, which is a string indicating whether the request will use CORS, or will be restricted to same-origin URLs. - -Signature: - -```typescript -mode?: RequestMode; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [mode](./kibana-plugin-public.httprequestinit.mode.md) + +## HttpRequestInit.mode property + +The mode associated with request, which is a string indicating whether the request will use CORS, or will be restricted to same-origin URLs. + +Signature: + +```typescript +mode?: RequestMode; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.redirect.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.redirect.md index b2554812fadf9f..6b07fd44416b79 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.redirect.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.redirect.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [redirect](./kibana-plugin-public.httprequestinit.redirect.md) - -## HttpRequestInit.redirect property - -The redirect mode associated with request, which is a string indicating how redirects for the request will be handled during fetching. A request will follow redirects by default. - -Signature: - -```typescript -redirect?: RequestRedirect; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [redirect](./kibana-plugin-public.httprequestinit.redirect.md) + +## HttpRequestInit.redirect property + +The redirect mode associated with request, which is a string indicating how redirects for the request will be handled during fetching. A request will follow redirects by default. + +Signature: + +```typescript +redirect?: RequestRedirect; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.referrer.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.referrer.md index 56c9bcb4afaa96..c1a8960de6eac4 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.referrer.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.referrer.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [referrer](./kibana-plugin-public.httprequestinit.referrer.md) - -## HttpRequestInit.referrer property - -The referrer of request. Its value can be a same-origin URL if explicitly set in init, the empty string to indicate no referrer, and "about:client" when defaulting to the global's default. This is used during fetching to determine the value of the `Referer` header of the request being made. - -Signature: - -```typescript -referrer?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [referrer](./kibana-plugin-public.httprequestinit.referrer.md) + +## HttpRequestInit.referrer property + +The referrer of request. Its value can be a same-origin URL if explicitly set in init, the empty string to indicate no referrer, and "about:client" when defaulting to the global's default. This is used during fetching to determine the value of the `Referer` header of the request being made. + +Signature: + +```typescript +referrer?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.referrerpolicy.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.referrerpolicy.md index 07231203c0030b..05e1e2487f8f29 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.referrerpolicy.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.referrerpolicy.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [referrerPolicy](./kibana-plugin-public.httprequestinit.referrerpolicy.md) - -## HttpRequestInit.referrerPolicy property - -The referrer policy associated with request. This is used during fetching to compute the value of the request's referrer. - -Signature: - -```typescript -referrerPolicy?: ReferrerPolicy; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [referrerPolicy](./kibana-plugin-public.httprequestinit.referrerpolicy.md) + +## HttpRequestInit.referrerPolicy property + +The referrer policy associated with request. This is used during fetching to compute the value of the request's referrer. + +Signature: + +```typescript +referrerPolicy?: ReferrerPolicy; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.signal.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.signal.md index b0e863eaa804f7..38a9f5d48056a4 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.signal.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.signal.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [signal](./kibana-plugin-public.httprequestinit.signal.md) - -## HttpRequestInit.signal property - -Returns the signal associated with request, which is an AbortSignal object indicating whether or not request has been aborted, and its abort event handler. - -Signature: - -```typescript -signal?: AbortSignal | null; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [signal](./kibana-plugin-public.httprequestinit.signal.md) + +## HttpRequestInit.signal property + +Returns the signal associated with request, which is an AbortSignal object indicating whether or not request has been aborted, and its abort event handler. + +Signature: + +```typescript +signal?: AbortSignal | null; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httprequestinit.window.md b/docs/development/core/public/kibana-plugin-public.httprequestinit.window.md index 1a6d7400654231..67a3a163a5d27d 100644 --- a/docs/development/core/public/kibana-plugin-public.httprequestinit.window.md +++ b/docs/development/core/public/kibana-plugin-public.httprequestinit.window.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [window](./kibana-plugin-public.httprequestinit.window.md) - -## HttpRequestInit.window property - -Can only be null. Used to disassociate request from any Window. - -Signature: - -```typescript -window?: null; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) > [window](./kibana-plugin-public.httprequestinit.window.md) + +## HttpRequestInit.window property + +Can only be null. Used to disassociate request from any Window. + +Signature: + +```typescript +window?: null; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpresponse.body.md b/docs/development/core/public/kibana-plugin-public.httpresponse.body.md new file mode 100644 index 00000000000000..773812135602b7 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpresponse.body.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpResponse](./kibana-plugin-public.httpresponse.md) > [body](./kibana-plugin-public.httpresponse.body.md) + +## HttpResponse.body property + +Parsed body received, may be undefined if there was an error. + +Signature: + +```typescript +readonly body?: TResponseBody; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpresponse.fetchoptions.md b/docs/development/core/public/kibana-plugin-public.httpresponse.fetchoptions.md new file mode 100644 index 00000000000000..8fd4f8d1e908ed --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpresponse.fetchoptions.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpResponse](./kibana-plugin-public.httpresponse.md) > [fetchOptions](./kibana-plugin-public.httpresponse.fetchoptions.md) + +## HttpResponse.fetchOptions property + +The original [HttpFetchOptionsWithPath](./kibana-plugin-public.httpfetchoptionswithpath.md) used to send this request. + +Signature: + +```typescript +readonly fetchOptions: Readonly; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpresponse.md b/docs/development/core/public/kibana-plugin-public.httpresponse.md new file mode 100644 index 00000000000000..3e70e5556b982e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpresponse.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpResponse](./kibana-plugin-public.httpresponse.md) + +## HttpResponse interface + + +Signature: + +```typescript +export interface HttpResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-public.httpresponse.body.md) | TResponseBody | Parsed body received, may be undefined if there was an error. | +| [fetchOptions](./kibana-plugin-public.httpresponse.fetchoptions.md) | Readonly<HttpFetchOptionsWithPath> | The original [HttpFetchOptionsWithPath](./kibana-plugin-public.httpfetchoptionswithpath.md) used to send this request. | +| [request](./kibana-plugin-public.httpresponse.request.md) | Readonly<Request> | Raw request sent to Kibana server. | +| [response](./kibana-plugin-public.httpresponse.response.md) | Readonly<Response> | Raw response received, may be undefined if there was an error. | + diff --git a/docs/development/core/public/kibana-plugin-public.httpresponse.request.md b/docs/development/core/public/kibana-plugin-public.httpresponse.request.md new file mode 100644 index 00000000000000..583a295e26a72e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpresponse.request.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpResponse](./kibana-plugin-public.httpresponse.md) > [request](./kibana-plugin-public.httpresponse.request.md) + +## HttpResponse.request property + +Raw request sent to Kibana server. + +Signature: + +```typescript +readonly request: Readonly; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpresponse.response.md b/docs/development/core/public/kibana-plugin-public.httpresponse.response.md new file mode 100644 index 00000000000000..b773b3a4d5b557 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpresponse.response.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpResponse](./kibana-plugin-public.httpresponse.md) > [response](./kibana-plugin-public.httpresponse.response.md) + +## HttpResponse.response property + +Raw response received, may be undefined if there was an error. + +Signature: + +```typescript +readonly response?: Readonly; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.addloadingcountsource.md b/docs/development/core/public/kibana-plugin-public.httpsetup.addloadingcountsource.md index a2fe66bb55c77b..88b1e14f6e85be 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.addloadingcountsource.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.addloadingcountsource.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [addLoadingCountSource](./kibana-plugin-public.httpsetup.addloadingcountsource.md) - -## HttpSetup.addLoadingCountSource() method - -Adds a new source of loading counts. Used to show the global loading indicator when sum of all observed counts are more than 0. - -Signature: - -```typescript -addLoadingCountSource(countSource$: Observable): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| countSource$ | Observable<number> | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [addLoadingCountSource](./kibana-plugin-public.httpsetup.addloadingcountsource.md) + +## HttpSetup.addLoadingCountSource() method + +Adds a new source of loading counts. Used to show the global loading indicator when sum of all observed counts are more than 0. + +Signature: + +```typescript +addLoadingCountSource(countSource$: Observable): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| countSource$ | Observable<number> | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.anonymouspaths.md b/docs/development/core/public/kibana-plugin-public.httpsetup.anonymouspaths.md index a9268ca1d8ed68..c44357b39443f9 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.anonymouspaths.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.anonymouspaths.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [anonymousPaths](./kibana-plugin-public.httpsetup.anonymouspaths.md) - -## HttpSetup.anonymousPaths property - -APIs for denoting certain paths for not requiring authentication - -Signature: - -```typescript -anonymousPaths: IAnonymousPaths; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [anonymousPaths](./kibana-plugin-public.httpsetup.anonymouspaths.md) + +## HttpSetup.anonymousPaths property + +APIs for denoting certain paths for not requiring authentication + +Signature: + +```typescript +anonymousPaths: IAnonymousPaths; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.basepath.md b/docs/development/core/public/kibana-plugin-public.httpsetup.basepath.md index 6b0726dc8ef2be..fa5ec7d6fef38a 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.basepath.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.basepath.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [basePath](./kibana-plugin-public.httpsetup.basepath.md) - -## HttpSetup.basePath property - -APIs for manipulating the basePath on URL segments. - -Signature: - -```typescript -basePath: IBasePath; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [basePath](./kibana-plugin-public.httpsetup.basepath.md) + +## HttpSetup.basePath property + +APIs for manipulating the basePath on URL segments. + +Signature: + +```typescript +basePath: IBasePath; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.delete.md b/docs/development/core/public/kibana-plugin-public.httpsetup.delete.md index 565f0eb336d4fe..83ce558826baf9 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.delete.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.delete.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [delete](./kibana-plugin-public.httpsetup.delete.md) - -## HttpSetup.delete property - -Makes an HTTP request with the DELETE method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. - -Signature: - -```typescript -delete: HttpHandler; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [delete](./kibana-plugin-public.httpsetup.delete.md) + +## HttpSetup.delete property + +Makes an HTTP request with the DELETE method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. + +Signature: + +```typescript +delete: HttpHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.fetch.md b/docs/development/core/public/kibana-plugin-public.httpsetup.fetch.md index 2d6447363fa9b7..4f9b24ca03e61d 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.fetch.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.fetch.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [fetch](./kibana-plugin-public.httpsetup.fetch.md) - -## HttpSetup.fetch property - -Makes an HTTP request. Defaults to a GET request unless overriden. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. - -Signature: - -```typescript -fetch: HttpHandler; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [fetch](./kibana-plugin-public.httpsetup.fetch.md) + +## HttpSetup.fetch property + +Makes an HTTP request. Defaults to a GET request unless overriden. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. + +Signature: + +```typescript +fetch: HttpHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.get.md b/docs/development/core/public/kibana-plugin-public.httpsetup.get.md index 0c484e33e9b58e..920b53d23c95c6 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.get.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.get.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [get](./kibana-plugin-public.httpsetup.get.md) - -## HttpSetup.get property - -Makes an HTTP request with the GET method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. - -Signature: - -```typescript -get: HttpHandler; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [get](./kibana-plugin-public.httpsetup.get.md) + +## HttpSetup.get property + +Makes an HTTP request with the GET method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. + +Signature: + +```typescript +get: HttpHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.getloadingcount_.md b/docs/development/core/public/kibana-plugin-public.httpsetup.getloadingcount_.md index 628b62b2ffc272..7f7a275e990f0b 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.getloadingcount_.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.getloadingcount_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [getLoadingCount$](./kibana-plugin-public.httpsetup.getloadingcount_.md) - -## HttpSetup.getLoadingCount$() method - -Get the sum of all loading count sources as a single Observable. - -Signature: - -```typescript -getLoadingCount$(): Observable; -``` -Returns: - -`Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [getLoadingCount$](./kibana-plugin-public.httpsetup.getloadingcount_.md) + +## HttpSetup.getLoadingCount$() method + +Get the sum of all loading count sources as a single Observable. + +Signature: + +```typescript +getLoadingCount$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.head.md b/docs/development/core/public/kibana-plugin-public.httpsetup.head.md index e4d49c843e5720..243998a68eb44f 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.head.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.head.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [head](./kibana-plugin-public.httpsetup.head.md) - -## HttpSetup.head property - -Makes an HTTP request with the HEAD method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. - -Signature: - -```typescript -head: HttpHandler; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [head](./kibana-plugin-public.httpsetup.head.md) + +## HttpSetup.head property + +Makes an HTTP request with the HEAD method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. + +Signature: + +```typescript +head: HttpHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.intercept.md b/docs/development/core/public/kibana-plugin-public.httpsetup.intercept.md index 1bda0c6166e652..36cf80aeb52dea 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.intercept.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.intercept.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [intercept](./kibana-plugin-public.httpsetup.intercept.md) - -## HttpSetup.intercept() method - -Adds a new [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) to the global HTTP client. - -Signature: - -```typescript -intercept(interceptor: HttpInterceptor): () => void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| interceptor | HttpInterceptor | | - -Returns: - -`() => void` - -a function for removing the attached interceptor. - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [intercept](./kibana-plugin-public.httpsetup.intercept.md) + +## HttpSetup.intercept() method + +Adds a new [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) to the global HTTP client. + +Signature: + +```typescript +intercept(interceptor: HttpInterceptor): () => void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| interceptor | HttpInterceptor | | + +Returns: + +`() => void` + +a function for removing the attached interceptor. + diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.md b/docs/development/core/public/kibana-plugin-public.httpsetup.md index 8a14d26c57ca36..d458f0edcc8a8f 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.md @@ -1,36 +1,36 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) - -## HttpSetup interface - - -Signature: - -```typescript -export interface HttpSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [anonymousPaths](./kibana-plugin-public.httpsetup.anonymouspaths.md) | IAnonymousPaths | APIs for denoting certain paths for not requiring authentication | -| [basePath](./kibana-plugin-public.httpsetup.basepath.md) | IBasePath | APIs for manipulating the basePath on URL segments. | -| [delete](./kibana-plugin-public.httpsetup.delete.md) | HttpHandler | Makes an HTTP request with the DELETE method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | -| [fetch](./kibana-plugin-public.httpsetup.fetch.md) | HttpHandler | Makes an HTTP request. Defaults to a GET request unless overriden. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | -| [get](./kibana-plugin-public.httpsetup.get.md) | HttpHandler | Makes an HTTP request with the GET method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | -| [head](./kibana-plugin-public.httpsetup.head.md) | HttpHandler | Makes an HTTP request with the HEAD method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | -| [options](./kibana-plugin-public.httpsetup.options.md) | HttpHandler | Makes an HTTP request with the OPTIONS method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | -| [patch](./kibana-plugin-public.httpsetup.patch.md) | HttpHandler | Makes an HTTP request with the PATCH method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | -| [post](./kibana-plugin-public.httpsetup.post.md) | HttpHandler | Makes an HTTP request with the POST method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | -| [put](./kibana-plugin-public.httpsetup.put.md) | HttpHandler | Makes an HTTP request with the PUT method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | - -## Methods - -| Method | Description | -| --- | --- | -| [addLoadingCountSource(countSource$)](./kibana-plugin-public.httpsetup.addloadingcountsource.md) | Adds a new source of loading counts. Used to show the global loading indicator when sum of all observed counts are more than 0. | -| [getLoadingCount$()](./kibana-plugin-public.httpsetup.getloadingcount_.md) | Get the sum of all loading count sources as a single Observable. | -| [intercept(interceptor)](./kibana-plugin-public.httpsetup.intercept.md) | Adds a new [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) to the global HTTP client. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) + +## HttpSetup interface + + +Signature: + +```typescript +export interface HttpSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [anonymousPaths](./kibana-plugin-public.httpsetup.anonymouspaths.md) | IAnonymousPaths | APIs for denoting certain paths for not requiring authentication | +| [basePath](./kibana-plugin-public.httpsetup.basepath.md) | IBasePath | APIs for manipulating the basePath on URL segments. | +| [delete](./kibana-plugin-public.httpsetup.delete.md) | HttpHandler | Makes an HTTP request with the DELETE method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | +| [fetch](./kibana-plugin-public.httpsetup.fetch.md) | HttpHandler | Makes an HTTP request. Defaults to a GET request unless overriden. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | +| [get](./kibana-plugin-public.httpsetup.get.md) | HttpHandler | Makes an HTTP request with the GET method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | +| [head](./kibana-plugin-public.httpsetup.head.md) | HttpHandler | Makes an HTTP request with the HEAD method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | +| [options](./kibana-plugin-public.httpsetup.options.md) | HttpHandler | Makes an HTTP request with the OPTIONS method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | +| [patch](./kibana-plugin-public.httpsetup.patch.md) | HttpHandler | Makes an HTTP request with the PATCH method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | +| [post](./kibana-plugin-public.httpsetup.post.md) | HttpHandler | Makes an HTTP request with the POST method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | +| [put](./kibana-plugin-public.httpsetup.put.md) | HttpHandler | Makes an HTTP request with the PUT method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | + +## Methods + +| Method | Description | +| --- | --- | +| [addLoadingCountSource(countSource$)](./kibana-plugin-public.httpsetup.addloadingcountsource.md) | Adds a new source of loading counts. Used to show the global loading indicator when sum of all observed counts are more than 0. | +| [getLoadingCount$()](./kibana-plugin-public.httpsetup.getloadingcount_.md) | Get the sum of all loading count sources as a single Observable. | +| [intercept(interceptor)](./kibana-plugin-public.httpsetup.intercept.md) | Adds a new [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) to the global HTTP client. | + diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.options.md b/docs/development/core/public/kibana-plugin-public.httpsetup.options.md index 4ea5be8826bff9..005ca3ab19dddf 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.options.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.options.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [options](./kibana-plugin-public.httpsetup.options.md) - -## HttpSetup.options property - -Makes an HTTP request with the OPTIONS method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. - -Signature: - -```typescript -options: HttpHandler; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [options](./kibana-plugin-public.httpsetup.options.md) + +## HttpSetup.options property + +Makes an HTTP request with the OPTIONS method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. + +Signature: + +```typescript +options: HttpHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.patch.md b/docs/development/core/public/kibana-plugin-public.httpsetup.patch.md index ef1d50005b012b..ee06af0ca63519 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.patch.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.patch.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [patch](./kibana-plugin-public.httpsetup.patch.md) - -## HttpSetup.patch property - -Makes an HTTP request with the PATCH method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. - -Signature: - -```typescript -patch: HttpHandler; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [patch](./kibana-plugin-public.httpsetup.patch.md) + +## HttpSetup.patch property + +Makes an HTTP request with the PATCH method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. + +Signature: + +```typescript +patch: HttpHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.post.md b/docs/development/core/public/kibana-plugin-public.httpsetup.post.md index 1c19c35ac30382..7b9a7af51fe04c 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.post.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.post.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [post](./kibana-plugin-public.httpsetup.post.md) - -## HttpSetup.post property - -Makes an HTTP request with the POST method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. - -Signature: - -```typescript -post: HttpHandler; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [post](./kibana-plugin-public.httpsetup.post.md) + +## HttpSetup.post property + +Makes an HTTP request with the POST method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. + +Signature: + +```typescript +post: HttpHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpsetup.put.md b/docs/development/core/public/kibana-plugin-public.httpsetup.put.md index e5243d8c80daed..d9d412ff13d920 100644 --- a/docs/development/core/public/kibana-plugin-public.httpsetup.put.md +++ b/docs/development/core/public/kibana-plugin-public.httpsetup.put.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [put](./kibana-plugin-public.httpsetup.put.md) - -## HttpSetup.put property - -Makes an HTTP request with the PUT method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. - -Signature: - -```typescript -put: HttpHandler; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpSetup](./kibana-plugin-public.httpsetup.md) > [put](./kibana-plugin-public.httpsetup.put.md) + +## HttpSetup.put property + +Makes an HTTP request with the PUT method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. + +Signature: + +```typescript +put: HttpHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpstart.md b/docs/development/core/public/kibana-plugin-public.httpstart.md index 9abf319acf00dd..5e3b5d066b0db5 100644 --- a/docs/development/core/public/kibana-plugin-public.httpstart.md +++ b/docs/development/core/public/kibana-plugin-public.httpstart.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpStart](./kibana-plugin-public.httpstart.md) - -## HttpStart type - -See [HttpSetup](./kibana-plugin-public.httpsetup.md) - -Signature: - -```typescript -export declare type HttpStart = HttpSetup; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpStart](./kibana-plugin-public.httpstart.md) + +## HttpStart type + +See [HttpSetup](./kibana-plugin-public.httpsetup.md) + +Signature: + +```typescript +export declare type HttpStart = HttpSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.i18nstart.context.md b/docs/development/core/public/kibana-plugin-public.i18nstart.context.md index 1dda40711b49b3..29ac950cc7adb0 100644 --- a/docs/development/core/public/kibana-plugin-public.i18nstart.context.md +++ b/docs/development/core/public/kibana-plugin-public.i18nstart.context.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [I18nStart](./kibana-plugin-public.i18nstart.md) > [Context](./kibana-plugin-public.i18nstart.context.md) - -## I18nStart.Context property - -React Context provider required as the topmost component for any i18n-compatible React tree. - -Signature: - -```typescript -Context: ({ children }: { - children: React.ReactNode; - }) => JSX.Element; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [I18nStart](./kibana-plugin-public.i18nstart.md) > [Context](./kibana-plugin-public.i18nstart.context.md) + +## I18nStart.Context property + +React Context provider required as the topmost component for any i18n-compatible React tree. + +Signature: + +```typescript +Context: ({ children }: { + children: React.ReactNode; + }) => JSX.Element; +``` diff --git a/docs/development/core/public/kibana-plugin-public.i18nstart.md b/docs/development/core/public/kibana-plugin-public.i18nstart.md index 0df5ee93a6af09..83dd60abfb4906 100644 --- a/docs/development/core/public/kibana-plugin-public.i18nstart.md +++ b/docs/development/core/public/kibana-plugin-public.i18nstart.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [I18nStart](./kibana-plugin-public.i18nstart.md) - -## I18nStart interface - -I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. - -Signature: - -```typescript -export interface I18nStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [Context](./kibana-plugin-public.i18nstart.context.md) | ({ children }: {
children: React.ReactNode;
}) => JSX.Element | React Context provider required as the topmost component for any i18n-compatible React tree. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [I18nStart](./kibana-plugin-public.i18nstart.md) + +## I18nStart interface + +I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. + +Signature: + +```typescript +export interface I18nStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [Context](./kibana-plugin-public.i18nstart.context.md) | ({ children }: {
children: React.ReactNode;
}) => JSX.Element | React Context provider required as the topmost component for any i18n-compatible React tree. | + diff --git a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.isanonymous.md b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.isanonymous.md index d6be78e1e725b2..269c255e880f04 100644 --- a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.isanonymous.md +++ b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.isanonymous.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) > [isAnonymous](./kibana-plugin-public.ianonymouspaths.isanonymous.md) - -## IAnonymousPaths.isAnonymous() method - -Determines whether the provided path doesn't require authentication. `path` should include the current basePath. - -Signature: - -```typescript -isAnonymous(path: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| path | string | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) > [isAnonymous](./kibana-plugin-public.ianonymouspaths.isanonymous.md) + +## IAnonymousPaths.isAnonymous() method + +Determines whether the provided path doesn't require authentication. `path` should include the current basePath. + +Signature: + +```typescript +isAnonymous(path: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| path | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.md b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.md index 1290df28780cfe..65563f1f8d9037 100644 --- a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.md +++ b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) - -## IAnonymousPaths interface - -APIs for denoting paths as not requiring authentication - -Signature: - -```typescript -export interface IAnonymousPaths -``` - -## Methods - -| Method | Description | -| --- | --- | -| [isAnonymous(path)](./kibana-plugin-public.ianonymouspaths.isanonymous.md) | Determines whether the provided path doesn't require authentication. path should include the current basePath. | -| [register(path)](./kibana-plugin-public.ianonymouspaths.register.md) | Register path as not requiring authentication. path should not include the current basePath. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) + +## IAnonymousPaths interface + +APIs for denoting paths as not requiring authentication + +Signature: + +```typescript +export interface IAnonymousPaths +``` + +## Methods + +| Method | Description | +| --- | --- | +| [isAnonymous(path)](./kibana-plugin-public.ianonymouspaths.isanonymous.md) | Determines whether the provided path doesn't require authentication. path should include the current basePath. | +| [register(path)](./kibana-plugin-public.ianonymouspaths.register.md) | Register path as not requiring authentication. path should not include the current basePath. | + diff --git a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.register.md b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.register.md index 3ab9bf438aa161..49819ae7f2420a 100644 --- a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.register.md +++ b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.register.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) > [register](./kibana-plugin-public.ianonymouspaths.register.md) - -## IAnonymousPaths.register() method - -Register `path` as not requiring authentication. `path` should not include the current basePath. - -Signature: - -```typescript -register(path: string): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| path | string | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) > [register](./kibana-plugin-public.ianonymouspaths.register.md) + +## IAnonymousPaths.register() method + +Register `path` as not requiring authentication. `path` should not include the current basePath. + +Signature: + +```typescript +register(path: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| path | string | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.ibasepath.get.md b/docs/development/core/public/kibana-plugin-public.ibasepath.get.md index 08ca3afee11f71..2b3354c00c0f6c 100644 --- a/docs/development/core/public/kibana-plugin-public.ibasepath.get.md +++ b/docs/development/core/public/kibana-plugin-public.ibasepath.get.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IBasePath](./kibana-plugin-public.ibasepath.md) > [get](./kibana-plugin-public.ibasepath.get.md) - -## IBasePath.get property - -Gets the `basePath` string. - -Signature: - -```typescript -get: () => string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IBasePath](./kibana-plugin-public.ibasepath.md) > [get](./kibana-plugin-public.ibasepath.get.md) + +## IBasePath.get property + +Gets the `basePath` string. + +Signature: + +```typescript +get: () => string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ibasepath.md b/docs/development/core/public/kibana-plugin-public.ibasepath.md index de392d45c44932..ca4c4b7ad3be71 100644 --- a/docs/development/core/public/kibana-plugin-public.ibasepath.md +++ b/docs/development/core/public/kibana-plugin-public.ibasepath.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IBasePath](./kibana-plugin-public.ibasepath.md) - -## IBasePath interface - -APIs for manipulating the basePath on URL segments. - -Signature: - -```typescript -export interface IBasePath -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [get](./kibana-plugin-public.ibasepath.get.md) | () => string | Gets the basePath string. | -| [prepend](./kibana-plugin-public.ibasepath.prepend.md) | (url: string) => string | Prepends path with the basePath. | -| [remove](./kibana-plugin-public.ibasepath.remove.md) | (url: string) => string | Removes the prepended basePath from the path. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IBasePath](./kibana-plugin-public.ibasepath.md) + +## IBasePath interface + +APIs for manipulating the basePath on URL segments. + +Signature: + +```typescript +export interface IBasePath +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [get](./kibana-plugin-public.ibasepath.get.md) | () => string | Gets the basePath string. | +| [prepend](./kibana-plugin-public.ibasepath.prepend.md) | (url: string) => string | Prepends path with the basePath. | +| [remove](./kibana-plugin-public.ibasepath.remove.md) | (url: string) => string | Removes the prepended basePath from the path. | + diff --git a/docs/development/core/public/kibana-plugin-public.ibasepath.prepend.md b/docs/development/core/public/kibana-plugin-public.ibasepath.prepend.md index 48b909aa2f7a82..98c07f848a5a9d 100644 --- a/docs/development/core/public/kibana-plugin-public.ibasepath.prepend.md +++ b/docs/development/core/public/kibana-plugin-public.ibasepath.prepend.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IBasePath](./kibana-plugin-public.ibasepath.md) > [prepend](./kibana-plugin-public.ibasepath.prepend.md) - -## IBasePath.prepend property - -Prepends `path` with the basePath. - -Signature: - -```typescript -prepend: (url: string) => string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IBasePath](./kibana-plugin-public.ibasepath.md) > [prepend](./kibana-plugin-public.ibasepath.prepend.md) + +## IBasePath.prepend property + +Prepends `path` with the basePath. + +Signature: + +```typescript +prepend: (url: string) => string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ibasepath.remove.md b/docs/development/core/public/kibana-plugin-public.ibasepath.remove.md index 6af85644208304..ce930fa1e15962 100644 --- a/docs/development/core/public/kibana-plugin-public.ibasepath.remove.md +++ b/docs/development/core/public/kibana-plugin-public.ibasepath.remove.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IBasePath](./kibana-plugin-public.ibasepath.md) > [remove](./kibana-plugin-public.ibasepath.remove.md) - -## IBasePath.remove property - -Removes the prepended basePath from the `path`. - -Signature: - -```typescript -remove: (url: string) => string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IBasePath](./kibana-plugin-public.ibasepath.md) > [remove](./kibana-plugin-public.ibasepath.remove.md) + +## IBasePath.remove property + +Removes the prepended basePath from the `path`. + +Signature: + +```typescript +remove: (url: string) => string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md index af3b5e3fc2eb65..58db072fabc15b 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md +++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextContainer](./kibana-plugin-public.icontextcontainer.md) > [createHandler](./kibana-plugin-public.icontextcontainer.createhandler.md) - -## IContextContainer.createHandler() method - -Create a new handler function pre-wired to context for the plugin. - -Signature: - -```typescript -createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. | -| handler | THandler | Handler function to pass context object to. | - -Returns: - -`(...rest: HandlerParameters) => ShallowPromise>` - -A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextContainer](./kibana-plugin-public.icontextcontainer.md) > [createHandler](./kibana-plugin-public.icontextcontainer.createhandler.md) + +## IContextContainer.createHandler() method + +Create a new handler function pre-wired to context for the plugin. + +Signature: + +```typescript +createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. | +| handler | THandler | Handler function to pass context object to. | + +Returns: + +`(...rest: HandlerParameters) => ShallowPromise>` + +A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. + diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.md index 7a21df6b93bb51..4b01554662aad6 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.md +++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.md @@ -1,80 +1,80 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextContainer](./kibana-plugin-public.icontextcontainer.md) - -## IContextContainer interface - -An object that handles registration of context providers and configuring handlers with context. - -Signature: - -```typescript -export interface IContextContainer> -``` - -## Remarks - -A [IContextContainer](./kibana-plugin-public.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. - -Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. - -In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-public.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. - -When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. - -```ts -// Correct -class MyPlugin { - private readonly handlers = new Map(); - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - return { - registerContext(pluginOpaqueId, contextName, provider) { - this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); - }, - registerRoute(pluginOpaqueId, path, handler) { - this.handlers.set( - path, - this.contextContainer.createHandler(pluginOpaqueId, handler) - ); - } - } - } -} - -// Incorrect -class MyPlugin { - private readonly handlers = new Map(); - - constructor(private readonly initContext: PluginInitializerContext) {} - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - return { - registerContext(contextName, provider) { - // BUG! - // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. - this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); - }, - registerRoute(path, handler) { - this.handlers.set( - path, - // BUG! - // This handler will not receive any contexts provided by other dependencies of the calling plugin. - this.contextContainer.createHandler(this.initContext.opaqueId, handler) - ); - } - } - } -} - -``` - -## Methods - -| Method | Description | -| --- | --- | -| [createHandler(pluginOpaqueId, handler)](./kibana-plugin-public.icontextcontainer.createhandler.md) | Create a new handler function pre-wired to context for the plugin. | -| [registerContext(pluginOpaqueId, contextName, provider)](./kibana-plugin-public.icontextcontainer.registercontext.md) | Register a new context provider. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextContainer](./kibana-plugin-public.icontextcontainer.md) + +## IContextContainer interface + +An object that handles registration of context providers and configuring handlers with context. + +Signature: + +```typescript +export interface IContextContainer> +``` + +## Remarks + +A [IContextContainer](./kibana-plugin-public.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. + +Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. + +In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-public.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. + +When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. + +```ts +// Correct +class MyPlugin { + private readonly handlers = new Map(); + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(pluginOpaqueId, contextName, provider) { + this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); + }, + registerRoute(pluginOpaqueId, path, handler) { + this.handlers.set( + path, + this.contextContainer.createHandler(pluginOpaqueId, handler) + ); + } + } + } +} + +// Incorrect +class MyPlugin { + private readonly handlers = new Map(); + + constructor(private readonly initContext: PluginInitializerContext) {} + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(contextName, provider) { + // BUG! + // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. + this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); + }, + registerRoute(path, handler) { + this.handlers.set( + path, + // BUG! + // This handler will not receive any contexts provided by other dependencies of the calling plugin. + this.contextContainer.createHandler(this.initContext.opaqueId, handler) + ); + } + } + } +} + +``` + +## Methods + +| Method | Description | +| --- | --- | +| [createHandler(pluginOpaqueId, handler)](./kibana-plugin-public.icontextcontainer.createhandler.md) | Create a new handler function pre-wired to context for the plugin. | +| [registerContext(pluginOpaqueId, contextName, provider)](./kibana-plugin-public.icontextcontainer.registercontext.md) | Register a new context provider. | + diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md index 775f95bd7affaa..15db2467582b6d 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md +++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md @@ -1,34 +1,34 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextContainer](./kibana-plugin-public.icontextcontainer.md) > [registerContext](./kibana-plugin-public.icontextcontainer.registercontext.md) - -## IContextContainer.registerContext() method - -Register a new context provider. - -Signature: - -```typescript -registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this context. | -| contextName | TContextName | The key of the TContext object this provider supplies the value for. | -| provider | IContextProvider<THandler, TContextName> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) to be called each time a new context is created. | - -Returns: - -`this` - -The [IContextContainer](./kibana-plugin-public.icontextcontainer.md) for method chaining. - -## Remarks - -The value (or resolved Promise value) returned by the `provider` function will be attached to the context object on the key specified by `contextName`. - -Throws an exception if more than one provider is registered for the same `contextName`. - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextContainer](./kibana-plugin-public.icontextcontainer.md) > [registerContext](./kibana-plugin-public.icontextcontainer.registercontext.md) + +## IContextContainer.registerContext() method + +Register a new context provider. + +Signature: + +```typescript +registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this context. | +| contextName | TContextName | The key of the TContext object this provider supplies the value for. | +| provider | IContextProvider<THandler, TContextName> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) to be called each time a new context is created. | + +Returns: + +`this` + +The [IContextContainer](./kibana-plugin-public.icontextcontainer.md) for method chaining. + +## Remarks + +The value (or resolved Promise value) returned by the `provider` function will be attached to the context object on the key specified by `contextName`. + +Throws an exception if more than one provider is registered for the same `contextName`. + diff --git a/docs/development/core/public/kibana-plugin-public.icontextprovider.md b/docs/development/core/public/kibana-plugin-public.icontextprovider.md index 40f0ee3782f6da..157b4834d648f4 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextprovider.md +++ b/docs/development/core/public/kibana-plugin-public.icontextprovider.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextProvider](./kibana-plugin-public.icontextprovider.md) - -## IContextProvider type - -A function that returns a context value for a specific key of given context type. - -Signature: - -```typescript -export declare type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName]; -``` - -## Remarks - -This function will be called each time a new context is built for a handler invocation. - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextProvider](./kibana-plugin-public.icontextprovider.md) + +## IContextProvider type + +A function that returns a context value for a specific key of given context type. + +Signature: + +```typescript +export declare type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName]; +``` + +## Remarks + +This function will be called each time a new context is built for a handler invocation. + diff --git a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.body.md b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.body.md index 2a5f3a68635b86..3c9475dc2549f8 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.body.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.body.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [body](./kibana-plugin-public.ihttpfetcherror.body.md) - -## IHttpFetchError.body property - -Signature: - -```typescript -readonly body?: any; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [body](./kibana-plugin-public.ihttpfetcherror.body.md) + +## IHttpFetchError.body property + +Signature: + +```typescript +readonly body?: any; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.md b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.md index 0be3b581792095..6109671bb1aa66 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) - -## IHttpFetchError interface - - -Signature: - -```typescript -export interface IHttpFetchError extends Error -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [body](./kibana-plugin-public.ihttpfetcherror.body.md) | any | | -| [req](./kibana-plugin-public.ihttpfetcherror.req.md) | Request | | -| [request](./kibana-plugin-public.ihttpfetcherror.request.md) | Request | | -| [res](./kibana-plugin-public.ihttpfetcherror.res.md) | Response | | -| [response](./kibana-plugin-public.ihttpfetcherror.response.md) | Response | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) + +## IHttpFetchError interface + + +Signature: + +```typescript +export interface IHttpFetchError extends Error +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-public.ihttpfetcherror.body.md) | any | | +| [req](./kibana-plugin-public.ihttpfetcherror.req.md) | Request | | +| [request](./kibana-plugin-public.ihttpfetcherror.request.md) | Request | | +| [res](./kibana-plugin-public.ihttpfetcherror.res.md) | Response | | +| [response](./kibana-plugin-public.ihttpfetcherror.response.md) | Response | | + diff --git a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.req.md b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.req.md index 1d20aa5ecd4163..b8d84e9bbec4c9 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.req.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.req.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [req](./kibana-plugin-public.ihttpfetcherror.req.md) - -## IHttpFetchError.req property - -> Warning: This API is now obsolete. -> -> Provided for legacy compatibility. Prefer the `request` property instead. -> - -Signature: - -```typescript -readonly req: Request; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [req](./kibana-plugin-public.ihttpfetcherror.req.md) + +## IHttpFetchError.req property + +> Warning: This API is now obsolete. +> +> Provided for legacy compatibility. Prefer the `request` property instead. +> + +Signature: + +```typescript +readonly req: Request; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.request.md b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.request.md index bbb1432f13bfbc..9917df69c799ae 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.request.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.request.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [request](./kibana-plugin-public.ihttpfetcherror.request.md) - -## IHttpFetchError.request property - -Signature: - -```typescript -readonly request: Request; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [request](./kibana-plugin-public.ihttpfetcherror.request.md) + +## IHttpFetchError.request property + +Signature: + +```typescript +readonly request: Request; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.res.md b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.res.md index 291b28f6a42509..f23fdc3e408486 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.res.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.res.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [res](./kibana-plugin-public.ihttpfetcherror.res.md) - -## IHttpFetchError.res property - -> Warning: This API is now obsolete. -> -> Provided for legacy compatibility. Prefer the `response` property instead. -> - -Signature: - -```typescript -readonly res?: Response; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [res](./kibana-plugin-public.ihttpfetcherror.res.md) + +## IHttpFetchError.res property + +> Warning: This API is now obsolete. +> +> Provided for legacy compatibility. Prefer the `response` property instead. +> + +Signature: + +```typescript +readonly res?: Response; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.response.md b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.response.md index c5efc1cc3858cd..7e4639db1eefe8 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.response.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpfetcherror.response.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [response](./kibana-plugin-public.ihttpfetcherror.response.md) - -## IHttpFetchError.response property - -Signature: - -```typescript -readonly response?: Response; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) > [response](./kibana-plugin-public.ihttpfetcherror.response.md) + +## IHttpFetchError.response property + +Signature: + +```typescript +readonly response?: Response; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.halt.md b/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.halt.md index 6bd3e2e397b91d..b501d7c97aded9 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.halt.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.halt.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) > [halt](./kibana-plugin-public.ihttpinterceptcontroller.halt.md) - -## IHttpInterceptController.halt() method - -Halt the request Promise chain and do not process further interceptors or response handlers. - -Signature: - -```typescript -halt(): void; -``` -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) > [halt](./kibana-plugin-public.ihttpinterceptcontroller.halt.md) + +## IHttpInterceptController.halt() method + +Halt the request Promise chain and do not process further interceptors or response handlers. + +Signature: + +```typescript +halt(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.halted.md b/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.halted.md index 2e61e8da56e6f6..d2b15f8389c58d 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.halted.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.halted.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) > [halted](./kibana-plugin-public.ihttpinterceptcontroller.halted.md) - -## IHttpInterceptController.halted property - -Whether or not this chain has been halted. - -Signature: - -```typescript -halted: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) > [halted](./kibana-plugin-public.ihttpinterceptcontroller.halted.md) + +## IHttpInterceptController.halted property + +Whether or not this chain has been halted. + +Signature: + +```typescript +halted: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.md b/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.md index b07d9fceb91f06..657614cd3e6e0e 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpinterceptcontroller.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) - -## IHttpInterceptController interface - -Used to halt a request Promise chain in a [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md). - -Signature: - -```typescript -export interface IHttpInterceptController -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [halted](./kibana-plugin-public.ihttpinterceptcontroller.halted.md) | boolean | Whether or not this chain has been halted. | - -## Methods - -| Method | Description | -| --- | --- | -| [halt()](./kibana-plugin-public.ihttpinterceptcontroller.halt.md) | Halt the request Promise chain and do not process further interceptors or response handlers. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) + +## IHttpInterceptController interface + +Used to halt a request Promise chain in a [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md). + +Signature: + +```typescript +export interface IHttpInterceptController +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [halted](./kibana-plugin-public.ihttpinterceptcontroller.halted.md) | boolean | Whether or not this chain has been halted. | + +## Methods + +| Method | Description | +| --- | --- | +| [halt()](./kibana-plugin-public.ihttpinterceptcontroller.halt.md) | Halt the request Promise chain and do not process further interceptors or response handlers. | + diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponse.body.md b/docs/development/core/public/kibana-plugin-public.ihttpresponse.body.md deleted file mode 100644 index 2f8710ccdc60ef..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.ihttpresponse.body.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) > [body](./kibana-plugin-public.ihttpresponse.body.md) - -## IHttpResponse.body property - -Parsed body received, may be undefined if there was an error. - -Signature: - -```typescript -readonly body?: TResponseBody; -``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponse.md b/docs/development/core/public/kibana-plugin-public.ihttpresponse.md deleted file mode 100644 index 5ddce0ba2d0f14..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.ihttpresponse.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) - -## IHttpResponse interface - - -Signature: - -```typescript -export interface IHttpResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [body](./kibana-plugin-public.ihttpresponse.body.md) | TResponseBody | Parsed body received, may be undefined if there was an error. | -| [request](./kibana-plugin-public.ihttpresponse.request.md) | Readonly<Request> | Raw request sent to Kibana server. | -| [response](./kibana-plugin-public.ihttpresponse.response.md) | Readonly<Response> | Raw response received, may be undefined if there was an error. | - diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponse.request.md b/docs/development/core/public/kibana-plugin-public.ihttpresponse.request.md deleted file mode 100644 index 12e5405eb5ed43..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.ihttpresponse.request.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) > [request](./kibana-plugin-public.ihttpresponse.request.md) - -## IHttpResponse.request property - -Raw request sent to Kibana server. - -Signature: - -```typescript -readonly request: Readonly; -``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponse.response.md b/docs/development/core/public/kibana-plugin-public.ihttpresponse.response.md deleted file mode 100644 index 9d0b4b59a638d7..00000000000000 --- a/docs/development/core/public/kibana-plugin-public.ihttpresponse.response.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) > [response](./kibana-plugin-public.ihttpresponse.response.md) - -## IHttpResponse.response property - -Raw response received, may be undefined if there was an error. - -Signature: - -```typescript -readonly response?: Readonly; -``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md index 36fcfb390617c3..718083fa4cf773 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) > [body](./kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md) - -## IHttpResponseInterceptorOverrides.body property - -Parsed body received, may be undefined if there was an error. - -Signature: - -```typescript -readonly body?: TResponseBody; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) > [body](./kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md) + +## IHttpResponseInterceptorOverrides.body property + +Parsed body received, may be undefined if there was an error. + +Signature: + +```typescript +readonly body?: TResponseBody; +``` diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.md b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.md index 44f067c429e987..dbb871f354cefa 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) - -## IHttpResponseInterceptorOverrides interface - -Properties that can be returned by HttpInterceptor.request to override the response. - -Signature: - -```typescript -export interface IHttpResponseInterceptorOverrides -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [body](./kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md) | TResponseBody | Parsed body received, may be undefined if there was an error. | -| [response](./kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md) | Readonly<Response> | Raw response received, may be undefined if there was an error. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) + +## IHttpResponseInterceptorOverrides interface + +Properties that can be returned by HttpInterceptor.request to override the response. + +Signature: + +```typescript +export interface IHttpResponseInterceptorOverrides +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-public.ihttpresponseinterceptoroverrides.body.md) | TResponseBody | Parsed body received, may be undefined if there was an error. | +| [response](./kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md) | Readonly<Response> | Raw response received, may be undefined if there was an error. | + diff --git a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md index bcba996645ba6d..73ce3ba9a366db 100644 --- a/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md +++ b/docs/development/core/public/kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) > [response](./kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md) - -## IHttpResponseInterceptorOverrides.response property - -Raw response received, may be undefined if there was an error. - -Signature: - -```typescript -readonly response?: Readonly; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) > [response](./kibana-plugin-public.ihttpresponseinterceptoroverrides.response.md) + +## IHttpResponseInterceptorOverrides.response property + +Raw response received, may be undefined if there was an error. + +Signature: + +```typescript +readonly response?: Readonly; +``` diff --git a/docs/development/core/public/kibana-plugin-public.imagevalidation.maxsize.md b/docs/development/core/public/kibana-plugin-public.imagevalidation.maxsize.md new file mode 100644 index 00000000000000..18e99c2a34e7e2 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.imagevalidation.maxsize.md @@ -0,0 +1,14 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ImageValidation](./kibana-plugin-public.imagevalidation.md) > [maxSize](./kibana-plugin-public.imagevalidation.maxsize.md) + +## ImageValidation.maxSize property + +Signature: + +```typescript +maxSize: { + length: number; + description: string; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.imagevalidation.md b/docs/development/core/public/kibana-plugin-public.imagevalidation.md new file mode 100644 index 00000000000000..99c23e44d35f10 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.imagevalidation.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ImageValidation](./kibana-plugin-public.imagevalidation.md) + +## ImageValidation interface + + +Signature: + +```typescript +export interface ImageValidation +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [maxSize](./kibana-plugin-public.imagevalidation.maxsize.md) | {
length: number;
description: string;
} | | + diff --git a/docs/development/core/public/kibana-plugin-public.itoasts.md b/docs/development/core/public/kibana-plugin-public.itoasts.md index 2a6d454e2194a5..999103e23ad5e1 100644 --- a/docs/development/core/public/kibana-plugin-public.itoasts.md +++ b/docs/development/core/public/kibana-plugin-public.itoasts.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IToasts](./kibana-plugin-public.itoasts.md) - -## IToasts type - -Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-public.toastsapi.md). - -Signature: - -```typescript -export declare type IToasts = Pick; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IToasts](./kibana-plugin-public.itoasts.md) + +## IToasts type + +Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-public.toastsapi.md). + +Signature: + +```typescript +export declare type IToasts = Pick; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.get.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.get.md index 8d14a10951a925..367129e55135c5 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.get.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.get.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [get](./kibana-plugin-public.iuisettingsclient.get.md) - -## IUiSettingsClient.get property - -Gets the value for a specific uiSetting. If this setting has no user-defined value then the `defaultOverride` parameter is returned (and parsed if setting is of type "json" or "number). If the parameter is not defined and the key is not registered by any plugin then an error is thrown, otherwise reads the default value defined by a plugin. - -Signature: - -```typescript -get: (key: string, defaultOverride?: T) => T; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [get](./kibana-plugin-public.iuisettingsclient.get.md) + +## IUiSettingsClient.get property + +Gets the value for a specific uiSetting. If this setting has no user-defined value then the `defaultOverride` parameter is returned (and parsed if setting is of type "json" or "number). If the parameter is not defined and the key is not registered by any plugin then an error is thrown, otherwise reads the default value defined by a plugin. + +Signature: + +```typescript +get: (key: string, defaultOverride?: T) => T; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.get_.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.get_.md index b7680b769f303f..e68ee4698a642c 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.get_.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.get_.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [get$](./kibana-plugin-public.iuisettingsclient.get_.md) - -## IUiSettingsClient.get$ property - -Gets an observable of the current value for a config key, and all updates to that config key in the future. Providing a `defaultOverride` argument behaves the same as it does in \#get() - -Signature: - -```typescript -get$: (key: string, defaultOverride?: T) => Observable; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [get$](./kibana-plugin-public.iuisettingsclient.get_.md) + +## IUiSettingsClient.get$ property + +Gets an observable of the current value for a config key, and all updates to that config key in the future. Providing a `defaultOverride` argument behaves the same as it does in \#get() + +Signature: + +```typescript +get$: (key: string, defaultOverride?: T) => Observable; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getall.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getall.md index b767a8ff603c86..61e2edc7f1675d 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getall.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getall.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [getAll](./kibana-plugin-public.iuisettingsclient.getall.md) - -## IUiSettingsClient.getAll property - -Gets the metadata about all uiSettings, including the type, default value, and user value for each key. - -Signature: - -```typescript -getAll: () => Readonly>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [getAll](./kibana-plugin-public.iuisettingsclient.getall.md) + +## IUiSettingsClient.getAll property + +Gets the metadata about all uiSettings, including the type, default value, and user value for each key. + +Signature: + +```typescript +getAll: () => Readonly>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getsaved_.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getsaved_.md index a4ddb9abcba979..c5cf0814238703 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getsaved_.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getsaved_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [getSaved$](./kibana-plugin-public.iuisettingsclient.getsaved_.md) - -## IUiSettingsClient.getSaved$ property - -Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. - -Signature: - -```typescript -getSaved$: () => Observable<{ - key: string; - newValue: T; - oldValue: T; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [getSaved$](./kibana-plugin-public.iuisettingsclient.getsaved_.md) + +## IUiSettingsClient.getSaved$ property + +Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. + +Signature: + +```typescript +getSaved$: () => Observable<{ + key: string; + newValue: T; + oldValue: T; + }>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getupdate_.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getupdate_.md index cec5bc096cf02c..471dc3dfe0c313 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getupdate_.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getupdate_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [getUpdate$](./kibana-plugin-public.iuisettingsclient.getupdate_.md) - -## IUiSettingsClient.getUpdate$ property - -Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. - -Signature: - -```typescript -getUpdate$: () => Observable<{ - key: string; - newValue: T; - oldValue: T; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [getUpdate$](./kibana-plugin-public.iuisettingsclient.getupdate_.md) + +## IUiSettingsClient.getUpdate$ property + +Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. + +Signature: + +```typescript +getUpdate$: () => Observable<{ + key: string; + newValue: T; + oldValue: T; + }>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getupdateerrors_.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getupdateerrors_.md index 2fbcaac03e2bb8..743219d935bbfc 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getupdateerrors_.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.getupdateerrors_.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [getUpdateErrors$](./kibana-plugin-public.iuisettingsclient.getupdateerrors_.md) - -## IUiSettingsClient.getUpdateErrors$ property - -Returns an Observable that notifies subscribers of each error while trying to update the settings, containing the actual Error class. - -Signature: - -```typescript -getUpdateErrors$: () => Observable; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [getUpdateErrors$](./kibana-plugin-public.iuisettingsclient.getupdateerrors_.md) + +## IUiSettingsClient.getUpdateErrors$ property + +Returns an Observable that notifies subscribers of each error while trying to update the settings, containing the actual Error class. + +Signature: + +```typescript +getUpdateErrors$: () => Observable; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.iscustom.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.iscustom.md index 30de59c066ee3b..c26b9b42dd00c6 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.iscustom.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.iscustom.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [isCustom](./kibana-plugin-public.iuisettingsclient.iscustom.md) - -## IUiSettingsClient.isCustom property - -Returns true if the setting wasn't registered by any plugin, but was either added directly via `set()`, or is an unknown setting found in the uiSettings saved object - -Signature: - -```typescript -isCustom: (key: string) => boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [isCustom](./kibana-plugin-public.iuisettingsclient.iscustom.md) + +## IUiSettingsClient.isCustom property + +Returns true if the setting wasn't registered by any plugin, but was either added directly via `set()`, or is an unknown setting found in the uiSettings saved object + +Signature: + +```typescript +isCustom: (key: string) => boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isdeclared.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isdeclared.md index 1ffcb61967e8ad..e064d787e0c92c 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isdeclared.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isdeclared.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [isDeclared](./kibana-plugin-public.iuisettingsclient.isdeclared.md) - -## IUiSettingsClient.isDeclared property - -Returns true if the key is a "known" uiSetting, meaning it is either registered by any plugin or was previously added as a custom setting via the `set()` method. - -Signature: - -```typescript -isDeclared: (key: string) => boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [isDeclared](./kibana-plugin-public.iuisettingsclient.isdeclared.md) + +## IUiSettingsClient.isDeclared property + +Returns true if the key is a "known" uiSetting, meaning it is either registered by any plugin or was previously added as a custom setting via the `set()` method. + +Signature: + +```typescript +isDeclared: (key: string) => boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isdefault.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isdefault.md index d61367c9841d42..6fafaac0a01ff0 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isdefault.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isdefault.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [isDefault](./kibana-plugin-public.iuisettingsclient.isdefault.md) - -## IUiSettingsClient.isDefault property - -Returns true if the setting has no user-defined value or is unknown - -Signature: - -```typescript -isDefault: (key: string) => boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [isDefault](./kibana-plugin-public.iuisettingsclient.isdefault.md) + +## IUiSettingsClient.isDefault property + +Returns true if the setting has no user-defined value or is unknown + +Signature: + +```typescript +isDefault: (key: string) => boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isoverridden.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isoverridden.md index 5749e1db1fe430..28018eddafddef 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isoverridden.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.isoverridden.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [isOverridden](./kibana-plugin-public.iuisettingsclient.isoverridden.md) - -## IUiSettingsClient.isOverridden property - -Shows whether the uiSettings value set by the user. - -Signature: - -```typescript -isOverridden: (key: string) => boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [isOverridden](./kibana-plugin-public.iuisettingsclient.isoverridden.md) + +## IUiSettingsClient.isOverridden property + +Shows whether the uiSettings value set by the user. + +Signature: + +```typescript +isOverridden: (key: string) => boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.md index 4183a30806d9a2..bc2fc02977f436 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.md @@ -1,32 +1,32 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) - -## IUiSettingsClient interface - -Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) - -Signature: - -```typescript -export interface IUiSettingsClient -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [get](./kibana-plugin-public.iuisettingsclient.get.md) | <T = any>(key: string, defaultOverride?: T) => T | Gets the value for a specific uiSetting. If this setting has no user-defined value then the defaultOverride parameter is returned (and parsed if setting is of type "json" or "number). If the parameter is not defined and the key is not registered by any plugin then an error is thrown, otherwise reads the default value defined by a plugin. | -| [get$](./kibana-plugin-public.iuisettingsclient.get_.md) | <T = any>(key: string, defaultOverride?: T) => Observable<T> | Gets an observable of the current value for a config key, and all updates to that config key in the future. Providing a defaultOverride argument behaves the same as it does in \#get() | -| [getAll](./kibana-plugin-public.iuisettingsclient.getall.md) | () => Readonly<Record<string, UiSettingsParams & UserProvidedValues>> | Gets the metadata about all uiSettings, including the type, default value, and user value for each key. | -| [getSaved$](./kibana-plugin-public.iuisettingsclient.getsaved_.md) | <T = any>() => Observable<{
key: string;
newValue: T;
oldValue: T;
}> | Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. | -| [getUpdate$](./kibana-plugin-public.iuisettingsclient.getupdate_.md) | <T = any>() => Observable<{
key: string;
newValue: T;
oldValue: T;
}> | Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. | -| [getUpdateErrors$](./kibana-plugin-public.iuisettingsclient.getupdateerrors_.md) | () => Observable<Error> | Returns an Observable that notifies subscribers of each error while trying to update the settings, containing the actual Error class. | -| [isCustom](./kibana-plugin-public.iuisettingsclient.iscustom.md) | (key: string) => boolean | Returns true if the setting wasn't registered by any plugin, but was either added directly via set(), or is an unknown setting found in the uiSettings saved object | -| [isDeclared](./kibana-plugin-public.iuisettingsclient.isdeclared.md) | (key: string) => boolean | Returns true if the key is a "known" uiSetting, meaning it is either registered by any plugin or was previously added as a custom setting via the set() method. | -| [isDefault](./kibana-plugin-public.iuisettingsclient.isdefault.md) | (key: string) => boolean | Returns true if the setting has no user-defined value or is unknown | -| [isOverridden](./kibana-plugin-public.iuisettingsclient.isoverridden.md) | (key: string) => boolean | Shows whether the uiSettings value set by the user. | -| [overrideLocalDefault](./kibana-plugin-public.iuisettingsclient.overridelocaldefault.md) | (key: string, newDefault: any) => void | Overrides the default value for a setting in this specific browser tab. If the page is reloaded the default override is lost. | -| [remove](./kibana-plugin-public.iuisettingsclient.remove.md) | (key: string) => Promise<boolean> | Removes the user-defined value for a setting, causing it to revert to the default. This method behaves the same as calling set(key, null), including the synchronization, custom setting, and error behavior of that method. | -| [set](./kibana-plugin-public.iuisettingsclient.set.md) | (key: string, value: any) => Promise<boolean> | Sets the value for a uiSetting. If the setting is not registered by any plugin it will be stored as a custom setting. The new value will be synchronously available via the get() method and sent to the server in the background. If the request to the server fails then a updateErrors$ will be notified and the setting will be reverted to its value before set() was called. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) + +## IUiSettingsClient interface + +Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) + +Signature: + +```typescript +export interface IUiSettingsClient +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [get](./kibana-plugin-public.iuisettingsclient.get.md) | <T = any>(key: string, defaultOverride?: T) => T | Gets the value for a specific uiSetting. If this setting has no user-defined value then the defaultOverride parameter is returned (and parsed if setting is of type "json" or "number). If the parameter is not defined and the key is not registered by any plugin then an error is thrown, otherwise reads the default value defined by a plugin. | +| [get$](./kibana-plugin-public.iuisettingsclient.get_.md) | <T = any>(key: string, defaultOverride?: T) => Observable<T> | Gets an observable of the current value for a config key, and all updates to that config key in the future. Providing a defaultOverride argument behaves the same as it does in \#get() | +| [getAll](./kibana-plugin-public.iuisettingsclient.getall.md) | () => Readonly<Record<string, UiSettingsParams & UserProvidedValues>> | Gets the metadata about all uiSettings, including the type, default value, and user value for each key. | +| [getSaved$](./kibana-plugin-public.iuisettingsclient.getsaved_.md) | <T = any>() => Observable<{
key: string;
newValue: T;
oldValue: T;
}> | Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. | +| [getUpdate$](./kibana-plugin-public.iuisettingsclient.getupdate_.md) | <T = any>() => Observable<{
key: string;
newValue: T;
oldValue: T;
}> | Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. | +| [getUpdateErrors$](./kibana-plugin-public.iuisettingsclient.getupdateerrors_.md) | () => Observable<Error> | Returns an Observable that notifies subscribers of each error while trying to update the settings, containing the actual Error class. | +| [isCustom](./kibana-plugin-public.iuisettingsclient.iscustom.md) | (key: string) => boolean | Returns true if the setting wasn't registered by any plugin, but was either added directly via set(), or is an unknown setting found in the uiSettings saved object | +| [isDeclared](./kibana-plugin-public.iuisettingsclient.isdeclared.md) | (key: string) => boolean | Returns true if the key is a "known" uiSetting, meaning it is either registered by any plugin or was previously added as a custom setting via the set() method. | +| [isDefault](./kibana-plugin-public.iuisettingsclient.isdefault.md) | (key: string) => boolean | Returns true if the setting has no user-defined value or is unknown | +| [isOverridden](./kibana-plugin-public.iuisettingsclient.isoverridden.md) | (key: string) => boolean | Shows whether the uiSettings value set by the user. | +| [overrideLocalDefault](./kibana-plugin-public.iuisettingsclient.overridelocaldefault.md) | (key: string, newDefault: any) => void | Overrides the default value for a setting in this specific browser tab. If the page is reloaded the default override is lost. | +| [remove](./kibana-plugin-public.iuisettingsclient.remove.md) | (key: string) => Promise<boolean> | Removes the user-defined value for a setting, causing it to revert to the default. This method behaves the same as calling set(key, null), including the synchronization, custom setting, and error behavior of that method. | +| [set](./kibana-plugin-public.iuisettingsclient.set.md) | (key: string, value: any) => Promise<boolean> | Sets the value for a uiSetting. If the setting is not registered by any plugin it will be stored as a custom setting. The new value will be synchronously available via the get() method and sent to the server in the background. If the request to the server fails then a updateErrors$ will be notified and the setting will be reverted to its value before set() was called. | + diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.overridelocaldefault.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.overridelocaldefault.md index d7e7c01876654a..f56b5687da5a4c 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.overridelocaldefault.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.overridelocaldefault.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [overrideLocalDefault](./kibana-plugin-public.iuisettingsclient.overridelocaldefault.md) - -## IUiSettingsClient.overrideLocalDefault property - -Overrides the default value for a setting in this specific browser tab. If the page is reloaded the default override is lost. - -Signature: - -```typescript -overrideLocalDefault: (key: string, newDefault: any) => void; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [overrideLocalDefault](./kibana-plugin-public.iuisettingsclient.overridelocaldefault.md) + +## IUiSettingsClient.overrideLocalDefault property + +Overrides the default value for a setting in this specific browser tab. If the page is reloaded the default override is lost. + +Signature: + +```typescript +overrideLocalDefault: (key: string, newDefault: any) => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.remove.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.remove.md index c2171e5c883f83..d086eb3dfc1a2b 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.remove.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.remove.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [remove](./kibana-plugin-public.iuisettingsclient.remove.md) - -## IUiSettingsClient.remove property - -Removes the user-defined value for a setting, causing it to revert to the default. This method behaves the same as calling `set(key, null)`, including the synchronization, custom setting, and error behavior of that method. - -Signature: - -```typescript -remove: (key: string) => Promise; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [remove](./kibana-plugin-public.iuisettingsclient.remove.md) + +## IUiSettingsClient.remove property + +Removes the user-defined value for a setting, causing it to revert to the default. This method behaves the same as calling `set(key, null)`, including the synchronization, custom setting, and error behavior of that method. + +Signature: + +```typescript +remove: (key: string) => Promise; +``` diff --git a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.set.md b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.set.md index d9e62eec4cf089..0c452d13beefd5 100644 --- a/docs/development/core/public/kibana-plugin-public.iuisettingsclient.set.md +++ b/docs/development/core/public/kibana-plugin-public.iuisettingsclient.set.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [set](./kibana-plugin-public.iuisettingsclient.set.md) - -## IUiSettingsClient.set property - -Sets the value for a uiSetting. If the setting is not registered by any plugin it will be stored as a custom setting. The new value will be synchronously available via the `get()` method and sent to the server in the background. If the request to the server fails then a updateErrors$ will be notified and the setting will be reverted to its value before `set()` was called. - -Signature: - -```typescript -set: (key: string, value: any) => Promise; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) > [set](./kibana-plugin-public.iuisettingsclient.set.md) + +## IUiSettingsClient.set property + +Sets the value for a uiSetting. If the setting is not registered by any plugin it will be stored as a custom setting. The new value will be synchronously available via the `get()` method and sent to the server in the background. If the request to the server fails then a updateErrors$ will be notified and the setting will be reverted to its value before `set()` was called. + +Signature: + +```typescript +set: (key: string, value: any) => Promise; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacycoresetup.injectedmetadata.md b/docs/development/core/public/kibana-plugin-public.legacycoresetup.injectedmetadata.md index f71277e64ff17a..7f3430e6de95e9 100644 --- a/docs/development/core/public/kibana-plugin-public.legacycoresetup.injectedmetadata.md +++ b/docs/development/core/public/kibana-plugin-public.legacycoresetup.injectedmetadata.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) > [injectedMetadata](./kibana-plugin-public.legacycoresetup.injectedmetadata.md) - -## LegacyCoreSetup.injectedMetadata property - -> Warning: This API is now obsolete. -> -> - -Signature: - -```typescript -injectedMetadata: InjectedMetadataSetup; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) > [injectedMetadata](./kibana-plugin-public.legacycoresetup.injectedmetadata.md) + +## LegacyCoreSetup.injectedMetadata property + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +injectedMetadata: InjectedMetadataSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacycoresetup.md b/docs/development/core/public/kibana-plugin-public.legacycoresetup.md index 803c96cd0b22c9..6a06343cec70e0 100644 --- a/docs/development/core/public/kibana-plugin-public.legacycoresetup.md +++ b/docs/development/core/public/kibana-plugin-public.legacycoresetup.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) - -## LegacyCoreSetup interface - -> Warning: This API is now obsolete. -> -> - -Setup interface exposed to the legacy platform via the `ui/new_platform` module. - -Signature: - -```typescript -export interface LegacyCoreSetup extends CoreSetup -``` - -## Remarks - -Some methods are not supported in the legacy platform and while present to make this type compatibile with [CoreSetup](./kibana-plugin-public.coresetup.md), unsupported methods will throw exceptions when called. - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [injectedMetadata](./kibana-plugin-public.legacycoresetup.injectedmetadata.md) | InjectedMetadataSetup | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) + +## LegacyCoreSetup interface + +> Warning: This API is now obsolete. +> +> + +Setup interface exposed to the legacy platform via the `ui/new_platform` module. + +Signature: + +```typescript +export interface LegacyCoreSetup extends CoreSetup +``` + +## Remarks + +Some methods are not supported in the legacy platform and while present to make this type compatibile with [CoreSetup](./kibana-plugin-public.coresetup.md), unsupported methods will throw exceptions when called. + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [injectedMetadata](./kibana-plugin-public.legacycoresetup.injectedmetadata.md) | InjectedMetadataSetup | | + diff --git a/docs/development/core/public/kibana-plugin-public.legacycorestart.injectedmetadata.md b/docs/development/core/public/kibana-plugin-public.legacycorestart.injectedmetadata.md index cd818c3f5adc72..273b28a111bd42 100644 --- a/docs/development/core/public/kibana-plugin-public.legacycorestart.injectedmetadata.md +++ b/docs/development/core/public/kibana-plugin-public.legacycorestart.injectedmetadata.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) > [injectedMetadata](./kibana-plugin-public.legacycorestart.injectedmetadata.md) - -## LegacyCoreStart.injectedMetadata property - -> Warning: This API is now obsolete. -> -> - -Signature: - -```typescript -injectedMetadata: InjectedMetadataStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) > [injectedMetadata](./kibana-plugin-public.legacycorestart.injectedmetadata.md) + +## LegacyCoreStart.injectedMetadata property + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +injectedMetadata: InjectedMetadataStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacycorestart.md b/docs/development/core/public/kibana-plugin-public.legacycorestart.md index 438a3d61107768..17bf021f064443 100644 --- a/docs/development/core/public/kibana-plugin-public.legacycorestart.md +++ b/docs/development/core/public/kibana-plugin-public.legacycorestart.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) - -## LegacyCoreStart interface - -> Warning: This API is now obsolete. -> -> - -Start interface exposed to the legacy platform via the `ui/new_platform` module. - -Signature: - -```typescript -export interface LegacyCoreStart extends CoreStart -``` - -## Remarks - -Some methods are not supported in the legacy platform and while present to make this type compatibile with [CoreStart](./kibana-plugin-public.corestart.md), unsupported methods will throw exceptions when called. - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [injectedMetadata](./kibana-plugin-public.legacycorestart.injectedmetadata.md) | InjectedMetadataStart | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) + +## LegacyCoreStart interface + +> Warning: This API is now obsolete. +> +> + +Start interface exposed to the legacy platform via the `ui/new_platform` module. + +Signature: + +```typescript +export interface LegacyCoreStart extends CoreStart +``` + +## Remarks + +Some methods are not supported in the legacy platform and while present to make this type compatibile with [CoreStart](./kibana-plugin-public.corestart.md), unsupported methods will throw exceptions when called. + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [injectedMetadata](./kibana-plugin-public.legacycorestart.injectedmetadata.md) | InjectedMetadataStart | | + diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.category.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.category.md new file mode 100644 index 00000000000000..ff952b45090790 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.category.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [category](./kibana-plugin-public.legacynavlink.category.md) + +## LegacyNavLink.category property + +Signature: + +```typescript +category?: AppCategory; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.euiicontype.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.euiicontype.md index bf0308e88d5064..5cb803d1d2f911 100644 --- a/docs/development/core/public/kibana-plugin-public.legacynavlink.euiicontype.md +++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.euiicontype.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [euiIconType](./kibana-plugin-public.legacynavlink.euiicontype.md) - -## LegacyNavLink.euiIconType property - -Signature: - -```typescript -euiIconType?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [euiIconType](./kibana-plugin-public.legacynavlink.euiicontype.md) + +## LegacyNavLink.euiIconType property + +Signature: + +```typescript +euiIconType?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.icon.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.icon.md index 5dfe64c3a96107..1bc64b6086628c 100644 --- a/docs/development/core/public/kibana-plugin-public.legacynavlink.icon.md +++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.icon.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [icon](./kibana-plugin-public.legacynavlink.icon.md) - -## LegacyNavLink.icon property - -Signature: - -```typescript -icon?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [icon](./kibana-plugin-public.legacynavlink.icon.md) + +## LegacyNavLink.icon property + +Signature: + +```typescript +icon?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.id.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.id.md index c8d8b025e48ee5..c6c2f2dfd8d98f 100644 --- a/docs/development/core/public/kibana-plugin-public.legacynavlink.id.md +++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [id](./kibana-plugin-public.legacynavlink.id.md) - -## LegacyNavLink.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [id](./kibana-plugin-public.legacynavlink.id.md) + +## LegacyNavLink.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.md index fc0c445f517b3b..1476052ed7a43b 100644 --- a/docs/development/core/public/kibana-plugin-public.legacynavlink.md +++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.md @@ -1,24 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) - -## LegacyNavLink interface - - -Signature: - -```typescript -export interface LegacyNavLink -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [euiIconType](./kibana-plugin-public.legacynavlink.euiicontype.md) | string | | -| [icon](./kibana-plugin-public.legacynavlink.icon.md) | string | | -| [id](./kibana-plugin-public.legacynavlink.id.md) | string | | -| [order](./kibana-plugin-public.legacynavlink.order.md) | number | | -| [title](./kibana-plugin-public.legacynavlink.title.md) | string | | -| [url](./kibana-plugin-public.legacynavlink.url.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) + +## LegacyNavLink interface + + +Signature: + +```typescript +export interface LegacyNavLink +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [category](./kibana-plugin-public.legacynavlink.category.md) | AppCategory | | +| [euiIconType](./kibana-plugin-public.legacynavlink.euiicontype.md) | string | | +| [icon](./kibana-plugin-public.legacynavlink.icon.md) | string | | +| [id](./kibana-plugin-public.legacynavlink.id.md) | string | | +| [order](./kibana-plugin-public.legacynavlink.order.md) | number | | +| [title](./kibana-plugin-public.legacynavlink.title.md) | string | | +| [url](./kibana-plugin-public.legacynavlink.url.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.order.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.order.md index bfb2a2caad623c..255fcfd0fb8cfc 100644 --- a/docs/development/core/public/kibana-plugin-public.legacynavlink.order.md +++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.order.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [order](./kibana-plugin-public.legacynavlink.order.md) - -## LegacyNavLink.order property - -Signature: - -```typescript -order: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [order](./kibana-plugin-public.legacynavlink.order.md) + +## LegacyNavLink.order property + +Signature: + +```typescript +order: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.title.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.title.md index 2cb7a4ebdbc761..90b1a98a90fef6 100644 --- a/docs/development/core/public/kibana-plugin-public.legacynavlink.title.md +++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.title.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [title](./kibana-plugin-public.legacynavlink.title.md) - -## LegacyNavLink.title property - -Signature: - -```typescript -title: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [title](./kibana-plugin-public.legacynavlink.title.md) + +## LegacyNavLink.title property + +Signature: + +```typescript +title: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacynavlink.url.md b/docs/development/core/public/kibana-plugin-public.legacynavlink.url.md index fc2d55109dc98d..e26095bfbfb6ea 100644 --- a/docs/development/core/public/kibana-plugin-public.legacynavlink.url.md +++ b/docs/development/core/public/kibana-plugin-public.legacynavlink.url.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [url](./kibana-plugin-public.legacynavlink.url.md) - -## LegacyNavLink.url property - -Signature: - -```typescript -url: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) > [url](./kibana-plugin-public.legacynavlink.url.md) + +## LegacyNavLink.url property + +Signature: + +```typescript +url: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index 27ca9f2d9fd577..95a4327728139f 100644 --- a/docs/development/core/public/kibana-plugin-public.md +++ b/docs/development/core/public/kibana-plugin-public.md @@ -1,151 +1,161 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) - -## kibana-plugin-public package - -The Kibana Core APIs for client-side plugins. - -A plugin's `public/index` file must contain a named import, `plugin`, that implements [PluginInitializer](./kibana-plugin-public.plugininitializer.md) which returns an object that implements [Plugin](./kibana-plugin-public.plugin.md). - -The plugin integrates with the core system via lifecycle events: `setup`, `start`, and `stop`. In each lifecycle method, the plugin will receive the corresponding core services available (either [CoreSetup](./kibana-plugin-public.coresetup.md) or [CoreStart](./kibana-plugin-public.corestart.md)) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. - -## Classes - -| Class | Description | -| --- | --- | -| [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. The client-side SavedObjectsClient is a thin convenience library around the SavedObjects HTTP API for interacting with Saved Objects. | -| [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) | This class is a very simple wrapper for SavedObjects loaded from the server with the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md).It provides basic functionality for creating/saving/deleting saved objects, but doesn't include any type-specific implementations. | -| [ToastsApi](./kibana-plugin-public.toastsapi.md) | Methods for adding and removing global toast messages. | - -## Enumerations - -| Enumeration | Description | -| --- | --- | -| [AppLeaveActionType](./kibana-plugin-public.appleaveactiontype.md) | Possible type of actions on application leave. | -| [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) | Status of the application's navLink. | -| [AppStatus](./kibana-plugin-public.appstatus.md) | Accessibility status of an application. | - -## Interfaces - -| Interface | Description | -| --- | --- | -| [App](./kibana-plugin-public.app.md) | Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. | -| [AppBase](./kibana-plugin-public.appbase.md) | | -| [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to show a confirmation message when trying to leave an application.See | -| [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to execute the default behaviour when leaving the application.See | -| [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | | -| [ApplicationStart](./kibana-plugin-public.applicationstart.md) | | -| [AppMountContext](./kibana-plugin-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). | -| [AppMountParameters](./kibana-plugin-public.appmountparameters.md) | | -| [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | -| [ChromeBadge](./kibana-plugin-public.chromebadge.md) | | -| [ChromeBrand](./kibana-plugin-public.chromebrand.md) | | -| [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. | -| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | | -| [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | | -| [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | -| [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | | -| [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. | -| [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. | -| [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) | | -| [ChromeStart](./kibana-plugin-public.chromestart.md) | ChromeStart allows plugins to customize the global chrome header UI and enrich the UX with additional information about the current location of the browser. | -| [ContextSetup](./kibana-plugin-public.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | -| [CoreSetup](./kibana-plugin-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle | -| [CoreStart](./kibana-plugin-public.corestart.md) | Core services exposed to the Plugin start lifecycle | -| [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | | -| [EnvironmentMode](./kibana-plugin-public.environmentmode.md) | | -| [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-public.itoasts.md) APIs. | -| [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error | -| [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | -| [HttpErrorRequest](./kibana-plugin-public.httperrorrequest.md) | | -| [HttpErrorResponse](./kibana-plugin-public.httperrorresponse.md) | | -| [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-public.httphandler.md). | -| [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md) | | -| [HttpHandler](./kibana-plugin-public.httphandler.md) | A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) for the response. | -| [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) | | -| [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) | An object that may define global interceptor functions for different parts of the request and response lifecycle. See [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md). | -| [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) | Fetch API options available to [HttpHandler](./kibana-plugin-public.httphandler.md)s. | -| [HttpSetup](./kibana-plugin-public.httpsetup.md) | | -| [I18nStart](./kibana-plugin-public.i18nstart.md) | I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. | -| [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) | APIs for denoting paths as not requiring authentication | -| [IBasePath](./kibana-plugin-public.ibasepath.md) | APIs for manipulating the basePath on URL segments. | -| [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | -| [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) | | -| [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) | Used to halt a request Promise chain in a [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md). | -| [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) | | -| [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) | Properties that can be returned by HttpInterceptor.request to override the response. | -| [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | -| [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) | Setup interface exposed to the legacy platform via the ui/new_platform module. | -| [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) | Start interface exposed to the legacy platform via the ui/new_platform module. | -| [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) | | -| [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) | | -| [NotificationsStart](./kibana-plugin-public.notificationsstart.md) | | -| [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) | | -| [OverlayRef](./kibana-plugin-public.overlayref.md) | Returned by [OverlayStart](./kibana-plugin-public.overlaystart.md) methods for closing a mounted overlay. | -| [OverlayStart](./kibana-plugin-public.overlaystart.md) | | -| [PackageInfo](./kibana-plugin-public.packageinfo.md) | | -| [Plugin](./kibana-plugin-public.plugin.md) | The interface that should be returned by a PluginInitializer. | -| [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) | The available core services passed to a PluginInitializer | -| [SavedObject](./kibana-plugin-public.savedobject.md) | | -| [SavedObjectAttributes](./kibana-plugin-public.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | -| [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) | A reference to another saved object. | -| [SavedObjectsBaseOptions](./kibana-plugin-public.savedobjectsbaseoptions.md) | | -| [SavedObjectsBatchResponse](./kibana-plugin-public.savedobjectsbatchresponse.md) | | -| [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) | | -| [SavedObjectsBulkCreateOptions](./kibana-plugin-public.savedobjectsbulkcreateoptions.md) | | -| [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) | | -| [SavedObjectsBulkUpdateOptions](./kibana-plugin-public.savedobjectsbulkupdateoptions.md) | | -| [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) | | -| [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) | | -| [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. | -| [SavedObjectsImportConflictError](./kibana-plugin-public.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. | -| [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) | Represents a failure to import. | -| [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. | -| [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) | The response describing the result of an import. | -| [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. | -| [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) | Represents a failure to import due to an unknown reason. | -| [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md) | Represents a failure to import due to having an unsupported saved object type. | -| [SavedObjectsMigrationVersion](./kibana-plugin-public.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | -| [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) | | -| [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) | | -| [UiSettingsState](./kibana-plugin-public.uisettingsstate.md) | | - -## Type Aliases - -| Type Alias | Description | -| --- | --- | -| [AppLeaveAction](./kibana-plugin-public.appleaveaction.md) | Possible actions to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md)See [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) and [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) | -| [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) | A handler that will be executed before leaving the application, either when going to another application or when closing the browser tab or manually changing the url. Should return confirm to to prompt a message to the user before leaving the page, or default to keep the default behavior (doing nothing).See [AppMountParameters](./kibana-plugin-public.appmountparameters.md) for detailed usage examples. | -| [AppMount](./kibana-plugin-public.appmount.md) | A mount function called when the user navigates to this app's route. | -| [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md) | A mount function called when the user navigates to this app's route. | -| [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. | -| [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) | Defines the list of fields that can be updated via an [AppUpdater](./kibana-plugin-public.appupdater.md). | -| [AppUpdater](./kibana-plugin-public.appupdater.md) | Updater for applications. see [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | -| [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) | | -| [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) | | -| [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) | | -| [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) | | -| [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) | | -| [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) | | -| [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | | -| [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. | -| [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | -| [HandlerParameters](./kibana-plugin-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). | -| [HttpStart](./kibana-plugin-public.httpstart.md) | See [HttpSetup](./kibana-plugin-public.httpsetup.md) | -| [IContextProvider](./kibana-plugin-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | -| [IToasts](./kibana-plugin-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-public.toastsapi.md). | -| [MountPoint](./kibana-plugin-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. | -| [PluginInitializer](./kibana-plugin-public.plugininitializer.md) | The plugin export at the root of a plugin's public directory should conform to this interface. | -| [PluginOpaqueId](./kibana-plugin-public.pluginopaqueid.md) | | -| [RecursiveReadonly](./kibana-plugin-public.recursivereadonly.md) | | -| [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value | -| [SavedObjectAttributeSingle](./kibana-plugin-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) | -| [SavedObjectsClientContract](./kibana-plugin-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | -| [Toast](./kibana-plugin-public.toast.md) | | -| [ToastInput](./kibana-plugin-public.toastinput.md) | Inputs for [IToasts](./kibana-plugin-public.itoasts.md) APIs. | -| [ToastInputFields](./kibana-plugin-public.toastinputfields.md) | Allowed fields for [ToastInput](./kibana-plugin-public.toastinput.md). | -| [ToastsSetup](./kibana-plugin-public.toastssetup.md) | [IToasts](./kibana-plugin-public.itoasts.md) | -| [ToastsStart](./kibana-plugin-public.toastsstart.md) | [IToasts](./kibana-plugin-public.itoasts.md) | -| [UnmountCallback](./kibana-plugin-public.unmountcallback.md) | A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-public.mountpoint.md) | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) + +## kibana-plugin-public package + +The Kibana Core APIs for client-side plugins. + +A plugin's `public/index` file must contain a named import, `plugin`, that implements [PluginInitializer](./kibana-plugin-public.plugininitializer.md) which returns an object that implements [Plugin](./kibana-plugin-public.plugin.md). + +The plugin integrates with the core system via lifecycle events: `setup`, `start`, and `stop`. In each lifecycle method, the plugin will receive the corresponding core services available (either [CoreSetup](./kibana-plugin-public.coresetup.md) or [CoreStart](./kibana-plugin-public.corestart.md)) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. + +## Classes + +| Class | Description | +| --- | --- | +| [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. The client-side SavedObjectsClient is a thin convenience library around the SavedObjects HTTP API for interacting with Saved Objects. | +| [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) | This class is a very simple wrapper for SavedObjects loaded from the server with the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md).It provides basic functionality for creating/saving/deleting saved objects, but doesn't include any type-specific implementations. | +| [ToastsApi](./kibana-plugin-public.toastsapi.md) | Methods for adding and removing global toast messages. | + +## Enumerations + +| Enumeration | Description | +| --- | --- | +| [AppLeaveActionType](./kibana-plugin-public.appleaveactiontype.md) | Possible type of actions on application leave. | +| [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) | Status of the application's navLink. | +| [AppStatus](./kibana-plugin-public.appstatus.md) | Accessibility status of an application. | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [App](./kibana-plugin-public.app.md) | Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. | +| [AppBase](./kibana-plugin-public.appbase.md) | | +| [AppCategory](./kibana-plugin-public.appcategory.md) | A category definition for nav links to know where to sort them in the left hand nav | +| [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to show a confirmation message when trying to leave an application.See | +| [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to execute the default behaviour when leaving the application.See | +| [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | | +| [ApplicationStart](./kibana-plugin-public.applicationstart.md) | | +| [AppMountContext](./kibana-plugin-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). | +| [AppMountParameters](./kibana-plugin-public.appmountparameters.md) | | +| [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | +| [ChromeBadge](./kibana-plugin-public.chromebadge.md) | | +| [ChromeBrand](./kibana-plugin-public.chromebrand.md) | | +| [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. | +| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | | +| [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | | +| [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | +| [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | | +| [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. | +| [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. | +| [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) | | +| [ChromeStart](./kibana-plugin-public.chromestart.md) | ChromeStart allows plugins to customize the global chrome header UI and enrich the UX with additional information about the current location of the browser. | +| [ContextSetup](./kibana-plugin-public.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | +| [CoreSetup](./kibana-plugin-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle | +| [CoreStart](./kibana-plugin-public.corestart.md) | Core services exposed to the Plugin start lifecycle | +| [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | | +| [EnvironmentMode](./kibana-plugin-public.environmentmode.md) | | +| [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-public.itoasts.md) APIs. | +| [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error | +| [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | +| [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-public.httphandler.md). | +| [HttpFetchOptionsWithPath](./kibana-plugin-public.httpfetchoptionswithpath.md) | Similar to [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) but with the URL path included. | +| [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md) | | +| [HttpHandler](./kibana-plugin-public.httphandler.md) | A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [HttpResponse](./kibana-plugin-public.httpresponse.md) for the response. | +| [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) | Headers to append to the request. Any headers that begin with kbn- are considered private to Core and will cause [HttpHandler](./kibana-plugin-public.httphandler.md) to throw an error. | +| [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) | An object that may define global interceptor functions for different parts of the request and response lifecycle. See [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md). | +| [HttpInterceptorRequestError](./kibana-plugin-public.httpinterceptorrequesterror.md) | | +| [HttpInterceptorResponseError](./kibana-plugin-public.httpinterceptorresponseerror.md) | | +| [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) | Fetch API options available to [HttpHandler](./kibana-plugin-public.httphandler.md)s. | +| [HttpResponse](./kibana-plugin-public.httpresponse.md) | | +| [HttpSetup](./kibana-plugin-public.httpsetup.md) | | +| [I18nStart](./kibana-plugin-public.i18nstart.md) | I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. | +| [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) | APIs for denoting paths as not requiring authentication | +| [IBasePath](./kibana-plugin-public.ibasepath.md) | APIs for manipulating the basePath on URL segments. | +| [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | +| [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) | | +| [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) | Used to halt a request Promise chain in a [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md). | +| [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) | Properties that can be returned by HttpInterceptor.request to override the response. | +| [ImageValidation](./kibana-plugin-public.imagevalidation.md) | | +| [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | +| [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) | Setup interface exposed to the legacy platform via the ui/new_platform module. | +| [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) | Start interface exposed to the legacy platform via the ui/new_platform module. | +| [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) | | +| [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) | | +| [NotificationsStart](./kibana-plugin-public.notificationsstart.md) | | +| [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) | | +| [OverlayRef](./kibana-plugin-public.overlayref.md) | Returned by [OverlayStart](./kibana-plugin-public.overlaystart.md) methods for closing a mounted overlay. | +| [OverlayStart](./kibana-plugin-public.overlaystart.md) | | +| [PackageInfo](./kibana-plugin-public.packageinfo.md) | | +| [Plugin](./kibana-plugin-public.plugin.md) | The interface that should be returned by a PluginInitializer. | +| [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) | The available core services passed to a PluginInitializer | +| [SavedObject](./kibana-plugin-public.savedobject.md) | | +| [SavedObjectAttributes](./kibana-plugin-public.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | +| [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) | A reference to another saved object. | +| [SavedObjectsBaseOptions](./kibana-plugin-public.savedobjectsbaseoptions.md) | | +| [SavedObjectsBatchResponse](./kibana-plugin-public.savedobjectsbatchresponse.md) | | +| [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) | | +| [SavedObjectsBulkCreateOptions](./kibana-plugin-public.savedobjectsbulkcreateoptions.md) | | +| [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) | | +| [SavedObjectsBulkUpdateOptions](./kibana-plugin-public.savedobjectsbulkupdateoptions.md) | | +| [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) | | +| [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) | | +| [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. | +| [SavedObjectsImportConflictError](./kibana-plugin-public.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. | +| [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) | Represents a failure to import. | +| [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. | +| [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) | The response describing the result of an import. | +| [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. | +| [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) | Represents a failure to import due to an unknown reason. | +| [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md) | Represents a failure to import due to having an unsupported saved object type. | +| [SavedObjectsMigrationVersion](./kibana-plugin-public.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) | | +| [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) | | +| [StringValidationRegex](./kibana-plugin-public.stringvalidationregex.md) | StringValidation with regex object | +| [StringValidationRegexString](./kibana-plugin-public.stringvalidationregexstring.md) | StringValidation as regex string | +| [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) | UiSettings parameters defined by the plugins. | +| [UiSettingsState](./kibana-plugin-public.uisettingsstate.md) | | +| [UserProvidedValues](./kibana-plugin-public.userprovidedvalues.md) | Describes the values explicitly set by user. | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [AppLeaveAction](./kibana-plugin-public.appleaveaction.md) | Possible actions to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md)See [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) and [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) | +| [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) | A handler that will be executed before leaving the application, either when going to another application or when closing the browser tab or manually changing the url. Should return confirm to to prompt a message to the user before leaving the page, or default to keep the default behavior (doing nothing).See [AppMountParameters](./kibana-plugin-public.appmountparameters.md) for detailed usage examples. | +| [AppMount](./kibana-plugin-public.appmount.md) | A mount function called when the user navigates to this app's route. | +| [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md) | A mount function called when the user navigates to this app's route. | +| [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. | +| [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) | Defines the list of fields that can be updated via an [AppUpdater](./kibana-plugin-public.appupdater.md). | +| [AppUpdater](./kibana-plugin-public.appupdater.md) | Updater for applications. see [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | +| [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) | | +| [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) | | +| [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) | | +| [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) | | +| [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) | | +| [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) | | +| [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | | +| [FatalErrorsStart](./kibana-plugin-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | +| [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. | +| [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | +| [HandlerParameters](./kibana-plugin-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). | +| [HttpStart](./kibana-plugin-public.httpstart.md) | See [HttpSetup](./kibana-plugin-public.httpsetup.md) | +| [IContextProvider](./kibana-plugin-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | +| [IToasts](./kibana-plugin-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-public.toastsapi.md). | +| [MountPoint](./kibana-plugin-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. | +| [PluginInitializer](./kibana-plugin-public.plugininitializer.md) | The plugin export at the root of a plugin's public directory should conform to this interface. | +| [PluginOpaqueId](./kibana-plugin-public.pluginopaqueid.md) | | +| [RecursiveReadonly](./kibana-plugin-public.recursivereadonly.md) | | +| [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value | +| [SavedObjectAttributeSingle](./kibana-plugin-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) | +| [SavedObjectsClientContract](./kibana-plugin-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | +| [StringValidation](./kibana-plugin-public.stringvalidation.md) | Allows regex objects or a regex string | +| [Toast](./kibana-plugin-public.toast.md) | | +| [ToastInput](./kibana-plugin-public.toastinput.md) | Inputs for [IToasts](./kibana-plugin-public.itoasts.md) APIs. | +| [ToastInputFields](./kibana-plugin-public.toastinputfields.md) | Allowed fields for [ToastInput](./kibana-plugin-public.toastinput.md). | +| [ToastsSetup](./kibana-plugin-public.toastssetup.md) | [IToasts](./kibana-plugin-public.itoasts.md) | +| [ToastsStart](./kibana-plugin-public.toastsstart.md) | [IToasts](./kibana-plugin-public.itoasts.md) | +| [UiSettingsType](./kibana-plugin-public.uisettingstype.md) | UI element type to represent the settings. | +| [UnmountCallback](./kibana-plugin-public.unmountcallback.md) | A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-public.mountpoint.md) | + diff --git a/docs/development/core/public/kibana-plugin-public.mountpoint.md b/docs/development/core/public/kibana-plugin-public.mountpoint.md index 928d22f00ed00b..4b4d1def18acc4 100644 --- a/docs/development/core/public/kibana-plugin-public.mountpoint.md +++ b/docs/development/core/public/kibana-plugin-public.mountpoint.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [MountPoint](./kibana-plugin-public.mountpoint.md) - -## MountPoint type - -A function that should mount DOM content inside the provided container element and return a handler to unmount it. - -Signature: - -```typescript -export declare type MountPoint = (element: T) => UnmountCallback; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [MountPoint](./kibana-plugin-public.mountpoint.md) + +## MountPoint type + +A function that should mount DOM content inside the provided container element and return a handler to unmount it. + +Signature: + +```typescript +export declare type MountPoint = (element: T) => UnmountCallback; +``` diff --git a/docs/development/core/public/kibana-plugin-public.notificationssetup.md b/docs/development/core/public/kibana-plugin-public.notificationssetup.md index c03abf9d01dcac..62251067b7a3d7 100644 --- a/docs/development/core/public/kibana-plugin-public.notificationssetup.md +++ b/docs/development/core/public/kibana-plugin-public.notificationssetup.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) - -## NotificationsSetup interface - - -Signature: - -```typescript -export interface NotificationsSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [toasts](./kibana-plugin-public.notificationssetup.toasts.md) | ToastsSetup | [ToastsSetup](./kibana-plugin-public.toastssetup.md) | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) + +## NotificationsSetup interface + + +Signature: + +```typescript +export interface NotificationsSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [toasts](./kibana-plugin-public.notificationssetup.toasts.md) | ToastsSetup | [ToastsSetup](./kibana-plugin-public.toastssetup.md) | + diff --git a/docs/development/core/public/kibana-plugin-public.notificationssetup.toasts.md b/docs/development/core/public/kibana-plugin-public.notificationssetup.toasts.md index dd613a959061e4..44262cd3c559c5 100644 --- a/docs/development/core/public/kibana-plugin-public.notificationssetup.toasts.md +++ b/docs/development/core/public/kibana-plugin-public.notificationssetup.toasts.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) > [toasts](./kibana-plugin-public.notificationssetup.toasts.md) - -## NotificationsSetup.toasts property - -[ToastsSetup](./kibana-plugin-public.toastssetup.md) - -Signature: - -```typescript -toasts: ToastsSetup; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) > [toasts](./kibana-plugin-public.notificationssetup.toasts.md) + +## NotificationsSetup.toasts property + +[ToastsSetup](./kibana-plugin-public.toastssetup.md) + +Signature: + +```typescript +toasts: ToastsSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.notificationsstart.md b/docs/development/core/public/kibana-plugin-public.notificationsstart.md index 56a1ce20957429..88ebd6cf3d830e 100644 --- a/docs/development/core/public/kibana-plugin-public.notificationsstart.md +++ b/docs/development/core/public/kibana-plugin-public.notificationsstart.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [NotificationsStart](./kibana-plugin-public.notificationsstart.md) - -## NotificationsStart interface - - -Signature: - -```typescript -export interface NotificationsStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [toasts](./kibana-plugin-public.notificationsstart.toasts.md) | ToastsStart | [ToastsStart](./kibana-plugin-public.toastsstart.md) | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [NotificationsStart](./kibana-plugin-public.notificationsstart.md) + +## NotificationsStart interface + + +Signature: + +```typescript +export interface NotificationsStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [toasts](./kibana-plugin-public.notificationsstart.toasts.md) | ToastsStart | [ToastsStart](./kibana-plugin-public.toastsstart.md) | + diff --git a/docs/development/core/public/kibana-plugin-public.notificationsstart.toasts.md b/docs/development/core/public/kibana-plugin-public.notificationsstart.toasts.md index 9d2c685946fdad..1e742495559d75 100644 --- a/docs/development/core/public/kibana-plugin-public.notificationsstart.toasts.md +++ b/docs/development/core/public/kibana-plugin-public.notificationsstart.toasts.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [NotificationsStart](./kibana-plugin-public.notificationsstart.md) > [toasts](./kibana-plugin-public.notificationsstart.toasts.md) - -## NotificationsStart.toasts property - -[ToastsStart](./kibana-plugin-public.toastsstart.md) - -Signature: - -```typescript -toasts: ToastsStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [NotificationsStart](./kibana-plugin-public.notificationsstart.md) > [toasts](./kibana-plugin-public.notificationsstart.toasts.md) + +## NotificationsStart.toasts property + +[ToastsStart](./kibana-plugin-public.toastsstart.md) + +Signature: + +```typescript +toasts: ToastsStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.add.md b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.add.md index 8ce59d5d9ca788..c0281090e20e10 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.add.md +++ b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.add.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) > [add](./kibana-plugin-public.overlaybannersstart.add.md) - -## OverlayBannersStart.add() method - -Add a new banner - -Signature: - -```typescript -add(mount: MountPoint, priority?: number): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mount | MountPoint | | -| priority | number | | - -Returns: - -`string` - -a unique identifier for the given banner to be used with [OverlayBannersStart.remove()](./kibana-plugin-public.overlaybannersstart.remove.md) and [OverlayBannersStart.replace()](./kibana-plugin-public.overlaybannersstart.replace.md) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) > [add](./kibana-plugin-public.overlaybannersstart.add.md) + +## OverlayBannersStart.add() method + +Add a new banner + +Signature: + +```typescript +add(mount: MountPoint, priority?: number): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mount | MountPoint | | +| priority | number | | + +Returns: + +`string` + +a unique identifier for the given banner to be used with [OverlayBannersStart.remove()](./kibana-plugin-public.overlaybannersstart.remove.md) and [OverlayBannersStart.replace()](./kibana-plugin-public.overlaybannersstart.replace.md) + diff --git a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.getcomponent.md b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.getcomponent.md index 0ecb9862dee3dd..3a89c1a0171e42 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.getcomponent.md +++ b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.getcomponent.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) > [getComponent](./kibana-plugin-public.overlaybannersstart.getcomponent.md) - -## OverlayBannersStart.getComponent() method - -Signature: - -```typescript -getComponent(): JSX.Element; -``` -Returns: - -`JSX.Element` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) > [getComponent](./kibana-plugin-public.overlaybannersstart.getcomponent.md) + +## OverlayBannersStart.getComponent() method + +Signature: + +```typescript +getComponent(): JSX.Element; +``` +Returns: + +`JSX.Element` + diff --git a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.md b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.md index 34e4ab85537924..0d5e221174a501 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.md +++ b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) - -## OverlayBannersStart interface - - -Signature: - -```typescript -export interface OverlayBannersStart -``` - -## Methods - -| Method | Description | -| --- | --- | -| [add(mount, priority)](./kibana-plugin-public.overlaybannersstart.add.md) | Add a new banner | -| [getComponent()](./kibana-plugin-public.overlaybannersstart.getcomponent.md) | | -| [remove(id)](./kibana-plugin-public.overlaybannersstart.remove.md) | Remove a banner | -| [replace(id, mount, priority)](./kibana-plugin-public.overlaybannersstart.replace.md) | Replace a banner in place | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) + +## OverlayBannersStart interface + + +Signature: + +```typescript +export interface OverlayBannersStart +``` + +## Methods + +| Method | Description | +| --- | --- | +| [add(mount, priority)](./kibana-plugin-public.overlaybannersstart.add.md) | Add a new banner | +| [getComponent()](./kibana-plugin-public.overlaybannersstart.getcomponent.md) | | +| [remove(id)](./kibana-plugin-public.overlaybannersstart.remove.md) | Remove a banner | +| [replace(id, mount, priority)](./kibana-plugin-public.overlaybannersstart.replace.md) | Replace a banner in place | + diff --git a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.remove.md b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.remove.md index 4fc5cfcd1c8d0b..8406fbbc26c21c 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.remove.md +++ b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.remove.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) > [remove](./kibana-plugin-public.overlaybannersstart.remove.md) - -## OverlayBannersStart.remove() method - -Remove a banner - -Signature: - -```typescript -remove(id: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| id | string | | - -Returns: - -`boolean` - -if the banner was found or not - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) > [remove](./kibana-plugin-public.overlaybannersstart.remove.md) + +## OverlayBannersStart.remove() method + +Remove a banner + +Signature: + +```typescript +remove(id: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`boolean` + +if the banner was found or not + diff --git a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.replace.md b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.replace.md index a8f6915ea9bb7d..5a6cd79300b741 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaybannersstart.replace.md +++ b/docs/development/core/public/kibana-plugin-public.overlaybannersstart.replace.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) > [replace](./kibana-plugin-public.overlaybannersstart.replace.md) - -## OverlayBannersStart.replace() method - -Replace a banner in place - -Signature: - -```typescript -replace(id: string | undefined, mount: MountPoint, priority?: number): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| id | string | undefined | | -| mount | MountPoint | | -| priority | number | | - -Returns: - -`string` - -a new identifier for the given banner to be used with [OverlayBannersStart.remove()](./kibana-plugin-public.overlaybannersstart.remove.md) and [OverlayBannersStart.replace()](./kibana-plugin-public.overlaybannersstart.replace.md) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) > [replace](./kibana-plugin-public.overlaybannersstart.replace.md) + +## OverlayBannersStart.replace() method + +Replace a banner in place + +Signature: + +```typescript +replace(id: string | undefined, mount: MountPoint, priority?: number): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | undefined | | +| mount | MountPoint | | +| priority | number | | + +Returns: + +`string` + +a new identifier for the given banner to be used with [OverlayBannersStart.remove()](./kibana-plugin-public.overlaybannersstart.remove.md) and [OverlayBannersStart.replace()](./kibana-plugin-public.overlaybannersstart.replace.md) + diff --git a/docs/development/core/public/kibana-plugin-public.overlayref.close.md b/docs/development/core/public/kibana-plugin-public.overlayref.close.md index 32f17882af304a..4dc0e8ab9a3c4b 100644 --- a/docs/development/core/public/kibana-plugin-public.overlayref.close.md +++ b/docs/development/core/public/kibana-plugin-public.overlayref.close.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayRef](./kibana-plugin-public.overlayref.md) > [close](./kibana-plugin-public.overlayref.close.md) - -## OverlayRef.close() method - -Closes the referenced overlay if it's still open which in turn will resolve the `onClose` Promise. If the overlay had already been closed this method does nothing. - -Signature: - -```typescript -close(): Promise; -``` -Returns: - -`Promise` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayRef](./kibana-plugin-public.overlayref.md) > [close](./kibana-plugin-public.overlayref.close.md) + +## OverlayRef.close() method + +Closes the referenced overlay if it's still open which in turn will resolve the `onClose` Promise. If the overlay had already been closed this method does nothing. + +Signature: + +```typescript +close(): Promise; +``` +Returns: + +`Promise` + diff --git a/docs/development/core/public/kibana-plugin-public.overlayref.md b/docs/development/core/public/kibana-plugin-public.overlayref.md index e71415280e4d24..a5ba8e61d3f9b3 100644 --- a/docs/development/core/public/kibana-plugin-public.overlayref.md +++ b/docs/development/core/public/kibana-plugin-public.overlayref.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayRef](./kibana-plugin-public.overlayref.md) - -## OverlayRef interface - -Returned by [OverlayStart](./kibana-plugin-public.overlaystart.md) methods for closing a mounted overlay. - -Signature: - -```typescript -export interface OverlayRef -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [onClose](./kibana-plugin-public.overlayref.onclose.md) | Promise<void> | A Promise that will resolve once this overlay is closed.Overlays can close from user interaction, calling close() on the overlay reference or another overlay replacing yours via openModal or openFlyout. | - -## Methods - -| Method | Description | -| --- | --- | -| [close()](./kibana-plugin-public.overlayref.close.md) | Closes the referenced overlay if it's still open which in turn will resolve the onClose Promise. If the overlay had already been closed this method does nothing. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayRef](./kibana-plugin-public.overlayref.md) + +## OverlayRef interface + +Returned by [OverlayStart](./kibana-plugin-public.overlaystart.md) methods for closing a mounted overlay. + +Signature: + +```typescript +export interface OverlayRef +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [onClose](./kibana-plugin-public.overlayref.onclose.md) | Promise<void> | A Promise that will resolve once this overlay is closed.Overlays can close from user interaction, calling close() on the overlay reference or another overlay replacing yours via openModal or openFlyout. | + +## Methods + +| Method | Description | +| --- | --- | +| [close()](./kibana-plugin-public.overlayref.close.md) | Closes the referenced overlay if it's still open which in turn will resolve the onClose Promise. If the overlay had already been closed this method does nothing. | + diff --git a/docs/development/core/public/kibana-plugin-public.overlayref.onclose.md b/docs/development/core/public/kibana-plugin-public.overlayref.onclose.md index 641b48b2b1ca11..64b4526b5c3ce3 100644 --- a/docs/development/core/public/kibana-plugin-public.overlayref.onclose.md +++ b/docs/development/core/public/kibana-plugin-public.overlayref.onclose.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayRef](./kibana-plugin-public.overlayref.md) > [onClose](./kibana-plugin-public.overlayref.onclose.md) - -## OverlayRef.onClose property - -A Promise that will resolve once this overlay is closed. - -Overlays can close from user interaction, calling `close()` on the overlay reference or another overlay replacing yours via `openModal` or `openFlyout`. - -Signature: - -```typescript -onClose: Promise; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayRef](./kibana-plugin-public.overlayref.md) > [onClose](./kibana-plugin-public.overlayref.onclose.md) + +## OverlayRef.onClose property + +A Promise that will resolve once this overlay is closed. + +Overlays can close from user interaction, calling `close()` on the overlay reference or another overlay replacing yours via `openModal` or `openFlyout`. + +Signature: + +```typescript +onClose: Promise; +``` diff --git a/docs/development/core/public/kibana-plugin-public.overlaystart.banners.md b/docs/development/core/public/kibana-plugin-public.overlaystart.banners.md index 60ecc4b873f0d8..a9dc10dfcbc80a 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaystart.banners.md +++ b/docs/development/core/public/kibana-plugin-public.overlaystart.banners.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [banners](./kibana-plugin-public.overlaystart.banners.md) - -## OverlayStart.banners property - -[OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) - -Signature: - -```typescript -banners: OverlayBannersStart; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [banners](./kibana-plugin-public.overlaystart.banners.md) + +## OverlayStart.banners property + +[OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) + +Signature: + +```typescript +banners: OverlayBannersStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.overlaystart.md b/docs/development/core/public/kibana-plugin-public.overlaystart.md index a83044763344ba..1f9d9d020ecf0b 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaystart.md +++ b/docs/development/core/public/kibana-plugin-public.overlaystart.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) - -## OverlayStart interface - - -Signature: - -```typescript -export interface OverlayStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [banners](./kibana-plugin-public.overlaystart.banners.md) | OverlayBannersStart | [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) | -| [openConfirm](./kibana-plugin-public.overlaystart.openconfirm.md) | OverlayModalStart['openConfirm'] | | -| [openFlyout](./kibana-plugin-public.overlaystart.openflyout.md) | OverlayFlyoutStart['open'] | | -| [openModal](./kibana-plugin-public.overlaystart.openmodal.md) | OverlayModalStart['open'] | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) + +## OverlayStart interface + + +Signature: + +```typescript +export interface OverlayStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [banners](./kibana-plugin-public.overlaystart.banners.md) | OverlayBannersStart | [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) | +| [openConfirm](./kibana-plugin-public.overlaystart.openconfirm.md) | OverlayModalStart['openConfirm'] | | +| [openFlyout](./kibana-plugin-public.overlaystart.openflyout.md) | OverlayFlyoutStart['open'] | | +| [openModal](./kibana-plugin-public.overlaystart.openmodal.md) | OverlayModalStart['open'] | | + diff --git a/docs/development/core/public/kibana-plugin-public.overlaystart.openconfirm.md b/docs/development/core/public/kibana-plugin-public.overlaystart.openconfirm.md index 543a69e0b33184..8c53cb39b60ef3 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaystart.openconfirm.md +++ b/docs/development/core/public/kibana-plugin-public.overlaystart.openconfirm.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [openConfirm](./kibana-plugin-public.overlaystart.openconfirm.md) - -## OverlayStart.openConfirm property - - -Signature: - -```typescript -openConfirm: OverlayModalStart['openConfirm']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [openConfirm](./kibana-plugin-public.overlaystart.openconfirm.md) + +## OverlayStart.openConfirm property + + +Signature: + +```typescript +openConfirm: OverlayModalStart['openConfirm']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.overlaystart.openflyout.md b/docs/development/core/public/kibana-plugin-public.overlaystart.openflyout.md index ad3351fb4d098b..1717d881a88066 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaystart.openflyout.md +++ b/docs/development/core/public/kibana-plugin-public.overlaystart.openflyout.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [openFlyout](./kibana-plugin-public.overlaystart.openflyout.md) - -## OverlayStart.openFlyout property - - -Signature: - -```typescript -openFlyout: OverlayFlyoutStart['open']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [openFlyout](./kibana-plugin-public.overlaystart.openflyout.md) + +## OverlayStart.openFlyout property + + +Signature: + +```typescript +openFlyout: OverlayFlyoutStart['open']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.overlaystart.openmodal.md b/docs/development/core/public/kibana-plugin-public.overlaystart.openmodal.md index 2c983d6151f4ca..2c5a30be5138e6 100644 --- a/docs/development/core/public/kibana-plugin-public.overlaystart.openmodal.md +++ b/docs/development/core/public/kibana-plugin-public.overlaystart.openmodal.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [openModal](./kibana-plugin-public.overlaystart.openmodal.md) - -## OverlayStart.openModal property - - -Signature: - -```typescript -openModal: OverlayModalStart['open']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [openModal](./kibana-plugin-public.overlaystart.openmodal.md) + +## OverlayStart.openModal property + + +Signature: + +```typescript +openModal: OverlayModalStart['open']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.packageinfo.branch.md b/docs/development/core/public/kibana-plugin-public.packageinfo.branch.md index 774a2909699386..008edb80af86e7 100644 --- a/docs/development/core/public/kibana-plugin-public.packageinfo.branch.md +++ b/docs/development/core/public/kibana-plugin-public.packageinfo.branch.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [branch](./kibana-plugin-public.packageinfo.branch.md) - -## PackageInfo.branch property - -Signature: - -```typescript -branch: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [branch](./kibana-plugin-public.packageinfo.branch.md) + +## PackageInfo.branch property + +Signature: + +```typescript +branch: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.packageinfo.buildnum.md b/docs/development/core/public/kibana-plugin-public.packageinfo.buildnum.md index 0c1003f8d8aff1..8895955e4dee1b 100644 --- a/docs/development/core/public/kibana-plugin-public.packageinfo.buildnum.md +++ b/docs/development/core/public/kibana-plugin-public.packageinfo.buildnum.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [buildNum](./kibana-plugin-public.packageinfo.buildnum.md) - -## PackageInfo.buildNum property - -Signature: - -```typescript -buildNum: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [buildNum](./kibana-plugin-public.packageinfo.buildnum.md) + +## PackageInfo.buildNum property + +Signature: + +```typescript +buildNum: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.packageinfo.buildsha.md b/docs/development/core/public/kibana-plugin-public.packageinfo.buildsha.md index 98a7916c142e9e..f12471f5ea7f5b 100644 --- a/docs/development/core/public/kibana-plugin-public.packageinfo.buildsha.md +++ b/docs/development/core/public/kibana-plugin-public.packageinfo.buildsha.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [buildSha](./kibana-plugin-public.packageinfo.buildsha.md) - -## PackageInfo.buildSha property - -Signature: - -```typescript -buildSha: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [buildSha](./kibana-plugin-public.packageinfo.buildsha.md) + +## PackageInfo.buildSha property + +Signature: + +```typescript +buildSha: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.packageinfo.dist.md b/docs/development/core/public/kibana-plugin-public.packageinfo.dist.md index c70299bbe6fcc2..f13f2ac4c679e8 100644 --- a/docs/development/core/public/kibana-plugin-public.packageinfo.dist.md +++ b/docs/development/core/public/kibana-plugin-public.packageinfo.dist.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [dist](./kibana-plugin-public.packageinfo.dist.md) - -## PackageInfo.dist property - -Signature: - -```typescript -dist: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [dist](./kibana-plugin-public.packageinfo.dist.md) + +## PackageInfo.dist property + +Signature: + +```typescript +dist: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.packageinfo.md b/docs/development/core/public/kibana-plugin-public.packageinfo.md index 1dbd8cb85c56bf..bd38e5e2c06e1c 100644 --- a/docs/development/core/public/kibana-plugin-public.packageinfo.md +++ b/docs/development/core/public/kibana-plugin-public.packageinfo.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) - -## PackageInfo interface - - -Signature: - -```typescript -export interface PackageInfo -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [branch](./kibana-plugin-public.packageinfo.branch.md) | string | | -| [buildNum](./kibana-plugin-public.packageinfo.buildnum.md) | number | | -| [buildSha](./kibana-plugin-public.packageinfo.buildsha.md) | string | | -| [dist](./kibana-plugin-public.packageinfo.dist.md) | boolean | | -| [version](./kibana-plugin-public.packageinfo.version.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) + +## PackageInfo interface + + +Signature: + +```typescript +export interface PackageInfo +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [branch](./kibana-plugin-public.packageinfo.branch.md) | string | | +| [buildNum](./kibana-plugin-public.packageinfo.buildnum.md) | number | | +| [buildSha](./kibana-plugin-public.packageinfo.buildsha.md) | string | | +| [dist](./kibana-plugin-public.packageinfo.dist.md) | boolean | | +| [version](./kibana-plugin-public.packageinfo.version.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.packageinfo.version.md b/docs/development/core/public/kibana-plugin-public.packageinfo.version.md index 26def753e424a5..6b8267c79b6d6d 100644 --- a/docs/development/core/public/kibana-plugin-public.packageinfo.version.md +++ b/docs/development/core/public/kibana-plugin-public.packageinfo.version.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [version](./kibana-plugin-public.packageinfo.version.md) - -## PackageInfo.version property - -Signature: - -```typescript -version: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PackageInfo](./kibana-plugin-public.packageinfo.md) > [version](./kibana-plugin-public.packageinfo.version.md) + +## PackageInfo.version property + +Signature: + +```typescript +version: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.plugin.md b/docs/development/core/public/kibana-plugin-public.plugin.md index 979436e6dab378..a81f9cd60fbbe2 100644 --- a/docs/development/core/public/kibana-plugin-public.plugin.md +++ b/docs/development/core/public/kibana-plugin-public.plugin.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Plugin](./kibana-plugin-public.plugin.md) - -## Plugin interface - -The interface that should be returned by a `PluginInitializer`. - -Signature: - -```typescript -export interface Plugin -``` - -## Methods - -| Method | Description | -| --- | --- | -| [setup(core, plugins)](./kibana-plugin-public.plugin.setup.md) | | -| [start(core, plugins)](./kibana-plugin-public.plugin.start.md) | | -| [stop()](./kibana-plugin-public.plugin.stop.md) | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Plugin](./kibana-plugin-public.plugin.md) + +## Plugin interface + +The interface that should be returned by a `PluginInitializer`. + +Signature: + +```typescript +export interface Plugin +``` + +## Methods + +| Method | Description | +| --- | --- | +| [setup(core, plugins)](./kibana-plugin-public.plugin.setup.md) | | +| [start(core, plugins)](./kibana-plugin-public.plugin.start.md) | | +| [stop()](./kibana-plugin-public.plugin.stop.md) | | + diff --git a/docs/development/core/public/kibana-plugin-public.plugin.setup.md b/docs/development/core/public/kibana-plugin-public.plugin.setup.md index f058bc8d86fbce..98d7db19cc353c 100644 --- a/docs/development/core/public/kibana-plugin-public.plugin.setup.md +++ b/docs/development/core/public/kibana-plugin-public.plugin.setup.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Plugin](./kibana-plugin-public.plugin.md) > [setup](./kibana-plugin-public.plugin.setup.md) - -## Plugin.setup() method - -Signature: - -```typescript -setup(core: CoreSetup, plugins: TPluginsSetup): TSetup | Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| core | CoreSetup<TPluginsStart> | | -| plugins | TPluginsSetup | | - -Returns: - -`TSetup | Promise` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Plugin](./kibana-plugin-public.plugin.md) > [setup](./kibana-plugin-public.plugin.setup.md) + +## Plugin.setup() method + +Signature: + +```typescript +setup(core: CoreSetup, plugins: TPluginsSetup): TSetup | Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreSetup<TPluginsStart> | | +| plugins | TPluginsSetup | | + +Returns: + +`TSetup | Promise` + diff --git a/docs/development/core/public/kibana-plugin-public.plugin.start.md b/docs/development/core/public/kibana-plugin-public.plugin.start.md index b132706f4b7c02..149d925f670ef7 100644 --- a/docs/development/core/public/kibana-plugin-public.plugin.start.md +++ b/docs/development/core/public/kibana-plugin-public.plugin.start.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Plugin](./kibana-plugin-public.plugin.md) > [start](./kibana-plugin-public.plugin.start.md) - -## Plugin.start() method - -Signature: - -```typescript -start(core: CoreStart, plugins: TPluginsStart): TStart | Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| core | CoreStart | | -| plugins | TPluginsStart | | - -Returns: - -`TStart | Promise` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Plugin](./kibana-plugin-public.plugin.md) > [start](./kibana-plugin-public.plugin.start.md) + +## Plugin.start() method + +Signature: + +```typescript +start(core: CoreStart, plugins: TPluginsStart): TStart | Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreStart | | +| plugins | TPluginsStart | | + +Returns: + +`TStart | Promise` + diff --git a/docs/development/core/public/kibana-plugin-public.plugin.stop.md b/docs/development/core/public/kibana-plugin-public.plugin.stop.md index 2ccb9f5f3655b7..e30bc4b5d8933f 100644 --- a/docs/development/core/public/kibana-plugin-public.plugin.stop.md +++ b/docs/development/core/public/kibana-plugin-public.plugin.stop.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Plugin](./kibana-plugin-public.plugin.md) > [stop](./kibana-plugin-public.plugin.stop.md) - -## Plugin.stop() method - -Signature: - -```typescript -stop?(): void; -``` -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Plugin](./kibana-plugin-public.plugin.md) > [stop](./kibana-plugin-public.plugin.stop.md) + +## Plugin.stop() method + +Signature: + +```typescript +stop?(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.plugininitializer.md b/docs/development/core/public/kibana-plugin-public.plugininitializer.md index 0e1124afff3692..ec2b145c09e5ac 100644 --- a/docs/development/core/public/kibana-plugin-public.plugininitializer.md +++ b/docs/development/core/public/kibana-plugin-public.plugininitializer.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializer](./kibana-plugin-public.plugininitializer.md) - -## PluginInitializer type - -The `plugin` export at the root of a plugin's `public` directory should conform to this interface. - -Signature: - -```typescript -export declare type PluginInitializer = (core: PluginInitializerContext) => Plugin; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializer](./kibana-plugin-public.plugininitializer.md) + +## PluginInitializer type + +The `plugin` export at the root of a plugin's `public` directory should conform to this interface. + +Signature: + +```typescript +export declare type PluginInitializer = (core: PluginInitializerContext) => Plugin; +``` diff --git a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.config.md b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.config.md index 28141c9e137499..a628a2b43c4079 100644 --- a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.config.md +++ b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.config.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) > [config](./kibana-plugin-public.plugininitializercontext.config.md) - -## PluginInitializerContext.config property - -Signature: - -```typescript -readonly config: { - get: () => T; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) > [config](./kibana-plugin-public.plugininitializercontext.config.md) + +## PluginInitializerContext.config property + +Signature: + +```typescript +readonly config: { + get: () => T; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.env.md b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.env.md index 92f36ab64a1d6a..eff61de2dadb1d 100644 --- a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.env.md +++ b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.env.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) > [env](./kibana-plugin-public.plugininitializercontext.env.md) - -## PluginInitializerContext.env property - -Signature: - -```typescript -readonly env: { - mode: Readonly; - packageInfo: Readonly; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) > [env](./kibana-plugin-public.plugininitializercontext.env.md) + +## PluginInitializerContext.env property + +Signature: + +```typescript +readonly env: { + mode: Readonly; + packageInfo: Readonly; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.md b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.md index 64eaabb28646de..78c5a88f89c8ec 100644 --- a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.md +++ b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) - -## PluginInitializerContext interface - -The available core services passed to a `PluginInitializer` - -Signature: - -```typescript -export interface PluginInitializerContext -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [config](./kibana-plugin-public.plugininitializercontext.config.md) | {
get: <T extends object = ConfigSchema>() => T;
} | | -| [env](./kibana-plugin-public.plugininitializercontext.env.md) | {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
} | | -| [opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) | PluginOpaqueId | A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) + +## PluginInitializerContext interface + +The available core services passed to a `PluginInitializer` + +Signature: + +```typescript +export interface PluginInitializerContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [config](./kibana-plugin-public.plugininitializercontext.config.md) | {
get: <T extends object = ConfigSchema>() => T;
} | | +| [env](./kibana-plugin-public.plugininitializercontext.env.md) | {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
} | | +| [opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) | PluginOpaqueId | A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. | + diff --git a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.opaqueid.md b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.opaqueid.md index 10e6b79be49594..5a77dc154f1cce 100644 --- a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.opaqueid.md +++ b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.opaqueid.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) > [opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) - -## PluginInitializerContext.opaqueId property - -A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. - -Signature: - -```typescript -readonly opaqueId: PluginOpaqueId; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) > [opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) + +## PluginInitializerContext.opaqueId property + +A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. + +Signature: + +```typescript +readonly opaqueId: PluginOpaqueId; +``` diff --git a/docs/development/core/public/kibana-plugin-public.pluginopaqueid.md b/docs/development/core/public/kibana-plugin-public.pluginopaqueid.md index 8a8202ae1334e8..54aa8c60f9f6fd 100644 --- a/docs/development/core/public/kibana-plugin-public.pluginopaqueid.md +++ b/docs/development/core/public/kibana-plugin-public.pluginopaqueid.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginOpaqueId](./kibana-plugin-public.pluginopaqueid.md) - -## PluginOpaqueId type - - -Signature: - -```typescript -export declare type PluginOpaqueId = symbol; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginOpaqueId](./kibana-plugin-public.pluginopaqueid.md) + +## PluginOpaqueId type + + +Signature: + +```typescript +export declare type PluginOpaqueId = symbol; +``` diff --git a/docs/development/core/public/kibana-plugin-public.recursivereadonly.md b/docs/development/core/public/kibana-plugin-public.recursivereadonly.md index fe048494063a09..8fe63c4ed838ed 100644 --- a/docs/development/core/public/kibana-plugin-public.recursivereadonly.md +++ b/docs/development/core/public/kibana-plugin-public.recursivereadonly.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [RecursiveReadonly](./kibana-plugin-public.recursivereadonly.md) - -## RecursiveReadonly type - - -Signature: - -```typescript -export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [RecursiveReadonly](./kibana-plugin-public.recursivereadonly.md) + +## RecursiveReadonly type + + +Signature: + +```typescript +export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ + [K in keyof T]: RecursiveReadonly; +}> : T; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.attributes.md b/docs/development/core/public/kibana-plugin-public.savedobject.attributes.md index 0ec57d679920c2..b619418da84324 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.attributes.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.attributes.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [attributes](./kibana-plugin-public.savedobject.attributes.md) - -## SavedObject.attributes property - -The data for a Saved Object is stored as an object in the `attributes` property. - -Signature: - -```typescript -attributes: T; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [attributes](./kibana-plugin-public.savedobject.attributes.md) + +## SavedObject.attributes property + +The data for a Saved Object is stored as an object in the `attributes` property. + +Signature: + +```typescript +attributes: T; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.error.md b/docs/development/core/public/kibana-plugin-public.savedobject.error.md index 1d00863ef6ecf4..a085da04d0c716 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.error.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.error.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [error](./kibana-plugin-public.savedobject.error.md) - -## SavedObject.error property - -Signature: - -```typescript -error?: { - message: string; - statusCode: number; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [error](./kibana-plugin-public.savedobject.error.md) + +## SavedObject.error property + +Signature: + +```typescript +error?: { + message: string; + statusCode: number; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.id.md b/docs/development/core/public/kibana-plugin-public.savedobject.id.md index 7b54e0a7c2a746..1e2fc6e8fbc64e 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.id.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [id](./kibana-plugin-public.savedobject.id.md) - -## SavedObject.id property - -The ID of this Saved Object, guaranteed to be unique for all objects of the same `type` - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [id](./kibana-plugin-public.savedobject.id.md) + +## SavedObject.id property + +The ID of this Saved Object, guaranteed to be unique for all objects of the same `type` + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.md b/docs/development/core/public/kibana-plugin-public.savedobject.md index 00260c62dd9341..b1bb3e267bf0ea 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) - -## SavedObject interface - - -Signature: - -```typescript -export interface SavedObject -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [attributes](./kibana-plugin-public.savedobject.attributes.md) | T | The data for a Saved Object is stored as an object in the attributes property. | -| [error](./kibana-plugin-public.savedobject.error.md) | {
message: string;
statusCode: number;
} | | -| [id](./kibana-plugin-public.savedobject.id.md) | string | The ID of this Saved Object, guaranteed to be unique for all objects of the same type | -| [migrationVersion](./kibana-plugin-public.savedobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | -| [references](./kibana-plugin-public.savedobject.references.md) | SavedObjectReference[] | A reference to another saved object. | -| [type](./kibana-plugin-public.savedobject.type.md) | string | The type of Saved Object. Each plugin can define it's own custom Saved Object types. | -| [updated\_at](./kibana-plugin-public.savedobject.updated_at.md) | string | Timestamp of the last time this document had been updated. | -| [version](./kibana-plugin-public.savedobject.version.md) | string | An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) + +## SavedObject interface + + +Signature: + +```typescript +export interface SavedObject +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [attributes](./kibana-plugin-public.savedobject.attributes.md) | T | The data for a Saved Object is stored as an object in the attributes property. | +| [error](./kibana-plugin-public.savedobject.error.md) | {
message: string;
statusCode: number;
} | | +| [id](./kibana-plugin-public.savedobject.id.md) | string | The ID of this Saved Object, guaranteed to be unique for all objects of the same type | +| [migrationVersion](./kibana-plugin-public.savedobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [references](./kibana-plugin-public.savedobject.references.md) | SavedObjectReference[] | A reference to another saved object. | +| [type](./kibana-plugin-public.savedobject.type.md) | string | The type of Saved Object. Each plugin can define it's own custom Saved Object types. | +| [updated\_at](./kibana-plugin-public.savedobject.updated_at.md) | string | Timestamp of the last time this document had been updated. | +| [version](./kibana-plugin-public.savedobject.version.md) | string | An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.migrationversion.md b/docs/development/core/public/kibana-plugin-public.savedobject.migrationversion.md index d07b664f11ff29..98c274df3473ce 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.migrationversion.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.migrationversion.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [migrationVersion](./kibana-plugin-public.savedobject.migrationversion.md) - -## SavedObject.migrationVersion property - -Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. - -Signature: - -```typescript -migrationVersion?: SavedObjectsMigrationVersion; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [migrationVersion](./kibana-plugin-public.savedobject.migrationversion.md) + +## SavedObject.migrationVersion property + +Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. + +Signature: + +```typescript +migrationVersion?: SavedObjectsMigrationVersion; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.references.md b/docs/development/core/public/kibana-plugin-public.savedobject.references.md index 3c3ecdd283b5f0..055275fcb48a7b 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.references.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.references.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [references](./kibana-plugin-public.savedobject.references.md) - -## SavedObject.references property - -A reference to another saved object. - -Signature: - -```typescript -references: SavedObjectReference[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [references](./kibana-plugin-public.savedobject.references.md) + +## SavedObject.references property + +A reference to another saved object. + +Signature: + +```typescript +references: SavedObjectReference[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.type.md b/docs/development/core/public/kibana-plugin-public.savedobject.type.md index 2bce5b8a15634d..0f7096ec143f7d 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.type.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [type](./kibana-plugin-public.savedobject.type.md) - -## SavedObject.type property - -The type of Saved Object. Each plugin can define it's own custom Saved Object types. - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [type](./kibana-plugin-public.savedobject.type.md) + +## SavedObject.type property + +The type of Saved Object. Each plugin can define it's own custom Saved Object types. + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.updated_at.md b/docs/development/core/public/kibana-plugin-public.savedobject.updated_at.md index 861128c69ae2ab..0bea6d602a9a0c 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.updated_at.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.updated_at.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [updated\_at](./kibana-plugin-public.savedobject.updated_at.md) - -## SavedObject.updated\_at property - -Timestamp of the last time this document had been updated. - -Signature: - -```typescript -updated_at?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [updated\_at](./kibana-plugin-public.savedobject.updated_at.md) + +## SavedObject.updated\_at property + +Timestamp of the last time this document had been updated. + +Signature: + +```typescript +updated_at?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobject.version.md b/docs/development/core/public/kibana-plugin-public.savedobject.version.md index 26356f444f2ca6..572d7f73057564 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobject.version.md +++ b/docs/development/core/public/kibana-plugin-public.savedobject.version.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [version](./kibana-plugin-public.savedobject.version.md) - -## SavedObject.version property - -An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. - -Signature: - -```typescript -version?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObject](./kibana-plugin-public.savedobject.md) > [version](./kibana-plugin-public.savedobject.version.md) + +## SavedObject.version property + +An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. + +Signature: + +```typescript +version?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectattribute.md b/docs/development/core/public/kibana-plugin-public.savedobjectattribute.md index 5ce6a60f76c795..00f8e7216d4457 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectattribute.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectattribute.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) - -## SavedObjectAttribute type - -Type definition for a Saved Object attribute value - -Signature: - -```typescript -export declare type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttributeSingle[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) + +## SavedObjectAttribute type + +Type definition for a Saved Object attribute value + +Signature: + +```typescript +export declare type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttributeSingle[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectattributes.md b/docs/development/core/public/kibana-plugin-public.savedobjectattributes.md index 39c02216f4827e..54cc3edeb52243 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectattributes.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectattributes.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectAttributes](./kibana-plugin-public.savedobjectattributes.md) - -## SavedObjectAttributes interface - -The data for a Saved Object is stored as an object in the `attributes` property. - -Signature: - -```typescript -export interface SavedObjectAttributes -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectAttributes](./kibana-plugin-public.savedobjectattributes.md) + +## SavedObjectAttributes interface + +The data for a Saved Object is stored as an object in the `attributes` property. + +Signature: + +```typescript +export interface SavedObjectAttributes +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectattributesingle.md b/docs/development/core/public/kibana-plugin-public.savedobjectattributesingle.md index 3f2d70baa64e61..a72538a5ee4a9f 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectattributesingle.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectattributesingle.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectAttributeSingle](./kibana-plugin-public.savedobjectattributesingle.md) - -## SavedObjectAttributeSingle type - -Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) - -Signature: - -```typescript -export declare type SavedObjectAttributeSingle = string | number | boolean | null | undefined | SavedObjectAttributes; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectAttributeSingle](./kibana-plugin-public.savedobjectattributesingle.md) + +## SavedObjectAttributeSingle type + +Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) + +Signature: + +```typescript +export declare type SavedObjectAttributeSingle = string | number | boolean | null | undefined | SavedObjectAttributes; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectreference.id.md b/docs/development/core/public/kibana-plugin-public.savedobjectreference.id.md index 27b820607f8601..1bc1f35641df05 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectreference.id.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectreference.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) > [id](./kibana-plugin-public.savedobjectreference.id.md) - -## SavedObjectReference.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) > [id](./kibana-plugin-public.savedobjectreference.id.md) + +## SavedObjectReference.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectreference.md b/docs/development/core/public/kibana-plugin-public.savedobjectreference.md index 7ae05e24a5d89a..f6c0d3676f64f5 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectreference.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectreference.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) - -## SavedObjectReference interface - -A reference to another saved object. - -Signature: - -```typescript -export interface SavedObjectReference -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [id](./kibana-plugin-public.savedobjectreference.id.md) | string | | -| [name](./kibana-plugin-public.savedobjectreference.name.md) | string | | -| [type](./kibana-plugin-public.savedobjectreference.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) + +## SavedObjectReference interface + +A reference to another saved object. + +Signature: + +```typescript +export interface SavedObjectReference +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-public.savedobjectreference.id.md) | string | | +| [name](./kibana-plugin-public.savedobjectreference.name.md) | string | | +| [type](./kibana-plugin-public.savedobjectreference.type.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectreference.name.md b/docs/development/core/public/kibana-plugin-public.savedobjectreference.name.md index 104a8c313b528f..cd39686b09ad76 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectreference.name.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectreference.name.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) > [name](./kibana-plugin-public.savedobjectreference.name.md) - -## SavedObjectReference.name property - -Signature: - -```typescript -name: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) > [name](./kibana-plugin-public.savedobjectreference.name.md) + +## SavedObjectReference.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectreference.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectreference.type.md index 5b55a18becab78..deba8fe324843a 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectreference.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectreference.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) > [type](./kibana-plugin-public.savedobjectreference.type.md) - -## SavedObjectReference.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) > [type](./kibana-plugin-public.savedobjectreference.type.md) + +## SavedObjectReference.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbaseoptions.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbaseoptions.md index 00ea2fd1582913..1fc64405d77021 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbaseoptions.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbaseoptions.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBaseOptions](./kibana-plugin-public.savedobjectsbaseoptions.md) - -## SavedObjectsBaseOptions interface - - -Signature: - -```typescript -export interface SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [namespace](./kibana-plugin-public.savedobjectsbaseoptions.namespace.md) | string | Specify the namespace for this operation | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBaseOptions](./kibana-plugin-public.savedobjectsbaseoptions.md) + +## SavedObjectsBaseOptions interface + + +Signature: + +```typescript +export interface SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [namespace](./kibana-plugin-public.savedobjectsbaseoptions.namespace.md) | string | Specify the namespace for this operation | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbaseoptions.namespace.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbaseoptions.namespace.md index fb8d0d957a2758..a30b6e9963a749 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbaseoptions.namespace.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbaseoptions.namespace.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBaseOptions](./kibana-plugin-public.savedobjectsbaseoptions.md) > [namespace](./kibana-plugin-public.savedobjectsbaseoptions.namespace.md) - -## SavedObjectsBaseOptions.namespace property - -Specify the namespace for this operation - -Signature: - -```typescript -namespace?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBaseOptions](./kibana-plugin-public.savedobjectsbaseoptions.md) > [namespace](./kibana-plugin-public.savedobjectsbaseoptions.namespace.md) + +## SavedObjectsBaseOptions.namespace property + +Specify the namespace for this operation + +Signature: + +```typescript +namespace?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbatchresponse.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbatchresponse.md index 2ccddb8f71bd6d..5a08b3f97f4299 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbatchresponse.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbatchresponse.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBatchResponse](./kibana-plugin-public.savedobjectsbatchresponse.md) - -## SavedObjectsBatchResponse interface - - -Signature: - -```typescript -export interface SavedObjectsBatchResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [savedObjects](./kibana-plugin-public.savedobjectsbatchresponse.savedobjects.md) | Array<SimpleSavedObject<T>> | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBatchResponse](./kibana-plugin-public.savedobjectsbatchresponse.md) + +## SavedObjectsBatchResponse interface + + +Signature: + +```typescript +export interface SavedObjectsBatchResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [savedObjects](./kibana-plugin-public.savedobjectsbatchresponse.savedobjects.md) | Array<SimpleSavedObject<T>> | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbatchresponse.savedobjects.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbatchresponse.savedobjects.md index f83b6268431c7f..7b8e1acb0d9dec 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbatchresponse.savedobjects.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbatchresponse.savedobjects.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBatchResponse](./kibana-plugin-public.savedobjectsbatchresponse.md) > [savedObjects](./kibana-plugin-public.savedobjectsbatchresponse.savedobjects.md) - -## SavedObjectsBatchResponse.savedObjects property - -Signature: - -```typescript -savedObjects: Array>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBatchResponse](./kibana-plugin-public.savedobjectsbatchresponse.md) > [savedObjects](./kibana-plugin-public.savedobjectsbatchresponse.savedobjects.md) + +## SavedObjectsBatchResponse.savedObjects property + +Signature: + +```typescript +savedObjects: Array>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.attributes.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.attributes.md index e3f7e0d6760871..f078ec35aa8162 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.attributes.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.attributes.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) > [attributes](./kibana-plugin-public.savedobjectsbulkcreateobject.attributes.md) - -## SavedObjectsBulkCreateObject.attributes property - -Signature: - -```typescript -attributes: T; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) > [attributes](./kibana-plugin-public.savedobjectsbulkcreateobject.attributes.md) + +## SavedObjectsBulkCreateObject.attributes property + +Signature: + +```typescript +attributes: T; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.md index 8f95c0533dded3..c479e9f9f3e3f1 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) - -## SavedObjectsBulkCreateObject interface - -Signature: - -```typescript -export interface SavedObjectsBulkCreateObject extends SavedObjectsCreateOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [attributes](./kibana-plugin-public.savedobjectsbulkcreateobject.attributes.md) | T | | -| [type](./kibana-plugin-public.savedobjectsbulkcreateobject.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) + +## SavedObjectsBulkCreateObject interface + +Signature: + +```typescript +export interface SavedObjectsBulkCreateObject extends SavedObjectsCreateOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [attributes](./kibana-plugin-public.savedobjectsbulkcreateobject.attributes.md) | T | | +| [type](./kibana-plugin-public.savedobjectsbulkcreateobject.type.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.type.md index 37497b91787822..3c29e99fa30c35 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateobject.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) > [type](./kibana-plugin-public.savedobjectsbulkcreateobject.type.md) - -## SavedObjectsBulkCreateObject.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) > [type](./kibana-plugin-public.savedobjectsbulkcreateobject.type.md) + +## SavedObjectsBulkCreateObject.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateoptions.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateoptions.md index 697084d8eee38c..198968f93f7e4b 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateoptions.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateoptions.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateOptions](./kibana-plugin-public.savedobjectsbulkcreateoptions.md) - -## SavedObjectsBulkCreateOptions interface - - -Signature: - -```typescript -export interface SavedObjectsBulkCreateOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [overwrite](./kibana-plugin-public.savedobjectsbulkcreateoptions.overwrite.md) | boolean | If a document with the given id already exists, overwrite it's contents (default=false). | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateOptions](./kibana-plugin-public.savedobjectsbulkcreateoptions.md) + +## SavedObjectsBulkCreateOptions interface + + +Signature: + +```typescript +export interface SavedObjectsBulkCreateOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [overwrite](./kibana-plugin-public.savedobjectsbulkcreateoptions.overwrite.md) | boolean | If a document with the given id already exists, overwrite it's contents (default=false). | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateoptions.overwrite.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateoptions.overwrite.md index e3b425da892b24..0acc51bfdb76bd 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateoptions.overwrite.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkcreateoptions.overwrite.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateOptions](./kibana-plugin-public.savedobjectsbulkcreateoptions.md) > [overwrite](./kibana-plugin-public.savedobjectsbulkcreateoptions.overwrite.md) - -## SavedObjectsBulkCreateOptions.overwrite property - -If a document with the given `id` already exists, overwrite it's contents (default=false). - -Signature: - -```typescript -overwrite?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkCreateOptions](./kibana-plugin-public.savedobjectsbulkcreateoptions.md) > [overwrite](./kibana-plugin-public.savedobjectsbulkcreateoptions.overwrite.md) + +## SavedObjectsBulkCreateOptions.overwrite property + +If a document with the given `id` already exists, overwrite it's contents (default=false). + +Signature: + +```typescript +overwrite?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.attributes.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.attributes.md index 235c896532bebd..9dc333d005e8e6 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.attributes.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.attributes.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [attributes](./kibana-plugin-public.savedobjectsbulkupdateobject.attributes.md) - -## SavedObjectsBulkUpdateObject.attributes property - -Signature: - -```typescript -attributes: T; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [attributes](./kibana-plugin-public.savedobjectsbulkupdateobject.attributes.md) + +## SavedObjectsBulkUpdateObject.attributes property + +Signature: + +```typescript +attributes: T; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.id.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.id.md index 8fbece1de7aa18..4f253769fc9127 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.id.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [id](./kibana-plugin-public.savedobjectsbulkupdateobject.id.md) - -## SavedObjectsBulkUpdateObject.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [id](./kibana-plugin-public.savedobjectsbulkupdateobject.id.md) + +## SavedObjectsBulkUpdateObject.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.md index 91688c01df34c3..ca0eabb2659017 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) - -## SavedObjectsBulkUpdateObject interface - - -Signature: - -```typescript -export interface SavedObjectsBulkUpdateObject -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [attributes](./kibana-plugin-public.savedobjectsbulkupdateobject.attributes.md) | T | | -| [id](./kibana-plugin-public.savedobjectsbulkupdateobject.id.md) | string | | -| [references](./kibana-plugin-public.savedobjectsbulkupdateobject.references.md) | SavedObjectReference[] | | -| [type](./kibana-plugin-public.savedobjectsbulkupdateobject.type.md) | string | | -| [version](./kibana-plugin-public.savedobjectsbulkupdateobject.version.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) + +## SavedObjectsBulkUpdateObject interface + + +Signature: + +```typescript +export interface SavedObjectsBulkUpdateObject +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [attributes](./kibana-plugin-public.savedobjectsbulkupdateobject.attributes.md) | T | | +| [id](./kibana-plugin-public.savedobjectsbulkupdateobject.id.md) | string | | +| [references](./kibana-plugin-public.savedobjectsbulkupdateobject.references.md) | SavedObjectReference[] | | +| [type](./kibana-plugin-public.savedobjectsbulkupdateobject.type.md) | string | | +| [version](./kibana-plugin-public.savedobjectsbulkupdateobject.version.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.references.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.references.md index 3949eb809c3a07..fd24cfa13c688e 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.references.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.references.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [references](./kibana-plugin-public.savedobjectsbulkupdateobject.references.md) - -## SavedObjectsBulkUpdateObject.references property - -Signature: - -```typescript -references?: SavedObjectReference[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [references](./kibana-plugin-public.savedobjectsbulkupdateobject.references.md) + +## SavedObjectsBulkUpdateObject.references property + +Signature: + +```typescript +references?: SavedObjectReference[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.type.md index b3bd0f7eb2580a..d0c9b11316b463 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [type](./kibana-plugin-public.savedobjectsbulkupdateobject.type.md) - -## SavedObjectsBulkUpdateObject.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [type](./kibana-plugin-public.savedobjectsbulkupdateobject.type.md) + +## SavedObjectsBulkUpdateObject.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.version.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.version.md index 7608bc7aff9090..ab1844430784b2 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.version.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateobject.version.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [version](./kibana-plugin-public.savedobjectsbulkupdateobject.version.md) - -## SavedObjectsBulkUpdateObject.version property - -Signature: - -```typescript -version?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) > [version](./kibana-plugin-public.savedobjectsbulkupdateobject.version.md) + +## SavedObjectsBulkUpdateObject.version property + +Signature: + +```typescript +version?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateoptions.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateoptions.md index 8a2ecefb732836..d3c29fa40dd30a 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateoptions.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateoptions.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-public.savedobjectsbulkupdateoptions.md) - -## SavedObjectsBulkUpdateOptions interface - - -Signature: - -```typescript -export interface SavedObjectsBulkUpdateOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [namespace](./kibana-plugin-public.savedobjectsbulkupdateoptions.namespace.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-public.savedobjectsbulkupdateoptions.md) + +## SavedObjectsBulkUpdateOptions interface + + +Signature: + +```typescript +export interface SavedObjectsBulkUpdateOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [namespace](./kibana-plugin-public.savedobjectsbulkupdateoptions.namespace.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateoptions.namespace.md b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateoptions.namespace.md index 0079e56684b755..2ea3feead97929 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateoptions.namespace.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsbulkupdateoptions.namespace.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-public.savedobjectsbulkupdateoptions.md) > [namespace](./kibana-plugin-public.savedobjectsbulkupdateoptions.namespace.md) - -## SavedObjectsBulkUpdateOptions.namespace property - -Signature: - -```typescript -namespace?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-public.savedobjectsbulkupdateoptions.md) > [namespace](./kibana-plugin-public.savedobjectsbulkupdateoptions.namespace.md) + +## SavedObjectsBulkUpdateOptions.namespace property + +Signature: + +```typescript +namespace?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkcreate.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkcreate.md index 426096d96c9ba2..391b2f57205d5c 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkcreate.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkcreate.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [bulkCreate](./kibana-plugin-public.savedobjectsclient.bulkcreate.md) - -## SavedObjectsClient.bulkCreate property - -Creates multiple documents at once - -Signature: - -```typescript -bulkCreate: (objects?: SavedObjectsBulkCreateObject[], options?: SavedObjectsBulkCreateOptions) => Promise>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [bulkCreate](./kibana-plugin-public.savedobjectsclient.bulkcreate.md) + +## SavedObjectsClient.bulkCreate property + +Creates multiple documents at once + +Signature: + +```typescript +bulkCreate: (objects?: SavedObjectsBulkCreateObject[], options?: SavedObjectsBulkCreateOptions) => Promise>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkget.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkget.md index fc8b3c8258f9c3..a54dfe72167a79 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkget.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkget.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [bulkGet](./kibana-plugin-public.savedobjectsclient.bulkget.md) - -## SavedObjectsClient.bulkGet property - -Returns an array of objects by id - -Signature: - -```typescript -bulkGet: (objects?: { - id: string; - type: string; - }[]) => Promise>; -``` - -## Example - -bulkGet(\[ { id: 'one', type: 'config' }, { id: 'foo', type: 'index-pattern' } \]) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [bulkGet](./kibana-plugin-public.savedobjectsclient.bulkget.md) + +## SavedObjectsClient.bulkGet property + +Returns an array of objects by id + +Signature: + +```typescript +bulkGet: (objects?: { + id: string; + type: string; + }[]) => Promise>; +``` + +## Example + +bulkGet(\[ { id: 'one', type: 'config' }, { id: 'foo', type: 'index-pattern' } \]) + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkupdate.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkupdate.md index f39638575beb17..94ae9bb70ccdae 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkupdate.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.bulkupdate.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [bulkUpdate](./kibana-plugin-public.savedobjectsclient.bulkupdate.md) - -## SavedObjectsClient.bulkUpdate() method - -Update multiple documents at once - -Signature: - -```typescript -bulkUpdate(objects?: SavedObjectsBulkUpdateObject[]): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| objects | SavedObjectsBulkUpdateObject[] | | - -Returns: - -`Promise>` - -The result of the update operation containing both failed and updated saved objects. - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [bulkUpdate](./kibana-plugin-public.savedobjectsclient.bulkupdate.md) + +## SavedObjectsClient.bulkUpdate() method + +Update multiple documents at once + +Signature: + +```typescript +bulkUpdate(objects?: SavedObjectsBulkUpdateObject[]): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | SavedObjectsBulkUpdateObject[] | | + +Returns: + +`Promise>` + +The result of the update operation containing both failed and updated saved objects. + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.create.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.create.md index d6366494f0037f..5a7666084ea0f4 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.create.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.create.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [create](./kibana-plugin-public.savedobjectsclient.create.md) - -## SavedObjectsClient.create property - -Persists an object - -Signature: - -```typescript -create: (type: string, attributes: T, options?: SavedObjectsCreateOptions) => Promise>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [create](./kibana-plugin-public.savedobjectsclient.create.md) + +## SavedObjectsClient.create property + +Persists an object + +Signature: + +```typescript +create: (type: string, attributes: T, options?: SavedObjectsCreateOptions) => Promise>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.delete.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.delete.md index 03658cbd9fcfdd..892fd474a1c9f6 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.delete.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.delete.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [delete](./kibana-plugin-public.savedobjectsclient.delete.md) - -## SavedObjectsClient.delete property - -Deletes an object - -Signature: - -```typescript -delete: (type: string, id: string) => Promise<{}>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [delete](./kibana-plugin-public.savedobjectsclient.delete.md) + +## SavedObjectsClient.delete property + +Deletes an object + +Signature: + +```typescript +delete: (type: string, id: string) => Promise<{}>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.find.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.find.md index a4fa3f17d0d94f..d3494045952ad3 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.find.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.find.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [find](./kibana-plugin-public.savedobjectsclient.find.md) - -## SavedObjectsClient.find property - -Search for objects - -Signature: - -```typescript -find: (options: Pick) => Promise>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [find](./kibana-plugin-public.savedobjectsclient.find.md) + +## SavedObjectsClient.find property + +Search for objects + +Signature: + +```typescript +find: (options: Pick) => Promise>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.get.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.get.md index 88500f4e3a2692..bddbadd3e13618 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.get.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.get.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [get](./kibana-plugin-public.savedobjectsclient.get.md) - -## SavedObjectsClient.get property - -Fetches a single object - -Signature: - -```typescript -get: (type: string, id: string) => Promise>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [get](./kibana-plugin-public.savedobjectsclient.get.md) + +## SavedObjectsClient.get property + +Fetches a single object + +Signature: + +```typescript +get: (type: string, id: string) => Promise>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.md index 88485aa71f7c54..7aa17eae2da87c 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.md @@ -1,36 +1,36 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) - -## SavedObjectsClient class - -Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. The client-side SavedObjectsClient is a thin convenience library around the SavedObjects HTTP API for interacting with Saved Objects. - -Signature: - -```typescript -export declare class SavedObjectsClient -``` - -## Remarks - -The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `SavedObjectsClient` class. - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [bulkCreate](./kibana-plugin-public.savedobjectsclient.bulkcreate.md) | | (objects?: SavedObjectsBulkCreateObject<SavedObjectAttributes>[], options?: SavedObjectsBulkCreateOptions) => Promise<SavedObjectsBatchResponse<SavedObjectAttributes>> | Creates multiple documents at once | -| [bulkGet](./kibana-plugin-public.savedobjectsclient.bulkget.md) | | (objects?: {
id: string;
type: string;
}[]) => Promise<SavedObjectsBatchResponse<SavedObjectAttributes>> | Returns an array of objects by id | -| [create](./kibana-plugin-public.savedobjectsclient.create.md) | | <T extends SavedObjectAttributes>(type: string, attributes: T, options?: SavedObjectsCreateOptions) => Promise<SimpleSavedObject<T>> | Persists an object | -| [delete](./kibana-plugin-public.savedobjectsclient.delete.md) | | (type: string, id: string) => Promise<{}> | Deletes an object | -| [find](./kibana-plugin-public.savedobjectsclient.find.md) | | <T extends SavedObjectAttributes>(options: Pick<SavedObjectFindOptionsServer, "search" | "filter" | "type" | "page" | "perPage" | "sortField" | "fields" | "searchFields" | "hasReference" | "defaultSearchOperator">) => Promise<SavedObjectsFindResponsePublic<T>> | Search for objects | -| [get](./kibana-plugin-public.savedobjectsclient.get.md) | | <T extends SavedObjectAttributes>(type: string, id: string) => Promise<SimpleSavedObject<T>> | Fetches a single object | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [bulkUpdate(objects)](./kibana-plugin-public.savedobjectsclient.bulkupdate.md) | | Update multiple documents at once | -| [update(type, id, attributes, { version, migrationVersion, references })](./kibana-plugin-public.savedobjectsclient.update.md) | | Updates an object | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) + +## SavedObjectsClient class + +Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. The client-side SavedObjectsClient is a thin convenience library around the SavedObjects HTTP API for interacting with Saved Objects. + +Signature: + +```typescript +export declare class SavedObjectsClient +``` + +## Remarks + +The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `SavedObjectsClient` class. + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [bulkCreate](./kibana-plugin-public.savedobjectsclient.bulkcreate.md) | | (objects?: SavedObjectsBulkCreateObject<SavedObjectAttributes>[], options?: SavedObjectsBulkCreateOptions) => Promise<SavedObjectsBatchResponse<SavedObjectAttributes>> | Creates multiple documents at once | +| [bulkGet](./kibana-plugin-public.savedobjectsclient.bulkget.md) | | (objects?: {
id: string;
type: string;
}[]) => Promise<SavedObjectsBatchResponse<SavedObjectAttributes>> | Returns an array of objects by id | +| [create](./kibana-plugin-public.savedobjectsclient.create.md) | | <T extends SavedObjectAttributes>(type: string, attributes: T, options?: SavedObjectsCreateOptions) => Promise<SimpleSavedObject<T>> | Persists an object | +| [delete](./kibana-plugin-public.savedobjectsclient.delete.md) | | (type: string, id: string) => Promise<{}> | Deletes an object | +| [find](./kibana-plugin-public.savedobjectsclient.find.md) | | <T extends SavedObjectAttributes>(options: Pick<SavedObjectFindOptionsServer, "search" | "filter" | "type" | "page" | "perPage" | "sortField" | "fields" | "searchFields" | "hasReference" | "defaultSearchOperator">) => Promise<SavedObjectsFindResponsePublic<T>> | Search for objects | +| [get](./kibana-plugin-public.savedobjectsclient.get.md) | | <T extends SavedObjectAttributes>(type: string, id: string) => Promise<SimpleSavedObject<T>> | Fetches a single object | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [bulkUpdate(objects)](./kibana-plugin-public.savedobjectsclient.bulkupdate.md) | | Update multiple documents at once | +| [update(type, id, attributes, { version, migrationVersion, references })](./kibana-plugin-public.savedobjectsclient.update.md) | | Updates an object | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.update.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.update.md index 5f87f46d6206f7..9f7e46943bbd5d 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.update.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.update.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [update](./kibana-plugin-public.savedobjectsclient.update.md) - -## SavedObjectsClient.update() method - -Updates an object - -Signature: - -```typescript -update(type: string, id: string, attributes: T, { version, migrationVersion, references }?: SavedObjectsUpdateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| id | string | | -| attributes | T | | -| { version, migrationVersion, references } | SavedObjectsUpdateOptions | | - -Returns: - -`Promise>` - - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) > [update](./kibana-plugin-public.savedobjectsclient.update.md) + +## SavedObjectsClient.update() method + +Updates an object + +Signature: + +```typescript +update(type: string, id: string, attributes: T, { version, migrationVersion, references }?: SavedObjectsUpdateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| attributes | T | | +| { version, migrationVersion, references } | SavedObjectsUpdateOptions | | + +Returns: + +`Promise>` + + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclientcontract.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclientcontract.md index 876f3164feec29..fd6dc0745a1196 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsclientcontract.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclientcontract.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClientContract](./kibana-plugin-public.savedobjectsclientcontract.md) - -## SavedObjectsClientContract type - -SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) - -Signature: - -```typescript -export declare type SavedObjectsClientContract = PublicMethodsOf; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsClientContract](./kibana-plugin-public.savedobjectsclientcontract.md) + +## SavedObjectsClientContract type + +SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) + +Signature: + +```typescript +export declare type SavedObjectsClientContract = PublicMethodsOf; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.id.md b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.id.md index fc0532a10d6395..7d953afda72801 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.id.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) > [id](./kibana-plugin-public.savedobjectscreateoptions.id.md) - -## SavedObjectsCreateOptions.id property - -(Not recommended) Specify an id instead of having the saved objects service generate one for you. - -Signature: - -```typescript -id?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) > [id](./kibana-plugin-public.savedobjectscreateoptions.id.md) + +## SavedObjectsCreateOptions.id property + +(Not recommended) Specify an id instead of having the saved objects service generate one for you. + +Signature: + +```typescript +id?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.md b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.md index 08090c0f8d8c30..0e6f17739d42e5 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) - -## SavedObjectsCreateOptions interface - - -Signature: - -```typescript -export interface SavedObjectsCreateOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [id](./kibana-plugin-public.savedobjectscreateoptions.id.md) | string | (Not recommended) Specify an id instead of having the saved objects service generate one for you. | -| [migrationVersion](./kibana-plugin-public.savedobjectscreateoptions.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | -| [overwrite](./kibana-plugin-public.savedobjectscreateoptions.overwrite.md) | boolean | If a document with the given id already exists, overwrite it's contents (default=false). | -| [references](./kibana-plugin-public.savedobjectscreateoptions.references.md) | SavedObjectReference[] | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) + +## SavedObjectsCreateOptions interface + + +Signature: + +```typescript +export interface SavedObjectsCreateOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-public.savedobjectscreateoptions.id.md) | string | (Not recommended) Specify an id instead of having the saved objects service generate one for you. | +| [migrationVersion](./kibana-plugin-public.savedobjectscreateoptions.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [overwrite](./kibana-plugin-public.savedobjectscreateoptions.overwrite.md) | boolean | If a document with the given id already exists, overwrite it's contents (default=false). | +| [references](./kibana-plugin-public.savedobjectscreateoptions.references.md) | SavedObjectReference[] | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.migrationversion.md b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.migrationversion.md index 5bc6b62f6680e0..6a32b56d644f24 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.migrationversion.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.migrationversion.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) > [migrationVersion](./kibana-plugin-public.savedobjectscreateoptions.migrationversion.md) - -## SavedObjectsCreateOptions.migrationVersion property - -Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. - -Signature: - -```typescript -migrationVersion?: SavedObjectsMigrationVersion; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) > [migrationVersion](./kibana-plugin-public.savedobjectscreateoptions.migrationversion.md) + +## SavedObjectsCreateOptions.migrationVersion property + +Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. + +Signature: + +```typescript +migrationVersion?: SavedObjectsMigrationVersion; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.overwrite.md b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.overwrite.md index d83541fc9e874e..7fcac94b45a634 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.overwrite.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.overwrite.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) > [overwrite](./kibana-plugin-public.savedobjectscreateoptions.overwrite.md) - -## SavedObjectsCreateOptions.overwrite property - -If a document with the given `id` already exists, overwrite it's contents (default=false). - -Signature: - -```typescript -overwrite?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) > [overwrite](./kibana-plugin-public.savedobjectscreateoptions.overwrite.md) + +## SavedObjectsCreateOptions.overwrite property + +If a document with the given `id` already exists, overwrite it's contents (default=false). + +Signature: + +```typescript +overwrite?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.references.md b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.references.md index f6bcd47a3e8d58..d828089e198e4e 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.references.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectscreateoptions.references.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) > [references](./kibana-plugin-public.savedobjectscreateoptions.references.md) - -## SavedObjectsCreateOptions.references property - -Signature: - -```typescript -references?: SavedObjectReference[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) > [references](./kibana-plugin-public.savedobjectscreateoptions.references.md) + +## SavedObjectsCreateOptions.references property + +Signature: + +```typescript +references?: SavedObjectReference[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md index 181e2bb237c532..9f83f4226ede08 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [defaultSearchOperator](./kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md) - -## SavedObjectsFindOptions.defaultSearchOperator property - -Signature: - -```typescript -defaultSearchOperator?: 'AND' | 'OR'; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [defaultSearchOperator](./kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md) + +## SavedObjectsFindOptions.defaultSearchOperator property + +Signature: + +```typescript +defaultSearchOperator?: 'AND' | 'OR'; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.fields.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.fields.md index 20cbf04418222d..4c56f06c53ddea 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.fields.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.fields.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [fields](./kibana-plugin-public.savedobjectsfindoptions.fields.md) - -## SavedObjectsFindOptions.fields property - -An array of fields to include in the results - -Signature: - -```typescript -fields?: string[]; -``` - -## Example - -SavedObjects.find({type: 'dashboard', fields: \['attributes.name', 'attributes.location'\]}) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [fields](./kibana-plugin-public.savedobjectsfindoptions.fields.md) + +## SavedObjectsFindOptions.fields property + +An array of fields to include in the results + +Signature: + +```typescript +fields?: string[]; +``` + +## Example + +SavedObjects.find({type: 'dashboard', fields: \['attributes.name', 'attributes.location'\]}) + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.filter.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.filter.md index 82237134e0b22c..e9b9a472171f11 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.filter.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.filter.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [filter](./kibana-plugin-public.savedobjectsfindoptions.filter.md) - -## SavedObjectsFindOptions.filter property - -Signature: - -```typescript -filter?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [filter](./kibana-plugin-public.savedobjectsfindoptions.filter.md) + +## SavedObjectsFindOptions.filter property + +Signature: + +```typescript +filter?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.hasreference.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.hasreference.md index 63f65d22cc33b9..22548f2ec42888 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.hasreference.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.hasreference.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [hasReference](./kibana-plugin-public.savedobjectsfindoptions.hasreference.md) - -## SavedObjectsFindOptions.hasReference property - -Signature: - -```typescript -hasReference?: { - type: string; - id: string; - }; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [hasReference](./kibana-plugin-public.savedobjectsfindoptions.hasreference.md) + +## SavedObjectsFindOptions.hasReference property + +Signature: + +```typescript +hasReference?: { + type: string; + id: string; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.md index 4c916431d4333f..ad093cf5a38eb2 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.md @@ -1,29 +1,29 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) - -## SavedObjectsFindOptions interface - - -Signature: - -```typescript -export interface SavedObjectsFindOptions extends SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [defaultSearchOperator](./kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md) | 'AND' | 'OR' | | -| [fields](./kibana-plugin-public.savedobjectsfindoptions.fields.md) | string[] | An array of fields to include in the results | -| [filter](./kibana-plugin-public.savedobjectsfindoptions.filter.md) | string | | -| [hasReference](./kibana-plugin-public.savedobjectsfindoptions.hasreference.md) | {
type: string;
id: string;
} | | -| [page](./kibana-plugin-public.savedobjectsfindoptions.page.md) | number | | -| [perPage](./kibana-plugin-public.savedobjectsfindoptions.perpage.md) | number | | -| [search](./kibana-plugin-public.savedobjectsfindoptions.search.md) | string | Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String query argument for more information | -| [searchFields](./kibana-plugin-public.savedobjectsfindoptions.searchfields.md) | string[] | The fields to perform the parsed query against. See Elasticsearch Simple Query String fields argument for more information | -| [sortField](./kibana-plugin-public.savedobjectsfindoptions.sortfield.md) | string | | -| [sortOrder](./kibana-plugin-public.savedobjectsfindoptions.sortorder.md) | string | | -| [type](./kibana-plugin-public.savedobjectsfindoptions.type.md) | string | string[] | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) + +## SavedObjectsFindOptions interface + + +Signature: + +```typescript +export interface SavedObjectsFindOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [defaultSearchOperator](./kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md) | 'AND' | 'OR' | | +| [fields](./kibana-plugin-public.savedobjectsfindoptions.fields.md) | string[] | An array of fields to include in the results | +| [filter](./kibana-plugin-public.savedobjectsfindoptions.filter.md) | string | | +| [hasReference](./kibana-plugin-public.savedobjectsfindoptions.hasreference.md) | {
type: string;
id: string;
} | | +| [page](./kibana-plugin-public.savedobjectsfindoptions.page.md) | number | | +| [perPage](./kibana-plugin-public.savedobjectsfindoptions.perpage.md) | number | | +| [search](./kibana-plugin-public.savedobjectsfindoptions.search.md) | string | Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String query argument for more information | +| [searchFields](./kibana-plugin-public.savedobjectsfindoptions.searchfields.md) | string[] | The fields to perform the parsed query against. See Elasticsearch Simple Query String fields argument for more information | +| [sortField](./kibana-plugin-public.savedobjectsfindoptions.sortfield.md) | string | | +| [sortOrder](./kibana-plugin-public.savedobjectsfindoptions.sortorder.md) | string | | +| [type](./kibana-plugin-public.savedobjectsfindoptions.type.md) | string | string[] | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.page.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.page.md index 982005adb24546..a7d057be732478 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.page.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.page.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [page](./kibana-plugin-public.savedobjectsfindoptions.page.md) - -## SavedObjectsFindOptions.page property - -Signature: - -```typescript -page?: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [page](./kibana-plugin-public.savedobjectsfindoptions.page.md) + +## SavedObjectsFindOptions.page property + +Signature: + +```typescript +page?: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.perpage.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.perpage.md index 3c61f690d82c05..bdb0d4a6129a5c 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.perpage.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.perpage.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [perPage](./kibana-plugin-public.savedobjectsfindoptions.perpage.md) - -## SavedObjectsFindOptions.perPage property - -Signature: - -```typescript -perPage?: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [perPage](./kibana-plugin-public.savedobjectsfindoptions.perpage.md) + +## SavedObjectsFindOptions.perPage property + +Signature: + +```typescript +perPage?: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.search.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.search.md index f8f95e53298266..1a343e8902ad6c 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.search.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.search.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [search](./kibana-plugin-public.savedobjectsfindoptions.search.md) - -## SavedObjectsFindOptions.search property - -Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String `query` argument for more information - -Signature: - -```typescript -search?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [search](./kibana-plugin-public.savedobjectsfindoptions.search.md) + +## SavedObjectsFindOptions.search property + +Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String `query` argument for more information + +Signature: + +```typescript +search?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.searchfields.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.searchfields.md index 5e97ef00b44178..c86b69f28758ca 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.searchfields.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.searchfields.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [searchFields](./kibana-plugin-public.savedobjectsfindoptions.searchfields.md) - -## SavedObjectsFindOptions.searchFields property - -The fields to perform the parsed query against. See Elasticsearch Simple Query String `fields` argument for more information - -Signature: - -```typescript -searchFields?: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [searchFields](./kibana-plugin-public.savedobjectsfindoptions.searchfields.md) + +## SavedObjectsFindOptions.searchFields property + +The fields to perform the parsed query against. See Elasticsearch Simple Query String `fields` argument for more information + +Signature: + +```typescript +searchFields?: string[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.sortfield.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.sortfield.md index 14ab40894cecd3..37585b2eab803c 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.sortfield.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.sortfield.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [sortField](./kibana-plugin-public.savedobjectsfindoptions.sortfield.md) - -## SavedObjectsFindOptions.sortField property - -Signature: - -```typescript -sortField?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [sortField](./kibana-plugin-public.savedobjectsfindoptions.sortfield.md) + +## SavedObjectsFindOptions.sortField property + +Signature: + +```typescript +sortField?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.sortorder.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.sortorder.md index b1e58658c0083c..78585a6e5aae3d 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.sortorder.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.sortorder.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [sortOrder](./kibana-plugin-public.savedobjectsfindoptions.sortorder.md) - -## SavedObjectsFindOptions.sortOrder property - -Signature: - -```typescript -sortOrder?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [sortOrder](./kibana-plugin-public.savedobjectsfindoptions.sortorder.md) + +## SavedObjectsFindOptions.sortOrder property + +Signature: + +```typescript +sortOrder?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.type.md index 97db9bc11c1c43..ac8bdc3eaafcf2 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [type](./kibana-plugin-public.savedobjectsfindoptions.type.md) - -## SavedObjectsFindOptions.type property - -Signature: - -```typescript -type: string | string[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [type](./kibana-plugin-public.savedobjectsfindoptions.type.md) + +## SavedObjectsFindOptions.type property + +Signature: + +```typescript +type: string | string[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.md index 61a2daa59f16a3..f60e7305fba347 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) - -## SavedObjectsFindResponsePublic interface - -Return type of the Saved Objects `find()` method. - -\*Note\*: this type is different between the Public and Server Saved Objects clients. - -Signature: - -```typescript -export interface SavedObjectsFindResponsePublic extends SavedObjectsBatchResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [page](./kibana-plugin-public.savedobjectsfindresponsepublic.page.md) | number | | -| [perPage](./kibana-plugin-public.savedobjectsfindresponsepublic.perpage.md) | number | | -| [total](./kibana-plugin-public.savedobjectsfindresponsepublic.total.md) | number | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) + +## SavedObjectsFindResponsePublic interface + +Return type of the Saved Objects `find()` method. + +\*Note\*: this type is different between the Public and Server Saved Objects clients. + +Signature: + +```typescript +export interface SavedObjectsFindResponsePublic extends SavedObjectsBatchResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [page](./kibana-plugin-public.savedobjectsfindresponsepublic.page.md) | number | | +| [perPage](./kibana-plugin-public.savedobjectsfindresponsepublic.perpage.md) | number | | +| [total](./kibana-plugin-public.savedobjectsfindresponsepublic.total.md) | number | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.page.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.page.md index 20e96d1e0df401..f6ec58ca81171a 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.page.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.page.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) > [page](./kibana-plugin-public.savedobjectsfindresponsepublic.page.md) - -## SavedObjectsFindResponsePublic.page property - -Signature: - -```typescript -page: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) > [page](./kibana-plugin-public.savedobjectsfindresponsepublic.page.md) + +## SavedObjectsFindResponsePublic.page property + +Signature: + +```typescript +page: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.perpage.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.perpage.md index f706f9cb03b26d..490e1b9c63bd9f 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.perpage.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.perpage.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) > [perPage](./kibana-plugin-public.savedobjectsfindresponsepublic.perpage.md) - -## SavedObjectsFindResponsePublic.perPage property - -Signature: - -```typescript -perPage: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) > [perPage](./kibana-plugin-public.savedobjectsfindresponsepublic.perpage.md) + +## SavedObjectsFindResponsePublic.perPage property + +Signature: + +```typescript +perPage: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.total.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.total.md index 0a44c73436a2c5..d2b40951b46933 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.total.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindresponsepublic.total.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) > [total](./kibana-plugin-public.savedobjectsfindresponsepublic.total.md) - -## SavedObjectsFindResponsePublic.total property - -Signature: - -```typescript -total: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) > [total](./kibana-plugin-public.savedobjectsfindresponsepublic.total.md) + +## SavedObjectsFindResponsePublic.total property + +Signature: + +```typescript +total: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportconflicterror.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportconflicterror.md index 6becc3d5074617..07013273f1a547 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportconflicterror.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportconflicterror.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportConflictError](./kibana-plugin-public.savedobjectsimportconflicterror.md) - -## SavedObjectsImportConflictError interface - -Represents a failure to import due to a conflict. - -Signature: - -```typescript -export interface SavedObjectsImportConflictError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [type](./kibana-plugin-public.savedobjectsimportconflicterror.type.md) | 'conflict' | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportConflictError](./kibana-plugin-public.savedobjectsimportconflicterror.md) + +## SavedObjectsImportConflictError interface + +Represents a failure to import due to a conflict. + +Signature: + +```typescript +export interface SavedObjectsImportConflictError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [type](./kibana-plugin-public.savedobjectsimportconflicterror.type.md) | 'conflict' | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportconflicterror.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportconflicterror.type.md index af20cc8fa8df27..0151f3e7db5d6d 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportconflicterror.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportconflicterror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportConflictError](./kibana-plugin-public.savedobjectsimportconflicterror.md) > [type](./kibana-plugin-public.savedobjectsimportconflicterror.type.md) - -## SavedObjectsImportConflictError.type property - -Signature: - -```typescript -type: 'conflict'; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportConflictError](./kibana-plugin-public.savedobjectsimportconflicterror.md) > [type](./kibana-plugin-public.savedobjectsimportconflicterror.type.md) + +## SavedObjectsImportConflictError.type property + +Signature: + +```typescript +type: 'conflict'; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.error.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.error.md index ece6016e8bf542..f650c949a5713f 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.error.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.error.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) > [error](./kibana-plugin-public.savedobjectsimporterror.error.md) - -## SavedObjectsImportError.error property - -Signature: - -```typescript -error: SavedObjectsImportConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) > [error](./kibana-plugin-public.savedobjectsimporterror.error.md) + +## SavedObjectsImportError.error property + +Signature: + +```typescript +error: SavedObjectsImportConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.id.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.id.md index 995fe61745a006..6eb20036791ba8 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.id.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) > [id](./kibana-plugin-public.savedobjectsimporterror.id.md) - -## SavedObjectsImportError.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) > [id](./kibana-plugin-public.savedobjectsimporterror.id.md) + +## SavedObjectsImportError.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.md index dee8bb1c79a57d..beb51cab1b21d5 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) - -## SavedObjectsImportError interface - -Represents a failure to import. - -Signature: - -```typescript -export interface SavedObjectsImportError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [error](./kibana-plugin-public.savedobjectsimporterror.error.md) | SavedObjectsImportConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError | | -| [id](./kibana-plugin-public.savedobjectsimporterror.id.md) | string | | -| [title](./kibana-plugin-public.savedobjectsimporterror.title.md) | string | | -| [type](./kibana-plugin-public.savedobjectsimporterror.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) + +## SavedObjectsImportError interface + +Represents a failure to import. + +Signature: + +```typescript +export interface SavedObjectsImportError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [error](./kibana-plugin-public.savedobjectsimporterror.error.md) | SavedObjectsImportConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError | | +| [id](./kibana-plugin-public.savedobjectsimporterror.id.md) | string | | +| [title](./kibana-plugin-public.savedobjectsimporterror.title.md) | string | | +| [type](./kibana-plugin-public.savedobjectsimporterror.type.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.title.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.title.md index 71fa13ad4a5d09..ef719e349618a0 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.title.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.title.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) > [title](./kibana-plugin-public.savedobjectsimporterror.title.md) - -## SavedObjectsImportError.title property - -Signature: - -```typescript -title?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) > [title](./kibana-plugin-public.savedobjectsimporterror.title.md) + +## SavedObjectsImportError.title property + +Signature: + +```typescript +title?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.type.md index fe98dc928e5f0b..5b854a805cb312 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimporterror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) > [type](./kibana-plugin-public.savedobjectsimporterror.type.md) - -## SavedObjectsImportError.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) > [type](./kibana-plugin-public.savedobjectsimporterror.type.md) + +## SavedObjectsImportError.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.blocking.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.blocking.md index 76bd6e0939a96a..8223c30f948d15 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.blocking.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.blocking.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) > [blocking](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.blocking.md) - -## SavedObjectsImportMissingReferencesError.blocking property - -Signature: - -```typescript -blocking: Array<{ - type: string; - id: string; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) > [blocking](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.blocking.md) + +## SavedObjectsImportMissingReferencesError.blocking property + +Signature: + +```typescript +blocking: Array<{ + type: string; + id: string; + }>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.md index 58af9e9be0cc5e..80c17b97047e82 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) - -## SavedObjectsImportMissingReferencesError interface - -Represents a failure to import due to missing references. - -Signature: - -```typescript -export interface SavedObjectsImportMissingReferencesError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [blocking](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.blocking.md) | Array<{
type: string;
id: string;
}> | | -| [references](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.references.md) | Array<{
type: string;
id: string;
}> | | -| [type](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.type.md) | 'missing_references' | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) + +## SavedObjectsImportMissingReferencesError interface + +Represents a failure to import due to missing references. + +Signature: + +```typescript +export interface SavedObjectsImportMissingReferencesError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [blocking](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.blocking.md) | Array<{
type: string;
id: string;
}> | | +| [references](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.references.md) | Array<{
type: string;
id: string;
}> | | +| [type](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.type.md) | 'missing_references' | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.references.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.references.md index f1dc3b454f7ed9..4a40aa98ca6d0d 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.references.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.references.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) > [references](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.references.md) - -## SavedObjectsImportMissingReferencesError.references property - -Signature: - -```typescript -references: Array<{ - type: string; - id: string; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) > [references](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.references.md) + +## SavedObjectsImportMissingReferencesError.references property + +Signature: + +```typescript +references: Array<{ + type: string; + id: string; + }>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.type.md index 340b36248d83e1..62862107c11b45 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportmissingreferenceserror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) > [type](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.type.md) - -## SavedObjectsImportMissingReferencesError.type property - -Signature: - -```typescript -type: 'missing_references'; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) > [type](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.type.md) + +## SavedObjectsImportMissingReferencesError.type property + +Signature: + +```typescript +type: 'missing_references'; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.errors.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.errors.md index c085fd0f8c3b46..7bcea02f7ca49a 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.errors.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.errors.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) > [errors](./kibana-plugin-public.savedobjectsimportresponse.errors.md) - -## SavedObjectsImportResponse.errors property - -Signature: - -```typescript -errors?: SavedObjectsImportError[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) > [errors](./kibana-plugin-public.savedobjectsimportresponse.errors.md) + +## SavedObjectsImportResponse.errors property + +Signature: + +```typescript +errors?: SavedObjectsImportError[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.md index 9733f11fd6b8f1..b75f5173461950 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) - -## SavedObjectsImportResponse interface - -The response describing the result of an import. - -Signature: - -```typescript -export interface SavedObjectsImportResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [errors](./kibana-plugin-public.savedobjectsimportresponse.errors.md) | SavedObjectsImportError[] | | -| [success](./kibana-plugin-public.savedobjectsimportresponse.success.md) | boolean | | -| [successCount](./kibana-plugin-public.savedobjectsimportresponse.successcount.md) | number | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) + +## SavedObjectsImportResponse interface + +The response describing the result of an import. + +Signature: + +```typescript +export interface SavedObjectsImportResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [errors](./kibana-plugin-public.savedobjectsimportresponse.errors.md) | SavedObjectsImportError[] | | +| [success](./kibana-plugin-public.savedobjectsimportresponse.success.md) | boolean | | +| [successCount](./kibana-plugin-public.savedobjectsimportresponse.successcount.md) | number | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.success.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.success.md index 062b8ce3f7c72d..b56ce92e7a91ed 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.success.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.success.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) > [success](./kibana-plugin-public.savedobjectsimportresponse.success.md) - -## SavedObjectsImportResponse.success property - -Signature: - -```typescript -success: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) > [success](./kibana-plugin-public.savedobjectsimportresponse.success.md) + +## SavedObjectsImportResponse.success property + +Signature: + +```typescript +success: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.successcount.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.successcount.md index c2c93859261758..1d5dc3295a8b5d 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.successcount.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportresponse.successcount.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) > [successCount](./kibana-plugin-public.savedobjectsimportresponse.successcount.md) - -## SavedObjectsImportResponse.successCount property - -Signature: - -```typescript -successCount: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) > [successCount](./kibana-plugin-public.savedobjectsimportresponse.successcount.md) + +## SavedObjectsImportResponse.successCount property + +Signature: + +```typescript +successCount: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.id.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.id.md index 2569152f17b156..93a983be538f0b 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.id.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) > [id](./kibana-plugin-public.savedobjectsimportretry.id.md) - -## SavedObjectsImportRetry.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) > [id](./kibana-plugin-public.savedobjectsimportretry.id.md) + +## SavedObjectsImportRetry.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.md index e2cad52f92f2da..64021b0e363de3 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) - -## SavedObjectsImportRetry interface - -Describes a retry operation for importing a saved object. - -Signature: - -```typescript -export interface SavedObjectsImportRetry -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [id](./kibana-plugin-public.savedobjectsimportretry.id.md) | string | | -| [overwrite](./kibana-plugin-public.savedobjectsimportretry.overwrite.md) | boolean | | -| [replaceReferences](./kibana-plugin-public.savedobjectsimportretry.replacereferences.md) | Array<{
type: string;
from: string;
to: string;
}> | | -| [type](./kibana-plugin-public.savedobjectsimportretry.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) + +## SavedObjectsImportRetry interface + +Describes a retry operation for importing a saved object. + +Signature: + +```typescript +export interface SavedObjectsImportRetry +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-public.savedobjectsimportretry.id.md) | string | | +| [overwrite](./kibana-plugin-public.savedobjectsimportretry.overwrite.md) | boolean | | +| [replaceReferences](./kibana-plugin-public.savedobjectsimportretry.replacereferences.md) | Array<{
type: string;
from: string;
to: string;
}> | | +| [type](./kibana-plugin-public.savedobjectsimportretry.type.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.overwrite.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.overwrite.md index 9d1f96b2fcfcfc..836d33585c0b8a 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.overwrite.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.overwrite.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) > [overwrite](./kibana-plugin-public.savedobjectsimportretry.overwrite.md) - -## SavedObjectsImportRetry.overwrite property - -Signature: - -```typescript -overwrite: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) > [overwrite](./kibana-plugin-public.savedobjectsimportretry.overwrite.md) + +## SavedObjectsImportRetry.overwrite property + +Signature: + +```typescript +overwrite: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.replacereferences.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.replacereferences.md index fe587ef8134cc5..35ad49b0cdf979 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.replacereferences.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.replacereferences.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) > [replaceReferences](./kibana-plugin-public.savedobjectsimportretry.replacereferences.md) - -## SavedObjectsImportRetry.replaceReferences property - -Signature: - -```typescript -replaceReferences: Array<{ - type: string; - from: string; - to: string; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) > [replaceReferences](./kibana-plugin-public.savedobjectsimportretry.replacereferences.md) + +## SavedObjectsImportRetry.replaceReferences property + +Signature: + +```typescript +replaceReferences: Array<{ + type: string; + from: string; + to: string; + }>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.type.md index b84dac102483ae..a7795ca326f335 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportretry.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) > [type](./kibana-plugin-public.savedobjectsimportretry.type.md) - -## SavedObjectsImportRetry.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) > [type](./kibana-plugin-public.savedobjectsimportretry.type.md) + +## SavedObjectsImportRetry.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.md index e6837571717879..cb949bad670450 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) - -## SavedObjectsImportUnknownError interface - -Represents a failure to import due to an unknown reason. - -Signature: - -```typescript -export interface SavedObjectsImportUnknownError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [message](./kibana-plugin-public.savedobjectsimportunknownerror.message.md) | string | | -| [statusCode](./kibana-plugin-public.savedobjectsimportunknownerror.statuscode.md) | number | | -| [type](./kibana-plugin-public.savedobjectsimportunknownerror.type.md) | 'unknown' | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) + +## SavedObjectsImportUnknownError interface + +Represents a failure to import due to an unknown reason. + +Signature: + +```typescript +export interface SavedObjectsImportUnknownError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [message](./kibana-plugin-public.savedobjectsimportunknownerror.message.md) | string | | +| [statusCode](./kibana-plugin-public.savedobjectsimportunknownerror.statuscode.md) | number | | +| [type](./kibana-plugin-public.savedobjectsimportunknownerror.type.md) | 'unknown' | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.message.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.message.md index 976c2817bda0a2..7a775d4ad8be52 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.message.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.message.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) > [message](./kibana-plugin-public.savedobjectsimportunknownerror.message.md) - -## SavedObjectsImportUnknownError.message property - -Signature: - -```typescript -message: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) > [message](./kibana-plugin-public.savedobjectsimportunknownerror.message.md) + +## SavedObjectsImportUnknownError.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.statuscode.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.statuscode.md index 6c7255dd4b6313..cea023fe577e51 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.statuscode.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.statuscode.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) > [statusCode](./kibana-plugin-public.savedobjectsimportunknownerror.statuscode.md) - -## SavedObjectsImportUnknownError.statusCode property - -Signature: - -```typescript -statusCode: number; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) > [statusCode](./kibana-plugin-public.savedobjectsimportunknownerror.statuscode.md) + +## SavedObjectsImportUnknownError.statusCode property + +Signature: + +```typescript +statusCode: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.type.md index 2ef764d68322e6..4f533bf6c6347b 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunknownerror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) > [type](./kibana-plugin-public.savedobjectsimportunknownerror.type.md) - -## SavedObjectsImportUnknownError.type property - -Signature: - -```typescript -type: 'unknown'; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) > [type](./kibana-plugin-public.savedobjectsimportunknownerror.type.md) + +## SavedObjectsImportUnknownError.type property + +Signature: + +```typescript +type: 'unknown'; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md index 09ae53c0313528..caa7a2729e6a0b 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md) - -## SavedObjectsImportUnsupportedTypeError interface - -Represents a failure to import due to having an unsupported saved object type. - -Signature: - -```typescript -export interface SavedObjectsImportUnsupportedTypeError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [type](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.type.md) | 'unsupported_type' | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md) + +## SavedObjectsImportUnsupportedTypeError interface + +Represents a failure to import due to having an unsupported saved object type. + +Signature: + +```typescript +export interface SavedObjectsImportUnsupportedTypeError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [type](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.type.md) | 'unsupported_type' | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunsupportedtypeerror.type.md b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunsupportedtypeerror.type.md index 55ddf15058faba..e6d20db043408b 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsimportunsupportedtypeerror.type.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsimportunsupportedtypeerror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md) > [type](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.type.md) - -## SavedObjectsImportUnsupportedTypeError.type property - -Signature: - -```typescript -type: 'unsupported_type'; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md) > [type](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.type.md) + +## SavedObjectsImportUnsupportedTypeError.type property + +Signature: + +```typescript +type: 'unsupported_type'; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsmigrationversion.md b/docs/development/core/public/kibana-plugin-public.savedobjectsmigrationversion.md index 675adb9498c507..7a50744acee306 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsmigrationversion.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsmigrationversion.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsMigrationVersion](./kibana-plugin-public.savedobjectsmigrationversion.md) - -## SavedObjectsMigrationVersion interface - -Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. - -Signature: - -```typescript -export interface SavedObjectsMigrationVersion -``` - -## Example - -migrationVersion: { dashboard: '7.1.1', space: '6.6.6', } - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsMigrationVersion](./kibana-plugin-public.savedobjectsmigrationversion.md) + +## SavedObjectsMigrationVersion interface + +Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. + +Signature: + +```typescript +export interface SavedObjectsMigrationVersion +``` + +## Example + +migrationVersion: { dashboard: '7.1.1', space: '6.6.6', } + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsstart.client.md b/docs/development/core/public/kibana-plugin-public.savedobjectsstart.client.md index d3e0da7a414b0d..be4bf6c5c21bfd 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsstart.client.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsstart.client.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) > [client](./kibana-plugin-public.savedobjectsstart.client.md) - -## SavedObjectsStart.client property - -[SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) - -Signature: - -```typescript -client: SavedObjectsClientContract; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) > [client](./kibana-plugin-public.savedobjectsstart.client.md) + +## SavedObjectsStart.client property + +[SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) + +Signature: + +```typescript +client: SavedObjectsClientContract; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md b/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md index 07a70f306cd26a..a7e69205bcf954 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) - -## SavedObjectsStart interface - - -Signature: - -```typescript -export interface SavedObjectsStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [client](./kibana-plugin-public.savedobjectsstart.client.md) | SavedObjectsClientContract | [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) + +## SavedObjectsStart interface + + +Signature: + +```typescript +export interface SavedObjectsStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [client](./kibana-plugin-public.savedobjectsstart.client.md) | SavedObjectsClientContract | [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.md b/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.md index 800a78d65486bc..dc9dc947516078 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) - -## SavedObjectsUpdateOptions interface - - -Signature: - -```typescript -export interface SavedObjectsUpdateOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [migrationVersion](./kibana-plugin-public.savedobjectsupdateoptions.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | -| [references](./kibana-plugin-public.savedobjectsupdateoptions.references.md) | SavedObjectReference[] | | -| [version](./kibana-plugin-public.savedobjectsupdateoptions.version.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) + +## SavedObjectsUpdateOptions interface + + +Signature: + +```typescript +export interface SavedObjectsUpdateOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [migrationVersion](./kibana-plugin-public.savedobjectsupdateoptions.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [references](./kibana-plugin-public.savedobjectsupdateoptions.references.md) | SavedObjectReference[] | | +| [version](./kibana-plugin-public.savedobjectsupdateoptions.version.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.migrationversion.md b/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.migrationversion.md index e5fe20acd39941..69e8312c1f197d 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.migrationversion.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.migrationversion.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) > [migrationVersion](./kibana-plugin-public.savedobjectsupdateoptions.migrationversion.md) - -## SavedObjectsUpdateOptions.migrationVersion property - -Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. - -Signature: - -```typescript -migrationVersion?: SavedObjectsMigrationVersion; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) > [migrationVersion](./kibana-plugin-public.savedobjectsupdateoptions.migrationversion.md) + +## SavedObjectsUpdateOptions.migrationVersion property + +Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. + +Signature: + +```typescript +migrationVersion?: SavedObjectsMigrationVersion; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.references.md b/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.references.md index eda84ec8e0bfa2..d4f479a634af39 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.references.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.references.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) > [references](./kibana-plugin-public.savedobjectsupdateoptions.references.md) - -## SavedObjectsUpdateOptions.references property - -Signature: - -```typescript -references?: SavedObjectReference[]; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) > [references](./kibana-plugin-public.savedobjectsupdateoptions.references.md) + +## SavedObjectsUpdateOptions.references property + +Signature: + +```typescript +references?: SavedObjectReference[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.version.md b/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.version.md index 9aacfa9124016c..7e0ccf9c2d71f4 100644 --- a/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.version.md +++ b/docs/development/core/public/kibana-plugin-public.savedobjectsupdateoptions.version.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) > [version](./kibana-plugin-public.savedobjectsupdateoptions.version.md) - -## SavedObjectsUpdateOptions.version property - -Signature: - -```typescript -version?: string; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) > [version](./kibana-plugin-public.savedobjectsupdateoptions.version.md) + +## SavedObjectsUpdateOptions.version property + +Signature: + +```typescript +version?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject._constructor_.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject._constructor_.md index ebc7652a0fcf53..f0769c0124d638 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject._constructor_.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject._constructor_.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [(constructor)](./kibana-plugin-public.simplesavedobject._constructor_.md) - -## SimpleSavedObject.(constructor) - -Constructs a new instance of the `SimpleSavedObject` class - -Signature: - -```typescript -constructor(client: SavedObjectsClient, { id, type, version, attributes, error, references, migrationVersion }: SavedObjectType); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| client | SavedObjectsClient | | -| { id, type, version, attributes, error, references, migrationVersion } | SavedObjectType<T> | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [(constructor)](./kibana-plugin-public.simplesavedobject._constructor_.md) + +## SimpleSavedObject.(constructor) + +Constructs a new instance of the `SimpleSavedObject` class + +Signature: + +```typescript +constructor(client: SavedObjectsClient, { id, type, version, attributes, error, references, migrationVersion }: SavedObjectType); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| client | SavedObjectsClient | | +| { id, type, version, attributes, error, references, migrationVersion } | SavedObjectType<T> | | + diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject._version.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject._version.md index 7cbe08b8de7606..d49d4309addd43 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject._version.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject._version.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [\_version](./kibana-plugin-public.simplesavedobject._version.md) - -## SimpleSavedObject.\_version property - -Signature: - -```typescript -_version?: SavedObjectType['version']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [\_version](./kibana-plugin-public.simplesavedobject._version.md) + +## SimpleSavedObject.\_version property + +Signature: + +```typescript +_version?: SavedObjectType['version']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.attributes.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.attributes.md index 1c57136a1952ef..00898a0db5c848 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.attributes.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.attributes.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [attributes](./kibana-plugin-public.simplesavedobject.attributes.md) - -## SimpleSavedObject.attributes property - -Signature: - -```typescript -attributes: T; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [attributes](./kibana-plugin-public.simplesavedobject.attributes.md) + +## SimpleSavedObject.attributes property + +Signature: + +```typescript +attributes: T; +``` diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.delete.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.delete.md index 8a04acfedec62f..e3ce90bc1d5446 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.delete.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.delete.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [delete](./kibana-plugin-public.simplesavedobject.delete.md) - -## SimpleSavedObject.delete() method - -Signature: - -```typescript -delete(): Promise<{}>; -``` -Returns: - -`Promise<{}>` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [delete](./kibana-plugin-public.simplesavedobject.delete.md) + +## SimpleSavedObject.delete() method + +Signature: + +```typescript +delete(): Promise<{}>; +``` +Returns: + +`Promise<{}>` + diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.error.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.error.md index 0b4f914ac92e82..5731b71b521266 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.error.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.error.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [error](./kibana-plugin-public.simplesavedobject.error.md) - -## SimpleSavedObject.error property - -Signature: - -```typescript -error: SavedObjectType['error']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [error](./kibana-plugin-public.simplesavedobject.error.md) + +## SimpleSavedObject.error property + +Signature: + +```typescript +error: SavedObjectType['error']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.get.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.get.md index 39a899e4a6cd34..943a23410f6aaa 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.get.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.get.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [get](./kibana-plugin-public.simplesavedobject.get.md) - -## SimpleSavedObject.get() method - -Signature: - -```typescript -get(key: string): any; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| key | string | | - -Returns: - -`any` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [get](./kibana-plugin-public.simplesavedobject.get.md) + +## SimpleSavedObject.get() method + +Signature: + +```typescript +get(key: string): any; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string | | + +Returns: + +`any` + diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.has.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.has.md index 5f3019d55c3f69..dacdcc849635f8 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.has.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.has.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [has](./kibana-plugin-public.simplesavedobject.has.md) - -## SimpleSavedObject.has() method - -Signature: - -```typescript -has(key: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| key | string | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [has](./kibana-plugin-public.simplesavedobject.has.md) + +## SimpleSavedObject.has() method + +Signature: + +```typescript +has(key: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.id.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.id.md index ed97976c4100f9..375c5bd105aa77 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.id.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [id](./kibana-plugin-public.simplesavedobject.id.md) - -## SimpleSavedObject.id property - -Signature: - -```typescript -id: SavedObjectType['id']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [id](./kibana-plugin-public.simplesavedobject.id.md) + +## SimpleSavedObject.id property + +Signature: + +```typescript +id: SavedObjectType['id']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.md index 8dc8bdceaeb133..1f6de163ec17d5 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.md @@ -1,44 +1,44 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) - -## SimpleSavedObject class - -This class is a very simple wrapper for SavedObjects loaded from the server with the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md). - -It provides basic functionality for creating/saving/deleting saved objects, but doesn't include any type-specific implementations. - -Signature: - -```typescript -export declare class SimpleSavedObject -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(client, { id, type, version, attributes, error, references, migrationVersion })](./kibana-plugin-public.simplesavedobject._constructor_.md) | | Constructs a new instance of the SimpleSavedObject class | - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [\_version](./kibana-plugin-public.simplesavedobject._version.md) | | SavedObjectType<T>['version'] | | -| [attributes](./kibana-plugin-public.simplesavedobject.attributes.md) | | T | | -| [error](./kibana-plugin-public.simplesavedobject.error.md) | | SavedObjectType<T>['error'] | | -| [id](./kibana-plugin-public.simplesavedobject.id.md) | | SavedObjectType<T>['id'] | | -| [migrationVersion](./kibana-plugin-public.simplesavedobject.migrationversion.md) | | SavedObjectType<T>['migrationVersion'] | | -| [references](./kibana-plugin-public.simplesavedobject.references.md) | | SavedObjectType<T>['references'] | | -| [type](./kibana-plugin-public.simplesavedobject.type.md) | | SavedObjectType<T>['type'] | | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [delete()](./kibana-plugin-public.simplesavedobject.delete.md) | | | -| [get(key)](./kibana-plugin-public.simplesavedobject.get.md) | | | -| [has(key)](./kibana-plugin-public.simplesavedobject.has.md) | | | -| [save()](./kibana-plugin-public.simplesavedobject.save.md) | | | -| [set(key, value)](./kibana-plugin-public.simplesavedobject.set.md) | | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) + +## SimpleSavedObject class + +This class is a very simple wrapper for SavedObjects loaded from the server with the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md). + +It provides basic functionality for creating/saving/deleting saved objects, but doesn't include any type-specific implementations. + +Signature: + +```typescript +export declare class SimpleSavedObject +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(client, { id, type, version, attributes, error, references, migrationVersion })](./kibana-plugin-public.simplesavedobject._constructor_.md) | | Constructs a new instance of the SimpleSavedObject class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [\_version](./kibana-plugin-public.simplesavedobject._version.md) | | SavedObjectType<T>['version'] | | +| [attributes](./kibana-plugin-public.simplesavedobject.attributes.md) | | T | | +| [error](./kibana-plugin-public.simplesavedobject.error.md) | | SavedObjectType<T>['error'] | | +| [id](./kibana-plugin-public.simplesavedobject.id.md) | | SavedObjectType<T>['id'] | | +| [migrationVersion](./kibana-plugin-public.simplesavedobject.migrationversion.md) | | SavedObjectType<T>['migrationVersion'] | | +| [references](./kibana-plugin-public.simplesavedobject.references.md) | | SavedObjectType<T>['references'] | | +| [type](./kibana-plugin-public.simplesavedobject.type.md) | | SavedObjectType<T>['type'] | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [delete()](./kibana-plugin-public.simplesavedobject.delete.md) | | | +| [get(key)](./kibana-plugin-public.simplesavedobject.get.md) | | | +| [has(key)](./kibana-plugin-public.simplesavedobject.has.md) | | | +| [save()](./kibana-plugin-public.simplesavedobject.save.md) | | | +| [set(key, value)](./kibana-plugin-public.simplesavedobject.set.md) | | | + diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.migrationversion.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.migrationversion.md index 6f7b3af03099dc..e6eafa4a118459 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.migrationversion.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.migrationversion.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [migrationVersion](./kibana-plugin-public.simplesavedobject.migrationversion.md) - -## SimpleSavedObject.migrationVersion property - -Signature: - -```typescript -migrationVersion: SavedObjectType['migrationVersion']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [migrationVersion](./kibana-plugin-public.simplesavedobject.migrationversion.md) + +## SimpleSavedObject.migrationVersion property + +Signature: + +```typescript +migrationVersion: SavedObjectType['migrationVersion']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.references.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.references.md index 159f855538f62d..b4264a77f8e946 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.references.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.references.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [references](./kibana-plugin-public.simplesavedobject.references.md) - -## SimpleSavedObject.references property - -Signature: - -```typescript -references: SavedObjectType['references']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [references](./kibana-plugin-public.simplesavedobject.references.md) + +## SimpleSavedObject.references property + +Signature: + +```typescript +references: SavedObjectType['references']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.save.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.save.md index 05f8880fbcdd6a..a93b6abfec171f 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.save.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.save.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [save](./kibana-plugin-public.simplesavedobject.save.md) - -## SimpleSavedObject.save() method - -Signature: - -```typescript -save(): Promise>; -``` -Returns: - -`Promise>` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [save](./kibana-plugin-public.simplesavedobject.save.md) + +## SimpleSavedObject.save() method + +Signature: + +```typescript +save(): Promise>; +``` +Returns: + +`Promise>` + diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.set.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.set.md index ce3f9c5919d7ce..e37b03e279a12a 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.set.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.set.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [set](./kibana-plugin-public.simplesavedobject.set.md) - -## SimpleSavedObject.set() method - -Signature: - -```typescript -set(key: string, value: any): T; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| key | string | | -| value | any | | - -Returns: - -`T` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [set](./kibana-plugin-public.simplesavedobject.set.md) + +## SimpleSavedObject.set() method + +Signature: + +```typescript +set(key: string, value: any): T; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| key | string | | +| value | any | | + +Returns: + +`T` + diff --git a/docs/development/core/public/kibana-plugin-public.simplesavedobject.type.md b/docs/development/core/public/kibana-plugin-public.simplesavedobject.type.md index b004c70013d6d8..5a8b8057460d3f 100644 --- a/docs/development/core/public/kibana-plugin-public.simplesavedobject.type.md +++ b/docs/development/core/public/kibana-plugin-public.simplesavedobject.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [type](./kibana-plugin-public.simplesavedobject.type.md) - -## SimpleSavedObject.type property - -Signature: - -```typescript -type: SavedObjectType['type']; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) > [type](./kibana-plugin-public.simplesavedobject.type.md) + +## SimpleSavedObject.type property + +Signature: + +```typescript +type: SavedObjectType['type']; +``` diff --git a/docs/development/core/public/kibana-plugin-public.stringvalidation.md b/docs/development/core/public/kibana-plugin-public.stringvalidation.md new file mode 100644 index 00000000000000..542836c0ba99e8 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.stringvalidation.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [StringValidation](./kibana-plugin-public.stringvalidation.md) + +## StringValidation type + +Allows regex objects or a regex string + +Signature: + +```typescript +export declare type StringValidation = StringValidationRegex | StringValidationRegexString; +``` diff --git a/docs/development/core/public/kibana-plugin-public.stringvalidationregex.md b/docs/development/core/public/kibana-plugin-public.stringvalidationregex.md new file mode 100644 index 00000000000000..e568d9fc035da1 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.stringvalidationregex.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [StringValidationRegex](./kibana-plugin-public.stringvalidationregex.md) + +## StringValidationRegex interface + +StringValidation with regex object + +Signature: + +```typescript +export interface StringValidationRegex +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [message](./kibana-plugin-public.stringvalidationregex.message.md) | string | | +| [regex](./kibana-plugin-public.stringvalidationregex.regex.md) | RegExp | | + diff --git a/docs/development/core/public/kibana-plugin-public.stringvalidationregex.message.md b/docs/development/core/public/kibana-plugin-public.stringvalidationregex.message.md new file mode 100644 index 00000000000000..27e11eedb3599e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.stringvalidationregex.message.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [StringValidationRegex](./kibana-plugin-public.stringvalidationregex.md) > [message](./kibana-plugin-public.stringvalidationregex.message.md) + +## StringValidationRegex.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.stringvalidationregex.regex.md b/docs/development/core/public/kibana-plugin-public.stringvalidationregex.regex.md new file mode 100644 index 00000000000000..fc3a6d96108c46 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.stringvalidationregex.regex.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [StringValidationRegex](./kibana-plugin-public.stringvalidationregex.md) > [regex](./kibana-plugin-public.stringvalidationregex.regex.md) + +## StringValidationRegex.regex property + +Signature: + +```typescript +regex: RegExp; +``` diff --git a/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.md b/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.md new file mode 100644 index 00000000000000..7aa7edf0ac9f06 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [StringValidationRegexString](./kibana-plugin-public.stringvalidationregexstring.md) + +## StringValidationRegexString interface + +StringValidation as regex string + +Signature: + +```typescript +export interface StringValidationRegexString +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [message](./kibana-plugin-public.stringvalidationregexstring.message.md) | string | | +| [regexString](./kibana-plugin-public.stringvalidationregexstring.regexstring.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.message.md b/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.message.md new file mode 100644 index 00000000000000..109dea29084aca --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.message.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [StringValidationRegexString](./kibana-plugin-public.stringvalidationregexstring.md) > [message](./kibana-plugin-public.stringvalidationregexstring.message.md) + +## StringValidationRegexString.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.regexstring.md b/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.regexstring.md new file mode 100644 index 00000000000000..6e7a23e4cc11f0 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.stringvalidationregexstring.regexstring.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [StringValidationRegexString](./kibana-plugin-public.stringvalidationregexstring.md) > [regexString](./kibana-plugin-public.stringvalidationregexstring.regexstring.md) + +## StringValidationRegexString.regexString property + +Signature: + +```typescript +regexString: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.toast.md b/docs/development/core/public/kibana-plugin-public.toast.md index 0cbbf29df073a2..7cbbf4b3c00fac 100644 --- a/docs/development/core/public/kibana-plugin-public.toast.md +++ b/docs/development/core/public/kibana-plugin-public.toast.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Toast](./kibana-plugin-public.toast.md) - -## Toast type - -Signature: - -```typescript -export declare type Toast = ToastInputFields & { - id: string; -}; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Toast](./kibana-plugin-public.toast.md) + +## Toast type + +Signature: + +```typescript +export declare type Toast = ToastInputFields & { + id: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.toastinput.md b/docs/development/core/public/kibana-plugin-public.toastinput.md index 9dd20b5899f3a1..425d7340754695 100644 --- a/docs/development/core/public/kibana-plugin-public.toastinput.md +++ b/docs/development/core/public/kibana-plugin-public.toastinput.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastInput](./kibana-plugin-public.toastinput.md) - -## ToastInput type - -Inputs for [IToasts](./kibana-plugin-public.itoasts.md) APIs. - -Signature: - -```typescript -export declare type ToastInput = string | ToastInputFields; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastInput](./kibana-plugin-public.toastinput.md) + +## ToastInput type + +Inputs for [IToasts](./kibana-plugin-public.itoasts.md) APIs. + +Signature: + +```typescript +export declare type ToastInput = string | ToastInputFields; +``` diff --git a/docs/development/core/public/kibana-plugin-public.toastinputfields.md b/docs/development/core/public/kibana-plugin-public.toastinputfields.md index 3a6bc3a5e45da4..a8b890e3c39732 100644 --- a/docs/development/core/public/kibana-plugin-public.toastinputfields.md +++ b/docs/development/core/public/kibana-plugin-public.toastinputfields.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastInputFields](./kibana-plugin-public.toastinputfields.md) - -## ToastInputFields type - -Allowed fields for [ToastInput](./kibana-plugin-public.toastinput.md). - -Signature: - -```typescript -export declare type ToastInputFields = Pick> & { - title?: string | MountPoint; - text?: string | MountPoint; -}; -``` - -## Remarks - -`id` cannot be specified. - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastInputFields](./kibana-plugin-public.toastinputfields.md) + +## ToastInputFields type + +Allowed fields for [ToastInput](./kibana-plugin-public.toastinput.md). + +Signature: + +```typescript +export declare type ToastInputFields = Pick> & { + title?: string | MountPoint; + text?: string | MountPoint; +}; +``` + +## Remarks + +`id` cannot be specified. + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi._constructor_.md b/docs/development/core/public/kibana-plugin-public.toastsapi._constructor_.md index 2b5ce41de8ecee..66f41a6ed38c6f 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi._constructor_.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi._constructor_.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [(constructor)](./kibana-plugin-public.toastsapi._constructor_.md) - -## ToastsApi.(constructor) - -Constructs a new instance of the `ToastsApi` class - -Signature: - -```typescript -constructor(deps: { - uiSettings: IUiSettingsClient; - }); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| deps | {
uiSettings: IUiSettingsClient;
} | | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [(constructor)](./kibana-plugin-public.toastsapi._constructor_.md) + +## ToastsApi.(constructor) + +Constructs a new instance of the `ToastsApi` class + +Signature: + +```typescript +constructor(deps: { + uiSettings: IUiSettingsClient; + }); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| deps | {
uiSettings: IUiSettingsClient;
} | | + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi.add.md b/docs/development/core/public/kibana-plugin-public.toastsapi.add.md index 6b651b310e9743..3d3213739e30bb 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi.add.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi.add.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [add](./kibana-plugin-public.toastsapi.add.md) - -## ToastsApi.add() method - -Adds a new toast to current array of toast. - -Signature: - -```typescript -add(toastOrTitle: ToastInput): Toast; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| toastOrTitle | ToastInput | a [ToastInput](./kibana-plugin-public.toastinput.md) | - -Returns: - -`Toast` - -a [Toast](./kibana-plugin-public.toast.md) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [add](./kibana-plugin-public.toastsapi.add.md) + +## ToastsApi.add() method + +Adds a new toast to current array of toast. + +Signature: + +```typescript +add(toastOrTitle: ToastInput): Toast; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| toastOrTitle | ToastInput | a [ToastInput](./kibana-plugin-public.toastinput.md) | + +Returns: + +`Toast` + +a [Toast](./kibana-plugin-public.toast.md) + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi.adddanger.md b/docs/development/core/public/kibana-plugin-public.toastsapi.adddanger.md index 67ebad919ed2a0..07bca25cba8c82 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi.adddanger.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi.adddanger.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [addDanger](./kibana-plugin-public.toastsapi.adddanger.md) - -## ToastsApi.addDanger() method - -Adds a new toast pre-configured with the danger color and alert icon. - -Signature: - -```typescript -addDanger(toastOrTitle: ToastInput): Toast; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| toastOrTitle | ToastInput | a [ToastInput](./kibana-plugin-public.toastinput.md) | - -Returns: - -`Toast` - -a [Toast](./kibana-plugin-public.toast.md) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [addDanger](./kibana-plugin-public.toastsapi.adddanger.md) + +## ToastsApi.addDanger() method + +Adds a new toast pre-configured with the danger color and alert icon. + +Signature: + +```typescript +addDanger(toastOrTitle: ToastInput): Toast; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| toastOrTitle | ToastInput | a [ToastInput](./kibana-plugin-public.toastinput.md) | + +Returns: + +`Toast` + +a [Toast](./kibana-plugin-public.toast.md) + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi.adderror.md b/docs/development/core/public/kibana-plugin-public.toastsapi.adderror.md index 39090fb8f1bbef..18455fef9d3437 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi.adderror.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi.adderror.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [addError](./kibana-plugin-public.toastsapi.adderror.md) - -## ToastsApi.addError() method - -Adds a new toast that displays an exception message with a button to open the full stacktrace in a modal. - -Signature: - -```typescript -addError(error: Error, options: ErrorToastOptions): Toast; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | an Error instance. | -| options | ErrorToastOptions | [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) | - -Returns: - -`Toast` - -a [Toast](./kibana-plugin-public.toast.md) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [addError](./kibana-plugin-public.toastsapi.adderror.md) + +## ToastsApi.addError() method + +Adds a new toast that displays an exception message with a button to open the full stacktrace in a modal. + +Signature: + +```typescript +addError(error: Error, options: ErrorToastOptions): Toast; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | an Error instance. | +| options | ErrorToastOptions | [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) | + +Returns: + +`Toast` + +a [Toast](./kibana-plugin-public.toast.md) + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi.addsuccess.md b/docs/development/core/public/kibana-plugin-public.toastsapi.addsuccess.md index ce9a9a2fae6911..b6a9bfb0356025 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi.addsuccess.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi.addsuccess.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [addSuccess](./kibana-plugin-public.toastsapi.addsuccess.md) - -## ToastsApi.addSuccess() method - -Adds a new toast pre-configured with the success color and check icon. - -Signature: - -```typescript -addSuccess(toastOrTitle: ToastInput): Toast; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| toastOrTitle | ToastInput | a [ToastInput](./kibana-plugin-public.toastinput.md) | - -Returns: - -`Toast` - -a [Toast](./kibana-plugin-public.toast.md) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [addSuccess](./kibana-plugin-public.toastsapi.addsuccess.md) + +## ToastsApi.addSuccess() method + +Adds a new toast pre-configured with the success color and check icon. + +Signature: + +```typescript +addSuccess(toastOrTitle: ToastInput): Toast; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| toastOrTitle | ToastInput | a [ToastInput](./kibana-plugin-public.toastinput.md) | + +Returns: + +`Toast` + +a [Toast](./kibana-plugin-public.toast.md) + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi.addwarning.md b/docs/development/core/public/kibana-plugin-public.toastsapi.addwarning.md index 948181f8257632..47de96959c6882 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi.addwarning.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi.addwarning.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [addWarning](./kibana-plugin-public.toastsapi.addwarning.md) - -## ToastsApi.addWarning() method - -Adds a new toast pre-configured with the warning color and help icon. - -Signature: - -```typescript -addWarning(toastOrTitle: ToastInput): Toast; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| toastOrTitle | ToastInput | a [ToastInput](./kibana-plugin-public.toastinput.md) | - -Returns: - -`Toast` - -a [Toast](./kibana-plugin-public.toast.md) - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [addWarning](./kibana-plugin-public.toastsapi.addwarning.md) + +## ToastsApi.addWarning() method + +Adds a new toast pre-configured with the warning color and help icon. + +Signature: + +```typescript +addWarning(toastOrTitle: ToastInput): Toast; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| toastOrTitle | ToastInput | a [ToastInput](./kibana-plugin-public.toastinput.md) | + +Returns: + +`Toast` + +a [Toast](./kibana-plugin-public.toast.md) + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi.get_.md b/docs/development/core/public/kibana-plugin-public.toastsapi.get_.md index 48e4fdc7a2ec00..7ae933f751bd07 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi.get_.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi.get_.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [get$](./kibana-plugin-public.toastsapi.get_.md) - -## ToastsApi.get$() method - -Observable of the toast messages to show to the user. - -Signature: - -```typescript -get$(): Rx.Observable; -``` -Returns: - -`Rx.Observable` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [get$](./kibana-plugin-public.toastsapi.get_.md) + +## ToastsApi.get$() method + +Observable of the toast messages to show to the user. + +Signature: + +```typescript +get$(): Rx.Observable; +``` +Returns: + +`Rx.Observable` + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi.md b/docs/development/core/public/kibana-plugin-public.toastsapi.md index ae4a2de9fc75cb..c69e9b4b8e456d 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi.md @@ -1,32 +1,32 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) - -## ToastsApi class - -Methods for adding and removing global toast messages. - -Signature: - -```typescript -export declare class ToastsApi implements IToasts -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(deps)](./kibana-plugin-public.toastsapi._constructor_.md) | | Constructs a new instance of the ToastsApi class | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [add(toastOrTitle)](./kibana-plugin-public.toastsapi.add.md) | | Adds a new toast to current array of toast. | -| [addDanger(toastOrTitle)](./kibana-plugin-public.toastsapi.adddanger.md) | | Adds a new toast pre-configured with the danger color and alert icon. | -| [addError(error, options)](./kibana-plugin-public.toastsapi.adderror.md) | | Adds a new toast that displays an exception message with a button to open the full stacktrace in a modal. | -| [addSuccess(toastOrTitle)](./kibana-plugin-public.toastsapi.addsuccess.md) | | Adds a new toast pre-configured with the success color and check icon. | -| [addWarning(toastOrTitle)](./kibana-plugin-public.toastsapi.addwarning.md) | | Adds a new toast pre-configured with the warning color and help icon. | -| [get$()](./kibana-plugin-public.toastsapi.get_.md) | | Observable of the toast messages to show to the user. | -| [remove(toastOrId)](./kibana-plugin-public.toastsapi.remove.md) | | Removes a toast from the current array of toasts if present. | - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) + +## ToastsApi class + +Methods for adding and removing global toast messages. + +Signature: + +```typescript +export declare class ToastsApi implements IToasts +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(deps)](./kibana-plugin-public.toastsapi._constructor_.md) | | Constructs a new instance of the ToastsApi class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [add(toastOrTitle)](./kibana-plugin-public.toastsapi.add.md) | | Adds a new toast to current array of toast. | +| [addDanger(toastOrTitle)](./kibana-plugin-public.toastsapi.adddanger.md) | | Adds a new toast pre-configured with the danger color and alert icon. | +| [addError(error, options)](./kibana-plugin-public.toastsapi.adderror.md) | | Adds a new toast that displays an exception message with a button to open the full stacktrace in a modal. | +| [addSuccess(toastOrTitle)](./kibana-plugin-public.toastsapi.addsuccess.md) | | Adds a new toast pre-configured with the success color and check icon. | +| [addWarning(toastOrTitle)](./kibana-plugin-public.toastsapi.addwarning.md) | | Adds a new toast pre-configured with the warning color and help icon. | +| [get$()](./kibana-plugin-public.toastsapi.get_.md) | | Observable of the toast messages to show to the user. | +| [remove(toastOrId)](./kibana-plugin-public.toastsapi.remove.md) | | Removes a toast from the current array of toasts if present. | + diff --git a/docs/development/core/public/kibana-plugin-public.toastsapi.remove.md b/docs/development/core/public/kibana-plugin-public.toastsapi.remove.md index 9f270411752077..6f1323a4b0de01 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsapi.remove.md +++ b/docs/development/core/public/kibana-plugin-public.toastsapi.remove.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [remove](./kibana-plugin-public.toastsapi.remove.md) - -## ToastsApi.remove() method - -Removes a toast from the current array of toasts if present. - -Signature: - -```typescript -remove(toastOrId: Toast | string): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| toastOrId | Toast | string | a [Toast](./kibana-plugin-public.toast.md) returned by [ToastsApi.add()](./kibana-plugin-public.toastsapi.add.md) or its id | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsApi](./kibana-plugin-public.toastsapi.md) > [remove](./kibana-plugin-public.toastsapi.remove.md) + +## ToastsApi.remove() method + +Removes a toast from the current array of toasts if present. + +Signature: + +```typescript +remove(toastOrId: Toast | string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| toastOrId | Toast | string | a [Toast](./kibana-plugin-public.toast.md) returned by [ToastsApi.add()](./kibana-plugin-public.toastsapi.add.md) or its id | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.toastssetup.md b/docs/development/core/public/kibana-plugin-public.toastssetup.md index e06dd7f7093bb8..ab3d7c45f3ce97 100644 --- a/docs/development/core/public/kibana-plugin-public.toastssetup.md +++ b/docs/development/core/public/kibana-plugin-public.toastssetup.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsSetup](./kibana-plugin-public.toastssetup.md) - -## ToastsSetup type - -[IToasts](./kibana-plugin-public.itoasts.md) - -Signature: - -```typescript -export declare type ToastsSetup = IToasts; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsSetup](./kibana-plugin-public.toastssetup.md) + +## ToastsSetup type + +[IToasts](./kibana-plugin-public.itoasts.md) + +Signature: + +```typescript +export declare type ToastsSetup = IToasts; +``` diff --git a/docs/development/core/public/kibana-plugin-public.toastsstart.md b/docs/development/core/public/kibana-plugin-public.toastsstart.md index 6e090dcdc64fb6..3f8f27bd558b3f 100644 --- a/docs/development/core/public/kibana-plugin-public.toastsstart.md +++ b/docs/development/core/public/kibana-plugin-public.toastsstart.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsStart](./kibana-plugin-public.toastsstart.md) - -## ToastsStart type - -[IToasts](./kibana-plugin-public.itoasts.md) - -Signature: - -```typescript -export declare type ToastsStart = IToasts; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ToastsStart](./kibana-plugin-public.toastsstart.md) + +## ToastsStart type + +[IToasts](./kibana-plugin-public.itoasts.md) + +Signature: + +```typescript +export declare type ToastsStart = IToasts; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.category.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.category.md new file mode 100644 index 00000000000000..c94a5ea4d4f9ee --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.category.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [category](./kibana-plugin-public.uisettingsparams.category.md) + +## UiSettingsParams.category property + +used to group the configured setting in the UI + +Signature: + +```typescript +category?: string[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.deprecation.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.deprecation.md new file mode 100644 index 00000000000000..928ba87ce86212 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.deprecation.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [deprecation](./kibana-plugin-public.uisettingsparams.deprecation.md) + +## UiSettingsParams.deprecation property + +optional deprecation information. Used to generate a deprecation warning. + +Signature: + +```typescript +deprecation?: DeprecationSettings; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.description.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.description.md new file mode 100644 index 00000000000000..13c7fb25411d09 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.description.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [description](./kibana-plugin-public.uisettingsparams.description.md) + +## UiSettingsParams.description property + +description provided to a user in UI + +Signature: + +```typescript +description?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.md new file mode 100644 index 00000000000000..6a368a6ae328ce --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) + +## UiSettingsParams interface + +UiSettings parameters defined by the plugins. + +Signature: + +```typescript +export interface UiSettingsParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [category](./kibana-plugin-public.uisettingsparams.category.md) | string[] | used to group the configured setting in the UI | +| [deprecation](./kibana-plugin-public.uisettingsparams.deprecation.md) | DeprecationSettings | optional deprecation information. Used to generate a deprecation warning. | +| [description](./kibana-plugin-public.uisettingsparams.description.md) | string | description provided to a user in UI | +| [name](./kibana-plugin-public.uisettingsparams.name.md) | string | title in the UI | +| [optionLabels](./kibana-plugin-public.uisettingsparams.optionlabels.md) | Record<string, string> | text labels for 'select' type UI element | +| [options](./kibana-plugin-public.uisettingsparams.options.md) | string[] | array of permitted values for this setting | +| [readonly](./kibana-plugin-public.uisettingsparams.readonly.md) | boolean | a flag indicating that value cannot be changed | +| [requiresPageReload](./kibana-plugin-public.uisettingsparams.requirespagereload.md) | boolean | a flag indicating whether new value applying requires page reloading | +| [type](./kibana-plugin-public.uisettingsparams.type.md) | UiSettingsType | defines a type of UI element [UiSettingsType](./kibana-plugin-public.uisettingstype.md) | +| [validation](./kibana-plugin-public.uisettingsparams.validation.md) | ImageValidation | StringValidation | | +| [value](./kibana-plugin-public.uisettingsparams.value.md) | SavedObjectAttribute | default value to fall back to if a user doesn't provide any | + diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.name.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.name.md new file mode 100644 index 00000000000000..91b13e8592129d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [name](./kibana-plugin-public.uisettingsparams.name.md) + +## UiSettingsParams.name property + +title in the UI + +Signature: + +```typescript +name?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.optionlabels.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.optionlabels.md new file mode 100644 index 00000000000000..c2eb182308072c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.optionlabels.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [optionLabels](./kibana-plugin-public.uisettingsparams.optionlabels.md) + +## UiSettingsParams.optionLabels property + +text labels for 'select' type UI element + +Signature: + +```typescript +optionLabels?: Record; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.options.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.options.md new file mode 100644 index 00000000000000..e3958027f42c9d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.options.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [options](./kibana-plugin-public.uisettingsparams.options.md) + +## UiSettingsParams.options property + +array of permitted values for this setting + +Signature: + +```typescript +options?: string[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.readonly.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.readonly.md new file mode 100644 index 00000000000000..6efd2d557b7f08 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.readonly.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [readonly](./kibana-plugin-public.uisettingsparams.readonly.md) + +## UiSettingsParams.readonly property + +a flag indicating that value cannot be changed + +Signature: + +```typescript +readonly?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.requirespagereload.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.requirespagereload.md new file mode 100644 index 00000000000000..0389b56d8e259f --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.requirespagereload.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [requiresPageReload](./kibana-plugin-public.uisettingsparams.requirespagereload.md) + +## UiSettingsParams.requiresPageReload property + +a flag indicating whether new value applying requires page reloading + +Signature: + +```typescript +requiresPageReload?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.type.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.type.md new file mode 100644 index 00000000000000..f3b20c90271a38 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [type](./kibana-plugin-public.uisettingsparams.type.md) + +## UiSettingsParams.type property + +defines a type of UI element [UiSettingsType](./kibana-plugin-public.uisettingstype.md) + +Signature: + +```typescript +type?: UiSettingsType; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.validation.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.validation.md new file mode 100644 index 00000000000000..c2202d07c6245c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.validation.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [validation](./kibana-plugin-public.uisettingsparams.validation.md) + +## UiSettingsParams.validation property + +Signature: + +```typescript +validation?: ImageValidation | StringValidation; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsparams.value.md b/docs/development/core/public/kibana-plugin-public.uisettingsparams.value.md new file mode 100644 index 00000000000000..31850514e03a71 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingsparams.value.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsParams](./kibana-plugin-public.uisettingsparams.md) > [value](./kibana-plugin-public.uisettingsparams.value.md) + +## UiSettingsParams.value property + +default value to fall back to if a user doesn't provide any + +Signature: + +```typescript +value?: SavedObjectAttribute; +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingsstate.md b/docs/development/core/public/kibana-plugin-public.uisettingsstate.md index 4754898f05cb01..f2b147b3e1a275 100644 --- a/docs/development/core/public/kibana-plugin-public.uisettingsstate.md +++ b/docs/development/core/public/kibana-plugin-public.uisettingsstate.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsState](./kibana-plugin-public.uisettingsstate.md) - -## UiSettingsState interface - - -Signature: - -```typescript -export interface UiSettingsState -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsState](./kibana-plugin-public.uisettingsstate.md) + +## UiSettingsState interface + + +Signature: + +```typescript +export interface UiSettingsState +``` diff --git a/docs/development/core/public/kibana-plugin-public.uisettingstype.md b/docs/development/core/public/kibana-plugin-public.uisettingstype.md new file mode 100644 index 00000000000000..d449236fe92d96 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.uisettingstype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UiSettingsType](./kibana-plugin-public.uisettingstype.md) + +## UiSettingsType type + +UI element type to represent the settings. + +Signature: + +```typescript +export declare type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string' | 'array' | 'image'; +``` diff --git a/docs/development/core/public/kibana-plugin-public.unmountcallback.md b/docs/development/core/public/kibana-plugin-public.unmountcallback.md index f44562120c9ee5..b533358741723c 100644 --- a/docs/development/core/public/kibana-plugin-public.unmountcallback.md +++ b/docs/development/core/public/kibana-plugin-public.unmountcallback.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UnmountCallback](./kibana-plugin-public.unmountcallback.md) - -## UnmountCallback type - -A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-public.mountpoint.md) - -Signature: - -```typescript -export declare type UnmountCallback = () => void; -``` + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UnmountCallback](./kibana-plugin-public.unmountcallback.md) + +## UnmountCallback type + +A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-public.mountpoint.md) + +Signature: + +```typescript +export declare type UnmountCallback = () => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.userprovidedvalues.isoverridden.md b/docs/development/core/public/kibana-plugin-public.userprovidedvalues.isoverridden.md new file mode 100644 index 00000000000000..75467967d99248 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.userprovidedvalues.isoverridden.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UserProvidedValues](./kibana-plugin-public.userprovidedvalues.md) > [isOverridden](./kibana-plugin-public.userprovidedvalues.isoverridden.md) + +## UserProvidedValues.isOverridden property + +Signature: + +```typescript +isOverridden?: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-public.userprovidedvalues.md b/docs/development/core/public/kibana-plugin-public.userprovidedvalues.md new file mode 100644 index 00000000000000..1c23c4d7a4b62f --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.userprovidedvalues.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UserProvidedValues](./kibana-plugin-public.userprovidedvalues.md) + +## UserProvidedValues interface + +Describes the values explicitly set by user. + +Signature: + +```typescript +export interface UserProvidedValues +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [isOverridden](./kibana-plugin-public.userprovidedvalues.isoverridden.md) | boolean | | +| [userValue](./kibana-plugin-public.userprovidedvalues.uservalue.md) | T | | + diff --git a/docs/development/core/public/kibana-plugin-public.userprovidedvalues.uservalue.md b/docs/development/core/public/kibana-plugin-public.userprovidedvalues.uservalue.md new file mode 100644 index 00000000000000..1f7121177b07ee --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.userprovidedvalues.uservalue.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UserProvidedValues](./kibana-plugin-public.userprovidedvalues.md) > [userValue](./kibana-plugin-public.userprovidedvalues.uservalue.md) + +## UserProvidedValues.userValue property + +Signature: + +```typescript +userValue?: T; +``` diff --git a/docs/development/core/server/index.md b/docs/development/core/server/index.md index da1d76853f43d3..2d8eb26a689c6e 100644 --- a/docs/development/core/server/index.md +++ b/docs/development/core/server/index.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) - -## API Reference - -## Packages - -| Package | Description | -| --- | --- | -| [kibana-plugin-server](./kibana-plugin-server.md) | The Kibana Core APIs for server-side plugins.A plugin requires a kibana.json file at it's root directory that follows to define static plugin information required to load the plugin.A plugin's server/index file must contain a named import, plugin, that implements which returns an object that implements .The plugin integrates with the core system via lifecycle events: setup, start, and stop. In each lifecycle method, the plugin will receive the corresponding core services available (either or ) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. | - + + +[Home](./index.md) + +## API Reference + +## Packages + +| Package | Description | +| --- | --- | +| [kibana-plugin-server](./kibana-plugin-server.md) | The Kibana Core APIs for server-side plugins.A plugin requires a kibana.json file at it's root directory that follows to define static plugin information required to load the plugin.A plugin's server/index file must contain a named import, plugin, that implements which returns an object that implements .The plugin integrates with the core system via lifecycle events: setup, start, and stop. In each lifecycle method, the plugin will receive the corresponding core services available (either or ) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. | + diff --git a/docs/development/core/server/kibana-plugin-server.apicaller.md b/docs/development/core/server/kibana-plugin-server.apicaller.md index 9fd50ea5c4b669..4e22a702ecbbef 100644 --- a/docs/development/core/server/kibana-plugin-server.apicaller.md +++ b/docs/development/core/server/kibana-plugin-server.apicaller.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [APICaller](./kibana-plugin-server.apicaller.md) - -## APICaller interface - - -Signature: - -```typescript -export interface APICaller -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [APICaller](./kibana-plugin-server.apicaller.md) + +## APICaller interface + + +Signature: + +```typescript +export interface APICaller +``` diff --git a/docs/development/core/server/kibana-plugin-server.assistanceapiresponse.indices.md b/docs/development/core/server/kibana-plugin-server.assistanceapiresponse.indices.md index 307cd3bb5ae215..6777ab6caeca28 100644 --- a/docs/development/core/server/kibana-plugin-server.assistanceapiresponse.indices.md +++ b/docs/development/core/server/kibana-plugin-server.assistanceapiresponse.indices.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistanceAPIResponse](./kibana-plugin-server.assistanceapiresponse.md) > [indices](./kibana-plugin-server.assistanceapiresponse.indices.md) - -## AssistanceAPIResponse.indices property - -Signature: - -```typescript -indices: { - [indexName: string]: { - action_required: MIGRATION_ASSISTANCE_INDEX_ACTION; - }; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistanceAPIResponse](./kibana-plugin-server.assistanceapiresponse.md) > [indices](./kibana-plugin-server.assistanceapiresponse.indices.md) + +## AssistanceAPIResponse.indices property + +Signature: + +```typescript +indices: { + [indexName: string]: { + action_required: MIGRATION_ASSISTANCE_INDEX_ACTION; + }; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.assistanceapiresponse.md b/docs/development/core/server/kibana-plugin-server.assistanceapiresponse.md index 398fe62ce2479a..9322b4c75837c2 100644 --- a/docs/development/core/server/kibana-plugin-server.assistanceapiresponse.md +++ b/docs/development/core/server/kibana-plugin-server.assistanceapiresponse.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistanceAPIResponse](./kibana-plugin-server.assistanceapiresponse.md) - -## AssistanceAPIResponse interface - - -Signature: - -```typescript -export interface AssistanceAPIResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [indices](./kibana-plugin-server.assistanceapiresponse.indices.md) | {
[indexName: string]: {
action_required: MIGRATION_ASSISTANCE_INDEX_ACTION;
};
} | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistanceAPIResponse](./kibana-plugin-server.assistanceapiresponse.md) + +## AssistanceAPIResponse interface + + +Signature: + +```typescript +export interface AssistanceAPIResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [indices](./kibana-plugin-server.assistanceapiresponse.indices.md) | {
[indexName: string]: {
action_required: MIGRATION_ASSISTANCE_INDEX_ACTION;
};
} | | + diff --git a/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.md b/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.md index cf7ca56c8a75e2..c37d47f0c4963c 100644 --- a/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.md +++ b/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistantAPIClientParams](./kibana-plugin-server.assistantapiclientparams.md) - -## AssistantAPIClientParams interface - - -Signature: - -```typescript -export interface AssistantAPIClientParams extends GenericParams -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [method](./kibana-plugin-server.assistantapiclientparams.method.md) | 'GET' | | -| [path](./kibana-plugin-server.assistantapiclientparams.path.md) | '/_migration/assistance' | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistantAPIClientParams](./kibana-plugin-server.assistantapiclientparams.md) + +## AssistantAPIClientParams interface + + +Signature: + +```typescript +export interface AssistantAPIClientParams extends GenericParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [method](./kibana-plugin-server.assistantapiclientparams.method.md) | 'GET' | | +| [path](./kibana-plugin-server.assistantapiclientparams.path.md) | '/_migration/assistance' | | + diff --git a/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.method.md b/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.method.md index feeb4403ca0a36..6929bf9ab3d1cc 100644 --- a/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.method.md +++ b/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.method.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistantAPIClientParams](./kibana-plugin-server.assistantapiclientparams.md) > [method](./kibana-plugin-server.assistantapiclientparams.method.md) - -## AssistantAPIClientParams.method property - -Signature: - -```typescript -method: 'GET'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistantAPIClientParams](./kibana-plugin-server.assistantapiclientparams.md) > [method](./kibana-plugin-server.assistantapiclientparams.method.md) + +## AssistantAPIClientParams.method property + +Signature: + +```typescript +method: 'GET'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.path.md b/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.path.md index 3b82c477993e0b..4889f41d613ebb 100644 --- a/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.path.md +++ b/docs/development/core/server/kibana-plugin-server.assistantapiclientparams.path.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistantAPIClientParams](./kibana-plugin-server.assistantapiclientparams.md) > [path](./kibana-plugin-server.assistantapiclientparams.path.md) - -## AssistantAPIClientParams.path property - -Signature: - -```typescript -path: '/_migration/assistance'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AssistantAPIClientParams](./kibana-plugin-server.assistantapiclientparams.md) > [path](./kibana-plugin-server.assistantapiclientparams.path.md) + +## AssistantAPIClientParams.path property + +Signature: + +```typescript +path: '/_migration/assistance'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authenticated.md b/docs/development/core/server/kibana-plugin-server.authenticated.md index d955f1f32f1f7a..aeb526bc3552bd 100644 --- a/docs/development/core/server/kibana-plugin-server.authenticated.md +++ b/docs/development/core/server/kibana-plugin-server.authenticated.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Authenticated](./kibana-plugin-server.authenticated.md) - -## Authenticated interface - - -Signature: - -```typescript -export interface Authenticated extends AuthResultParams -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [type](./kibana-plugin-server.authenticated.type.md) | AuthResultType.authenticated | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Authenticated](./kibana-plugin-server.authenticated.md) + +## Authenticated interface + + +Signature: + +```typescript +export interface Authenticated extends AuthResultParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [type](./kibana-plugin-server.authenticated.type.md) | AuthResultType.authenticated | | + diff --git a/docs/development/core/server/kibana-plugin-server.authenticated.type.md b/docs/development/core/server/kibana-plugin-server.authenticated.type.md index 08a73e812d1575..a432fad9d57306 100644 --- a/docs/development/core/server/kibana-plugin-server.authenticated.type.md +++ b/docs/development/core/server/kibana-plugin-server.authenticated.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Authenticated](./kibana-plugin-server.authenticated.md) > [type](./kibana-plugin-server.authenticated.type.md) - -## Authenticated.type property - -Signature: - -```typescript -type: AuthResultType.authenticated; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Authenticated](./kibana-plugin-server.authenticated.md) > [type](./kibana-plugin-server.authenticated.type.md) + +## Authenticated.type property + +Signature: + +```typescript +type: AuthResultType.authenticated; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authenticationhandler.md b/docs/development/core/server/kibana-plugin-server.authenticationhandler.md index ff60e6e811ed62..ed5eb6bc5e36dd 100644 --- a/docs/development/core/server/kibana-plugin-server.authenticationhandler.md +++ b/docs/development/core/server/kibana-plugin-server.authenticationhandler.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthenticationHandler](./kibana-plugin-server.authenticationhandler.md) - -## AuthenticationHandler type - -See [AuthToolkit](./kibana-plugin-server.authtoolkit.md). - -Signature: - -```typescript -export declare type AuthenticationHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: AuthToolkit) => AuthResult | IKibanaResponse | Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthenticationHandler](./kibana-plugin-server.authenticationhandler.md) + +## AuthenticationHandler type + +See [AuthToolkit](./kibana-plugin-server.authtoolkit.md). + +Signature: + +```typescript +export declare type AuthenticationHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: AuthToolkit) => AuthResult | IKibanaResponse | Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authheaders.md b/docs/development/core/server/kibana-plugin-server.authheaders.md index bdb7cda2fa304b..7540157926edcb 100644 --- a/docs/development/core/server/kibana-plugin-server.authheaders.md +++ b/docs/development/core/server/kibana-plugin-server.authheaders.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthHeaders](./kibana-plugin-server.authheaders.md) - -## AuthHeaders type - -Auth Headers map - -Signature: - -```typescript -export declare type AuthHeaders = Record; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthHeaders](./kibana-plugin-server.authheaders.md) + +## AuthHeaders type + +Auth Headers map + +Signature: + +```typescript +export declare type AuthHeaders = Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authresult.md b/docs/development/core/server/kibana-plugin-server.authresult.md index 5d1bdbc8e71183..8739c4899bd02a 100644 --- a/docs/development/core/server/kibana-plugin-server.authresult.md +++ b/docs/development/core/server/kibana-plugin-server.authresult.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResult](./kibana-plugin-server.authresult.md) - -## AuthResult type - - -Signature: - -```typescript -export declare type AuthResult = Authenticated; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResult](./kibana-plugin-server.authresult.md) + +## AuthResult type + + +Signature: + +```typescript +export declare type AuthResult = Authenticated; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authresultparams.md b/docs/development/core/server/kibana-plugin-server.authresultparams.md index b098fe278d850f..55b247f21f5a9e 100644 --- a/docs/development/core/server/kibana-plugin-server.authresultparams.md +++ b/docs/development/core/server/kibana-plugin-server.authresultparams.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultParams](./kibana-plugin-server.authresultparams.md) - -## AuthResultParams interface - -Result of an incoming request authentication. - -Signature: - -```typescript -export interface AuthResultParams -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [requestHeaders](./kibana-plugin-server.authresultparams.requestheaders.md) | AuthHeaders | Auth specific headers to attach to a request object. Used to perform a request to Elasticsearch on behalf of an authenticated user. | -| [responseHeaders](./kibana-plugin-server.authresultparams.responseheaders.md) | AuthHeaders | Auth specific headers to attach to a response object. Used to send back authentication mechanism related headers to a client when needed. | -| [state](./kibana-plugin-server.authresultparams.state.md) | Record<string, any> | Data to associate with an incoming request. Any downstream plugin may get access to the data. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultParams](./kibana-plugin-server.authresultparams.md) + +## AuthResultParams interface + +Result of an incoming request authentication. + +Signature: + +```typescript +export interface AuthResultParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [requestHeaders](./kibana-plugin-server.authresultparams.requestheaders.md) | AuthHeaders | Auth specific headers to attach to a request object. Used to perform a request to Elasticsearch on behalf of an authenticated user. | +| [responseHeaders](./kibana-plugin-server.authresultparams.responseheaders.md) | AuthHeaders | Auth specific headers to attach to a response object. Used to send back authentication mechanism related headers to a client when needed. | +| [state](./kibana-plugin-server.authresultparams.state.md) | Record<string, any> | Data to associate with an incoming request. Any downstream plugin may get access to the data. | + diff --git a/docs/development/core/server/kibana-plugin-server.authresultparams.requestheaders.md b/docs/development/core/server/kibana-plugin-server.authresultparams.requestheaders.md index 0fda032b64f987..a30f630de27cca 100644 --- a/docs/development/core/server/kibana-plugin-server.authresultparams.requestheaders.md +++ b/docs/development/core/server/kibana-plugin-server.authresultparams.requestheaders.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultParams](./kibana-plugin-server.authresultparams.md) > [requestHeaders](./kibana-plugin-server.authresultparams.requestheaders.md) - -## AuthResultParams.requestHeaders property - -Auth specific headers to attach to a request object. Used to perform a request to Elasticsearch on behalf of an authenticated user. - -Signature: - -```typescript -requestHeaders?: AuthHeaders; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultParams](./kibana-plugin-server.authresultparams.md) > [requestHeaders](./kibana-plugin-server.authresultparams.requestheaders.md) + +## AuthResultParams.requestHeaders property + +Auth specific headers to attach to a request object. Used to perform a request to Elasticsearch on behalf of an authenticated user. + +Signature: + +```typescript +requestHeaders?: AuthHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authresultparams.responseheaders.md b/docs/development/core/server/kibana-plugin-server.authresultparams.responseheaders.md index c14feb25801d1e..112c1277bbbed8 100644 --- a/docs/development/core/server/kibana-plugin-server.authresultparams.responseheaders.md +++ b/docs/development/core/server/kibana-plugin-server.authresultparams.responseheaders.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultParams](./kibana-plugin-server.authresultparams.md) > [responseHeaders](./kibana-plugin-server.authresultparams.responseheaders.md) - -## AuthResultParams.responseHeaders property - -Auth specific headers to attach to a response object. Used to send back authentication mechanism related headers to a client when needed. - -Signature: - -```typescript -responseHeaders?: AuthHeaders; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultParams](./kibana-plugin-server.authresultparams.md) > [responseHeaders](./kibana-plugin-server.authresultparams.responseheaders.md) + +## AuthResultParams.responseHeaders property + +Auth specific headers to attach to a response object. Used to send back authentication mechanism related headers to a client when needed. + +Signature: + +```typescript +responseHeaders?: AuthHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authresultparams.state.md b/docs/development/core/server/kibana-plugin-server.authresultparams.state.md index 8ca3da20a9c224..085cbe0c3c3fae 100644 --- a/docs/development/core/server/kibana-plugin-server.authresultparams.state.md +++ b/docs/development/core/server/kibana-plugin-server.authresultparams.state.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultParams](./kibana-plugin-server.authresultparams.md) > [state](./kibana-plugin-server.authresultparams.state.md) - -## AuthResultParams.state property - -Data to associate with an incoming request. Any downstream plugin may get access to the data. - -Signature: - -```typescript -state?: Record; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultParams](./kibana-plugin-server.authresultparams.md) > [state](./kibana-plugin-server.authresultparams.state.md) + +## AuthResultParams.state property + +Data to associate with an incoming request. Any downstream plugin may get access to the data. + +Signature: + +```typescript +state?: Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authresulttype.md b/docs/development/core/server/kibana-plugin-server.authresulttype.md index e8962cb14d198e..61a98ee5e7b110 100644 --- a/docs/development/core/server/kibana-plugin-server.authresulttype.md +++ b/docs/development/core/server/kibana-plugin-server.authresulttype.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultType](./kibana-plugin-server.authresulttype.md) - -## AuthResultType enum - - -Signature: - -```typescript -export declare enum AuthResultType -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| authenticated | "authenticated" | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthResultType](./kibana-plugin-server.authresulttype.md) + +## AuthResultType enum + + +Signature: + +```typescript +export declare enum AuthResultType +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| authenticated | "authenticated" | | + diff --git a/docs/development/core/server/kibana-plugin-server.authstatus.md b/docs/development/core/server/kibana-plugin-server.authstatus.md index e59ade4f73e38b..eb350c794d6d6c 100644 --- a/docs/development/core/server/kibana-plugin-server.authstatus.md +++ b/docs/development/core/server/kibana-plugin-server.authstatus.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthStatus](./kibana-plugin-server.authstatus.md) - -## AuthStatus enum - -Status indicating an outcome of the authentication. - -Signature: - -```typescript -export declare enum AuthStatus -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| authenticated | "authenticated" | auth interceptor successfully authenticated a user | -| unauthenticated | "unauthenticated" | auth interceptor failed user authentication | -| unknown | "unknown" | auth interceptor has not been registered | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthStatus](./kibana-plugin-server.authstatus.md) + +## AuthStatus enum + +Status indicating an outcome of the authentication. + +Signature: + +```typescript +export declare enum AuthStatus +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| authenticated | "authenticated" | auth interceptor successfully authenticated a user | +| unauthenticated | "unauthenticated" | auth interceptor failed user authentication | +| unknown | "unknown" | auth interceptor has not been registered | + diff --git a/docs/development/core/server/kibana-plugin-server.authtoolkit.authenticated.md b/docs/development/core/server/kibana-plugin-server.authtoolkit.authenticated.md index 54d78c840ed5ab..47ba021602b22a 100644 --- a/docs/development/core/server/kibana-plugin-server.authtoolkit.authenticated.md +++ b/docs/development/core/server/kibana-plugin-server.authtoolkit.authenticated.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthToolkit](./kibana-plugin-server.authtoolkit.md) > [authenticated](./kibana-plugin-server.authtoolkit.authenticated.md) - -## AuthToolkit.authenticated property - -Authentication is successful with given credentials, allow request to pass through - -Signature: - -```typescript -authenticated: (data?: AuthResultParams) => AuthResult; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthToolkit](./kibana-plugin-server.authtoolkit.md) > [authenticated](./kibana-plugin-server.authtoolkit.authenticated.md) + +## AuthToolkit.authenticated property + +Authentication is successful with given credentials, allow request to pass through + +Signature: + +```typescript +authenticated: (data?: AuthResultParams) => AuthResult; +``` diff --git a/docs/development/core/server/kibana-plugin-server.authtoolkit.md b/docs/development/core/server/kibana-plugin-server.authtoolkit.md index 0c030ddce4ec33..bc7003c5a68f30 100644 --- a/docs/development/core/server/kibana-plugin-server.authtoolkit.md +++ b/docs/development/core/server/kibana-plugin-server.authtoolkit.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthToolkit](./kibana-plugin-server.authtoolkit.md) - -## AuthToolkit interface - -A tool set defining an outcome of Auth interceptor for incoming request. - -Signature: - -```typescript -export interface AuthToolkit -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [authenticated](./kibana-plugin-server.authtoolkit.authenticated.md) | (data?: AuthResultParams) => AuthResult | Authentication is successful with given credentials, allow request to pass through | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [AuthToolkit](./kibana-plugin-server.authtoolkit.md) + +## AuthToolkit interface + +A tool set defining an outcome of Auth interceptor for incoming request. + +Signature: + +```typescript +export interface AuthToolkit +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [authenticated](./kibana-plugin-server.authtoolkit.authenticated.md) | (data?: AuthResultParams) => AuthResult | Authentication is successful with given credentials, allow request to pass through | + diff --git a/docs/development/core/server/kibana-plugin-server.basepath.get.md b/docs/development/core/server/kibana-plugin-server.basepath.get.md index a20bc1a4e3174c..4dbbb1e5bd7a38 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.get.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.get.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [get](./kibana-plugin-server.basepath.get.md) - -## BasePath.get property - -returns `basePath` value, specific for an incoming request. - -Signature: - -```typescript -get: (request: LegacyRequest | KibanaRequest) => string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [get](./kibana-plugin-server.basepath.get.md) + +## BasePath.get property + +returns `basePath` value, specific for an incoming request. + +Signature: + +```typescript +get: (request: LegacyRequest | KibanaRequest) => string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.basepath.md b/docs/development/core/server/kibana-plugin-server.basepath.md index 63aeb7f711d978..d7ee8e5d12e65e 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) - -## BasePath class - -Access or manipulate the Kibana base path - -Signature: - -```typescript -export declare class BasePath -``` - -## Remarks - -The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `BasePath` class. - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [get](./kibana-plugin-server.basepath.get.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown, any>) => string | returns basePath value, specific for an incoming request. | -| [prepend](./kibana-plugin-server.basepath.prepend.md) | | (path: string) => string | Prepends path with the basePath. | -| [remove](./kibana-plugin-server.basepath.remove.md) | | (path: string) => string | Removes the prepended basePath from the path. | -| [serverBasePath](./kibana-plugin-server.basepath.serverbasepath.md) | | string | returns the server's basePathSee [BasePath.get](./kibana-plugin-server.basepath.get.md) for getting the basePath value for a specific request | -| [set](./kibana-plugin-server.basepath.set.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown, any>, requestSpecificBasePath: string) => void | sets basePath value, specific for an incoming request. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) + +## BasePath class + +Access or manipulate the Kibana base path + +Signature: + +```typescript +export declare class BasePath +``` + +## Remarks + +The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `BasePath` class. + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [get](./kibana-plugin-server.basepath.get.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown, any>) => string | returns basePath value, specific for an incoming request. | +| [prepend](./kibana-plugin-server.basepath.prepend.md) | | (path: string) => string | Prepends path with the basePath. | +| [remove](./kibana-plugin-server.basepath.remove.md) | | (path: string) => string | Removes the prepended basePath from the path. | +| [serverBasePath](./kibana-plugin-server.basepath.serverbasepath.md) | | string | returns the server's basePathSee [BasePath.get](./kibana-plugin-server.basepath.get.md) for getting the basePath value for a specific request | +| [set](./kibana-plugin-server.basepath.set.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown, any>, requestSpecificBasePath: string) => void | sets basePath value, specific for an incoming request. | + diff --git a/docs/development/core/server/kibana-plugin-server.basepath.prepend.md b/docs/development/core/server/kibana-plugin-server.basepath.prepend.md index 9a615dfe80f329..17f3b8bf80e61a 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.prepend.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.prepend.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [prepend](./kibana-plugin-server.basepath.prepend.md) - -## BasePath.prepend property - -Prepends `path` with the basePath. - -Signature: - -```typescript -prepend: (path: string) => string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [prepend](./kibana-plugin-server.basepath.prepend.md) + +## BasePath.prepend property + +Prepends `path` with the basePath. + +Signature: + +```typescript +prepend: (path: string) => string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.basepath.remove.md b/docs/development/core/server/kibana-plugin-server.basepath.remove.md index 8fcfbc2b921d3a..25844682623e34 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.remove.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.remove.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [remove](./kibana-plugin-server.basepath.remove.md) - -## BasePath.remove property - -Removes the prepended basePath from the `path`. - -Signature: - -```typescript -remove: (path: string) => string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [remove](./kibana-plugin-server.basepath.remove.md) + +## BasePath.remove property + +Removes the prepended basePath from the `path`. + +Signature: + +```typescript +remove: (path: string) => string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.basepath.serverbasepath.md b/docs/development/core/server/kibana-plugin-server.basepath.serverbasepath.md index d7e45a92dba6d7..35a3b67de7a73c 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.serverbasepath.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.serverbasepath.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [serverBasePath](./kibana-plugin-server.basepath.serverbasepath.md) - -## BasePath.serverBasePath property - -returns the server's basePath - -See [BasePath.get](./kibana-plugin-server.basepath.get.md) for getting the basePath value for a specific request - -Signature: - -```typescript -readonly serverBasePath: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [serverBasePath](./kibana-plugin-server.basepath.serverbasepath.md) + +## BasePath.serverBasePath property + +returns the server's basePath + +See [BasePath.get](./kibana-plugin-server.basepath.get.md) for getting the basePath value for a specific request + +Signature: + +```typescript +readonly serverBasePath: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.basepath.set.md b/docs/development/core/server/kibana-plugin-server.basepath.set.md index ac08baa0bb99e9..479a96aa0347c4 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.set.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.set.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [set](./kibana-plugin-server.basepath.set.md) - -## BasePath.set property - -sets `basePath` value, specific for an incoming request. - -Signature: - -```typescript -set: (request: LegacyRequest | KibanaRequest, requestSpecificBasePath: string) => void; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [set](./kibana-plugin-server.basepath.set.md) + +## BasePath.set property + +sets `basePath` value, specific for an incoming request. + +Signature: + +```typescript +set: (request: LegacyRequest | KibanaRequest, requestSpecificBasePath: string) => void; +``` diff --git a/docs/development/core/server/kibana-plugin-server.callapioptions.md b/docs/development/core/server/kibana-plugin-server.callapioptions.md index ffdf638b236bb3..4a73e5631a71cf 100644 --- a/docs/development/core/server/kibana-plugin-server.callapioptions.md +++ b/docs/development/core/server/kibana-plugin-server.callapioptions.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CallAPIOptions](./kibana-plugin-server.callapioptions.md) - -## CallAPIOptions interface - -The set of options that defines how API call should be made and result be processed. - -Signature: - -```typescript -export interface CallAPIOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [signal](./kibana-plugin-server.callapioptions.signal.md) | AbortSignal | A signal object that allows you to abort the request via an AbortController object. | -| [wrap401Errors](./kibana-plugin-server.callapioptions.wrap401errors.md) | boolean | Indicates whether 401 Unauthorized errors returned from the Elasticsearch API should be wrapped into Boom error instances with properly set WWW-Authenticate header that could have been returned by the API itself. If API didn't specify that then Basic realm="Authorization Required" is used as WWW-Authenticate. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CallAPIOptions](./kibana-plugin-server.callapioptions.md) + +## CallAPIOptions interface + +The set of options that defines how API call should be made and result be processed. + +Signature: + +```typescript +export interface CallAPIOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [signal](./kibana-plugin-server.callapioptions.signal.md) | AbortSignal | A signal object that allows you to abort the request via an AbortController object. | +| [wrap401Errors](./kibana-plugin-server.callapioptions.wrap401errors.md) | boolean | Indicates whether 401 Unauthorized errors returned from the Elasticsearch API should be wrapped into Boom error instances with properly set WWW-Authenticate header that could have been returned by the API itself. If API didn't specify that then Basic realm="Authorization Required" is used as WWW-Authenticate. | + diff --git a/docs/development/core/server/kibana-plugin-server.callapioptions.signal.md b/docs/development/core/server/kibana-plugin-server.callapioptions.signal.md index 402ed0ca8e34c8..a442da87e590fd 100644 --- a/docs/development/core/server/kibana-plugin-server.callapioptions.signal.md +++ b/docs/development/core/server/kibana-plugin-server.callapioptions.signal.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CallAPIOptions](./kibana-plugin-server.callapioptions.md) > [signal](./kibana-plugin-server.callapioptions.signal.md) - -## CallAPIOptions.signal property - -A signal object that allows you to abort the request via an AbortController object. - -Signature: - -```typescript -signal?: AbortSignal; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CallAPIOptions](./kibana-plugin-server.callapioptions.md) > [signal](./kibana-plugin-server.callapioptions.signal.md) + +## CallAPIOptions.signal property + +A signal object that allows you to abort the request via an AbortController object. + +Signature: + +```typescript +signal?: AbortSignal; +``` diff --git a/docs/development/core/server/kibana-plugin-server.callapioptions.wrap401errors.md b/docs/development/core/server/kibana-plugin-server.callapioptions.wrap401errors.md index 296d7695339508..6544fa482c57fb 100644 --- a/docs/development/core/server/kibana-plugin-server.callapioptions.wrap401errors.md +++ b/docs/development/core/server/kibana-plugin-server.callapioptions.wrap401errors.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CallAPIOptions](./kibana-plugin-server.callapioptions.md) > [wrap401Errors](./kibana-plugin-server.callapioptions.wrap401errors.md) - -## CallAPIOptions.wrap401Errors property - -Indicates whether `401 Unauthorized` errors returned from the Elasticsearch API should be wrapped into `Boom` error instances with properly set `WWW-Authenticate` header that could have been returned by the API itself. If API didn't specify that then `Basic realm="Authorization Required"` is used as `WWW-Authenticate`. - -Signature: - -```typescript -wrap401Errors?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CallAPIOptions](./kibana-plugin-server.callapioptions.md) > [wrap401Errors](./kibana-plugin-server.callapioptions.wrap401errors.md) + +## CallAPIOptions.wrap401Errors property + +Indicates whether `401 Unauthorized` errors returned from the Elasticsearch API should be wrapped into `Boom` error instances with properly set `WWW-Authenticate` header that could have been returned by the API itself. If API didn't specify that then `Basic realm="Authorization Required"` is used as `WWW-Authenticate`. + +Signature: + +```typescript +wrap401Errors?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.capabilities.catalogue.md b/docs/development/core/server/kibana-plugin-server.capabilities.catalogue.md index 4eb012c78f0cbc..92224b47c136c7 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilities.catalogue.md +++ b/docs/development/core/server/kibana-plugin-server.capabilities.catalogue.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Capabilities](./kibana-plugin-server.capabilities.md) > [catalogue](./kibana-plugin-server.capabilities.catalogue.md) - -## Capabilities.catalogue property - -Catalogue capabilities. Catalogue entries drive the visibility of the Kibana homepage options. - -Signature: - -```typescript -catalogue: Record; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Capabilities](./kibana-plugin-server.capabilities.md) > [catalogue](./kibana-plugin-server.capabilities.catalogue.md) + +## Capabilities.catalogue property + +Catalogue capabilities. Catalogue entries drive the visibility of the Kibana homepage options. + +Signature: + +```typescript +catalogue: Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.capabilities.management.md b/docs/development/core/server/kibana-plugin-server.capabilities.management.md index d917c81dc37206..d995324a6d7326 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilities.management.md +++ b/docs/development/core/server/kibana-plugin-server.capabilities.management.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Capabilities](./kibana-plugin-server.capabilities.md) > [management](./kibana-plugin-server.capabilities.management.md) - -## Capabilities.management property - -Management section capabilities. - -Signature: - -```typescript -management: { - [sectionId: string]: Record; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Capabilities](./kibana-plugin-server.capabilities.md) > [management](./kibana-plugin-server.capabilities.management.md) + +## Capabilities.management property + +Management section capabilities. + +Signature: + +```typescript +management: { + [sectionId: string]: Record; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.capabilities.md b/docs/development/core/server/kibana-plugin-server.capabilities.md index 031282b9733acc..586b3cac05b199 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilities.md +++ b/docs/development/core/server/kibana-plugin-server.capabilities.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Capabilities](./kibana-plugin-server.capabilities.md) - -## Capabilities interface - -The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. - -Signature: - -```typescript -export interface Capabilities -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [catalogue](./kibana-plugin-server.capabilities.catalogue.md) | Record<string, boolean> | Catalogue capabilities. Catalogue entries drive the visibility of the Kibana homepage options. | -| [management](./kibana-plugin-server.capabilities.management.md) | {
[sectionId: string]: Record<string, boolean>;
} | Management section capabilities. | -| [navLinks](./kibana-plugin-server.capabilities.navlinks.md) | Record<string, boolean> | Navigation link capabilities. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Capabilities](./kibana-plugin-server.capabilities.md) + +## Capabilities interface + +The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. + +Signature: + +```typescript +export interface Capabilities +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [catalogue](./kibana-plugin-server.capabilities.catalogue.md) | Record<string, boolean> | Catalogue capabilities. Catalogue entries drive the visibility of the Kibana homepage options. | +| [management](./kibana-plugin-server.capabilities.management.md) | {
[sectionId: string]: Record<string, boolean>;
} | Management section capabilities. | +| [navLinks](./kibana-plugin-server.capabilities.navlinks.md) | Record<string, boolean> | Navigation link capabilities. | + diff --git a/docs/development/core/server/kibana-plugin-server.capabilities.navlinks.md b/docs/development/core/server/kibana-plugin-server.capabilities.navlinks.md index a1612ea840fbf7..85287852efc6be 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilities.navlinks.md +++ b/docs/development/core/server/kibana-plugin-server.capabilities.navlinks.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Capabilities](./kibana-plugin-server.capabilities.md) > [navLinks](./kibana-plugin-server.capabilities.navlinks.md) - -## Capabilities.navLinks property - -Navigation link capabilities. - -Signature: - -```typescript -navLinks: Record; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Capabilities](./kibana-plugin-server.capabilities.md) > [navLinks](./kibana-plugin-server.capabilities.navlinks.md) + +## Capabilities.navLinks property + +Navigation link capabilities. + +Signature: + +```typescript +navLinks: Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.capabilitiesprovider.md b/docs/development/core/server/kibana-plugin-server.capabilitiesprovider.md index 66e5d256ada66b..a03cbab7e621de 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilitiesprovider.md +++ b/docs/development/core/server/kibana-plugin-server.capabilitiesprovider.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesProvider](./kibana-plugin-server.capabilitiesprovider.md) - -## CapabilitiesProvider type - -See [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) - -Signature: - -```typescript -export declare type CapabilitiesProvider = () => Partial; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesProvider](./kibana-plugin-server.capabilitiesprovider.md) + +## CapabilitiesProvider type + +See [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) + +Signature: + +```typescript +export declare type CapabilitiesProvider = () => Partial; +``` diff --git a/docs/development/core/server/kibana-plugin-server.capabilitiessetup.md b/docs/development/core/server/kibana-plugin-server.capabilitiessetup.md index 27c42fe75e7517..53153b2bbb8871 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilitiessetup.md +++ b/docs/development/core/server/kibana-plugin-server.capabilitiessetup.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) - -## CapabilitiesSetup interface - -APIs to manage the [Capabilities](./kibana-plugin-server.capabilities.md) that will be used by the application. - -Plugins relying on capabilities to toggle some of their features should register them during the setup phase using the `registerProvider` method. - -Plugins having the responsibility to restrict capabilities depending on a given context should register their capabilities switcher using the `registerSwitcher` method. - -Refers to the methods documentation for complete description and examples. - -Signature: - -```typescript -export interface CapabilitiesSetup -``` - -## Methods - -| Method | Description | -| --- | --- | -| [registerProvider(provider)](./kibana-plugin-server.capabilitiessetup.registerprovider.md) | Register a [CapabilitiesProvider](./kibana-plugin-server.capabilitiesprovider.md) to be used to provide [Capabilities](./kibana-plugin-server.capabilities.md) when resolving them. | -| [registerSwitcher(switcher)](./kibana-plugin-server.capabilitiessetup.registerswitcher.md) | Register a [CapabilitiesSwitcher](./kibana-plugin-server.capabilitiesswitcher.md) to be used to change the default state of the [Capabilities](./kibana-plugin-server.capabilities.md) entries when resolving them.A capabilities switcher can only change the state of existing capabilities. Capabilities added or removed when invoking the switcher will be ignored. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) + +## CapabilitiesSetup interface + +APIs to manage the [Capabilities](./kibana-plugin-server.capabilities.md) that will be used by the application. + +Plugins relying on capabilities to toggle some of their features should register them during the setup phase using the `registerProvider` method. + +Plugins having the responsibility to restrict capabilities depending on a given context should register their capabilities switcher using the `registerSwitcher` method. + +Refers to the methods documentation for complete description and examples. + +Signature: + +```typescript +export interface CapabilitiesSetup +``` + +## Methods + +| Method | Description | +| --- | --- | +| [registerProvider(provider)](./kibana-plugin-server.capabilitiessetup.registerprovider.md) | Register a [CapabilitiesProvider](./kibana-plugin-server.capabilitiesprovider.md) to be used to provide [Capabilities](./kibana-plugin-server.capabilities.md) when resolving them. | +| [registerSwitcher(switcher)](./kibana-plugin-server.capabilitiessetup.registerswitcher.md) | Register a [CapabilitiesSwitcher](./kibana-plugin-server.capabilitiesswitcher.md) to be used to change the default state of the [Capabilities](./kibana-plugin-server.capabilities.md) entries when resolving them.A capabilities switcher can only change the state of existing capabilities. Capabilities added or removed when invoking the switcher will be ignored. | + diff --git a/docs/development/core/server/kibana-plugin-server.capabilitiessetup.registerprovider.md b/docs/development/core/server/kibana-plugin-server.capabilitiessetup.registerprovider.md index 750913ee35895b..c0e7fa50eb91d4 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilitiessetup.registerprovider.md +++ b/docs/development/core/server/kibana-plugin-server.capabilitiessetup.registerprovider.md @@ -1,46 +1,46 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) > [registerProvider](./kibana-plugin-server.capabilitiessetup.registerprovider.md) - -## CapabilitiesSetup.registerProvider() method - -Register a [CapabilitiesProvider](./kibana-plugin-server.capabilitiesprovider.md) to be used to provide [Capabilities](./kibana-plugin-server.capabilities.md) when resolving them. - -Signature: - -```typescript -registerProvider(provider: CapabilitiesProvider): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| provider | CapabilitiesProvider | | - -Returns: - -`void` - -## Example - -How to register a plugin's capabilities during setup - -```ts -// my-plugin/server/plugin.ts -public setup(core: CoreSetup, deps: {}) { - core.capabilities.registerProvider(() => { - return { - catalogue: { - myPlugin: true, - }, - myPlugin: { - someFeature: true, - featureDisabledByDefault: false, - }, - } - }); -} - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) > [registerProvider](./kibana-plugin-server.capabilitiessetup.registerprovider.md) + +## CapabilitiesSetup.registerProvider() method + +Register a [CapabilitiesProvider](./kibana-plugin-server.capabilitiesprovider.md) to be used to provide [Capabilities](./kibana-plugin-server.capabilities.md) when resolving them. + +Signature: + +```typescript +registerProvider(provider: CapabilitiesProvider): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| provider | CapabilitiesProvider | | + +Returns: + +`void` + +## Example + +How to register a plugin's capabilities during setup + +```ts +// my-plugin/server/plugin.ts +public setup(core: CoreSetup, deps: {}) { + core.capabilities.registerProvider(() => { + return { + catalogue: { + myPlugin: true, + }, + myPlugin: { + someFeature: true, + featureDisabledByDefault: false, + }, + } + }); +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.capabilitiessetup.registerswitcher.md b/docs/development/core/server/kibana-plugin-server.capabilitiessetup.registerswitcher.md index fbaa2959c635c2..948d256e9aa73e 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilitiessetup.registerswitcher.md +++ b/docs/development/core/server/kibana-plugin-server.capabilitiessetup.registerswitcher.md @@ -1,47 +1,47 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) > [registerSwitcher](./kibana-plugin-server.capabilitiessetup.registerswitcher.md) - -## CapabilitiesSetup.registerSwitcher() method - -Register a [CapabilitiesSwitcher](./kibana-plugin-server.capabilitiesswitcher.md) to be used to change the default state of the [Capabilities](./kibana-plugin-server.capabilities.md) entries when resolving them. - -A capabilities switcher can only change the state of existing capabilities. Capabilities added or removed when invoking the switcher will be ignored. - -Signature: - -```typescript -registerSwitcher(switcher: CapabilitiesSwitcher): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| switcher | CapabilitiesSwitcher | | - -Returns: - -`void` - -## Example - -How to restrict some capabilities - -```ts -// my-plugin/server/plugin.ts -public setup(core: CoreSetup, deps: {}) { - core.capabilities.registerSwitcher((request, capabilities) => { - if(myPluginApi.shouldRestrictSomePluginBecauseOf(request)) { - return { - somePlugin: { - featureEnabledByDefault: false // `featureEnabledByDefault` will be disabled. All other capabilities will remain unchanged. - } - } - } - return {}; // All capabilities will remain unchanged. - }); -} - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) > [registerSwitcher](./kibana-plugin-server.capabilitiessetup.registerswitcher.md) + +## CapabilitiesSetup.registerSwitcher() method + +Register a [CapabilitiesSwitcher](./kibana-plugin-server.capabilitiesswitcher.md) to be used to change the default state of the [Capabilities](./kibana-plugin-server.capabilities.md) entries when resolving them. + +A capabilities switcher can only change the state of existing capabilities. Capabilities added or removed when invoking the switcher will be ignored. + +Signature: + +```typescript +registerSwitcher(switcher: CapabilitiesSwitcher): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| switcher | CapabilitiesSwitcher | | + +Returns: + +`void` + +## Example + +How to restrict some capabilities + +```ts +// my-plugin/server/plugin.ts +public setup(core: CoreSetup, deps: {}) { + core.capabilities.registerSwitcher((request, capabilities) => { + if(myPluginApi.shouldRestrictSomePluginBecauseOf(request)) { + return { + somePlugin: { + featureEnabledByDefault: false // `featureEnabledByDefault` will be disabled. All other capabilities will remain unchanged. + } + } + } + return {}; // All capabilities will remain unchanged. + }); +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.capabilitiesstart.md b/docs/development/core/server/kibana-plugin-server.capabilitiesstart.md index 55cc1aed76b5b5..1f6eda9dcb3928 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilitiesstart.md +++ b/docs/development/core/server/kibana-plugin-server.capabilitiesstart.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) - -## CapabilitiesStart interface - -APIs to access the application [Capabilities](./kibana-plugin-server.capabilities.md). - -Signature: - -```typescript -export interface CapabilitiesStart -``` - -## Methods - -| Method | Description | -| --- | --- | -| [resolveCapabilities(request)](./kibana-plugin-server.capabilitiesstart.resolvecapabilities.md) | Resolve the [Capabilities](./kibana-plugin-server.capabilities.md) to be used for given request | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) + +## CapabilitiesStart interface + +APIs to access the application [Capabilities](./kibana-plugin-server.capabilities.md). + +Signature: + +```typescript +export interface CapabilitiesStart +``` + +## Methods + +| Method | Description | +| --- | --- | +| [resolveCapabilities(request)](./kibana-plugin-server.capabilitiesstart.resolvecapabilities.md) | Resolve the [Capabilities](./kibana-plugin-server.capabilities.md) to be used for given request | + diff --git a/docs/development/core/server/kibana-plugin-server.capabilitiesstart.resolvecapabilities.md b/docs/development/core/server/kibana-plugin-server.capabilitiesstart.resolvecapabilities.md index 95b751dd4fc95f..43b6f6059eb0de 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilitiesstart.resolvecapabilities.md +++ b/docs/development/core/server/kibana-plugin-server.capabilitiesstart.resolvecapabilities.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) > [resolveCapabilities](./kibana-plugin-server.capabilitiesstart.resolvecapabilities.md) - -## CapabilitiesStart.resolveCapabilities() method - -Resolve the [Capabilities](./kibana-plugin-server.capabilities.md) to be used for given request - -Signature: - -```typescript -resolveCapabilities(request: KibanaRequest): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | KibanaRequest | | - -Returns: - -`Promise` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) > [resolveCapabilities](./kibana-plugin-server.capabilitiesstart.resolvecapabilities.md) + +## CapabilitiesStart.resolveCapabilities() method + +Resolve the [Capabilities](./kibana-plugin-server.capabilities.md) to be used for given request + +Signature: + +```typescript +resolveCapabilities(request: KibanaRequest): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | KibanaRequest | | + +Returns: + +`Promise` + diff --git a/docs/development/core/server/kibana-plugin-server.capabilitiesswitcher.md b/docs/development/core/server/kibana-plugin-server.capabilitiesswitcher.md index dd6af543768965..5e5a5c63ae3416 100644 --- a/docs/development/core/server/kibana-plugin-server.capabilitiesswitcher.md +++ b/docs/development/core/server/kibana-plugin-server.capabilitiesswitcher.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesSwitcher](./kibana-plugin-server.capabilitiesswitcher.md) - -## CapabilitiesSwitcher type - -See [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) - -Signature: - -```typescript -export declare type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities) => Partial | Promise>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CapabilitiesSwitcher](./kibana-plugin-server.capabilitiesswitcher.md) + +## CapabilitiesSwitcher type + +See [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) + +Signature: + +```typescript +export declare type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities) => Partial | Promise>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.clusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-server.clusterclient._constructor_.md index 252991affbc3c9..5b76a0e43317e8 100644 --- a/docs/development/core/server/kibana-plugin-server.clusterclient._constructor_.md +++ b/docs/development/core/server/kibana-plugin-server.clusterclient._constructor_.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) > [(constructor)](./kibana-plugin-server.clusterclient._constructor_.md) - -## ClusterClient.(constructor) - -Constructs a new instance of the `ClusterClient` class - -Signature: - -```typescript -constructor(config: ElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| config | ElasticsearchClientConfig | | -| log | Logger | | -| getAuthHeaders | GetAuthHeaders | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) > [(constructor)](./kibana-plugin-server.clusterclient._constructor_.md) + +## ClusterClient.(constructor) + +Constructs a new instance of the `ClusterClient` class + +Signature: + +```typescript +constructor(config: ElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| config | ElasticsearchClientConfig | | +| log | Logger | | +| getAuthHeaders | GetAuthHeaders | | + diff --git a/docs/development/core/server/kibana-plugin-server.clusterclient.asscoped.md b/docs/development/core/server/kibana-plugin-server.clusterclient.asscoped.md index bb1f481c9ef4fb..594a05e8dfe2e4 100644 --- a/docs/development/core/server/kibana-plugin-server.clusterclient.asscoped.md +++ b/docs/development/core/server/kibana-plugin-server.clusterclient.asscoped.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) > [asScoped](./kibana-plugin-server.clusterclient.asscoped.md) - -## ClusterClient.asScoped() method - -Creates an instance of [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) based on the configuration the current cluster client that exposes additional `callAsCurrentUser` method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. - -Signature: - -```typescript -asScoped(request?: ScopeableRequest): IScopedClusterClient; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | ScopeableRequest | Request the IScopedClusterClient instance will be scoped to. Supports request optionality, Legacy.Request & FakeRequest for BWC with LegacyPlatform | - -Returns: - -`IScopedClusterClient` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) > [asScoped](./kibana-plugin-server.clusterclient.asscoped.md) + +## ClusterClient.asScoped() method + +Creates an instance of [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) based on the configuration the current cluster client that exposes additional `callAsCurrentUser` method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. + +Signature: + +```typescript +asScoped(request?: ScopeableRequest): IScopedClusterClient; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | ScopeableRequest | Request the IScopedClusterClient instance will be scoped to. Supports request optionality, Legacy.Request & FakeRequest for BWC with LegacyPlatform | + +Returns: + +`IScopedClusterClient` + diff --git a/docs/development/core/server/kibana-plugin-server.clusterclient.callasinternaluser.md b/docs/development/core/server/kibana-plugin-server.clusterclient.callasinternaluser.md index 7afb6afa4bc3b7..263bb6308f4715 100644 --- a/docs/development/core/server/kibana-plugin-server.clusterclient.callasinternaluser.md +++ b/docs/development/core/server/kibana-plugin-server.clusterclient.callasinternaluser.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) > [callAsInternalUser](./kibana-plugin-server.clusterclient.callasinternaluser.md) - -## ClusterClient.callAsInternalUser property - -Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-server.apicaller.md). - -Signature: - -```typescript -callAsInternalUser: APICaller; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) > [callAsInternalUser](./kibana-plugin-server.clusterclient.callasinternaluser.md) + +## ClusterClient.callAsInternalUser property + +Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-server.apicaller.md). + +Signature: + +```typescript +callAsInternalUser: APICaller; +``` diff --git a/docs/development/core/server/kibana-plugin-server.clusterclient.close.md b/docs/development/core/server/kibana-plugin-server.clusterclient.close.md index 6030f4372e8e03..7b0efb9c0b2e98 100644 --- a/docs/development/core/server/kibana-plugin-server.clusterclient.close.md +++ b/docs/development/core/server/kibana-plugin-server.clusterclient.close.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) > [close](./kibana-plugin-server.clusterclient.close.md) - -## ClusterClient.close() method - -Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. - -Signature: - -```typescript -close(): void; -``` -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) > [close](./kibana-plugin-server.clusterclient.close.md) + +## ClusterClient.close() method + +Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. + +Signature: + +```typescript +close(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.clusterclient.md b/docs/development/core/server/kibana-plugin-server.clusterclient.md index d547b846e65b79..65c6c33304d33c 100644 --- a/docs/development/core/server/kibana-plugin-server.clusterclient.md +++ b/docs/development/core/server/kibana-plugin-server.clusterclient.md @@ -1,35 +1,35 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) - -## ClusterClient class - -Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). - -See [ClusterClient](./kibana-plugin-server.clusterclient.md). - -Signature: - -```typescript -export declare class ClusterClient implements IClusterClient -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(config, log, getAuthHeaders)](./kibana-plugin-server.clusterclient._constructor_.md) | | Constructs a new instance of the ClusterClient class | - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [callAsInternalUser](./kibana-plugin-server.clusterclient.callasinternaluser.md) | | APICaller | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-server.apicaller.md). | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [asScoped(request)](./kibana-plugin-server.clusterclient.asscoped.md) | | Creates an instance of [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) based on the configuration the current cluster client that exposes additional callAsCurrentUser method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. | -| [close()](./kibana-plugin-server.clusterclient.close.md) | | Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ClusterClient](./kibana-plugin-server.clusterclient.md) + +## ClusterClient class + +Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). + +See [ClusterClient](./kibana-plugin-server.clusterclient.md). + +Signature: + +```typescript +export declare class ClusterClient implements IClusterClient +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(config, log, getAuthHeaders)](./kibana-plugin-server.clusterclient._constructor_.md) | | Constructs a new instance of the ClusterClient class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [callAsInternalUser](./kibana-plugin-server.clusterclient.callasinternaluser.md) | | APICaller | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-server.apicaller.md). | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [asScoped(request)](./kibana-plugin-server.clusterclient.asscoped.md) | | Creates an instance of [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) based on the configuration the current cluster client that exposes additional callAsCurrentUser method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. | +| [close()](./kibana-plugin-server.clusterclient.close.md) | | Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. | + diff --git a/docs/development/core/server/kibana-plugin-server.configdeprecation.md b/docs/development/core/server/kibana-plugin-server.configdeprecation.md index ba7e40b8dc6247..772a52f5b9264b 100644 --- a/docs/development/core/server/kibana-plugin-server.configdeprecation.md +++ b/docs/development/core/server/kibana-plugin-server.configdeprecation.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) - -## ConfigDeprecation type - -Configuration deprecation returned from [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md) that handles a single deprecation from the configuration. - -Signature: - -```typescript -export declare type ConfigDeprecation = (config: Record, fromPath: string, logger: ConfigDeprecationLogger) => Record; -``` - -## Remarks - -This should only be manually implemented if [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) does not provide the proper helpers for a specific deprecation need. - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) + +## ConfigDeprecation type + +Configuration deprecation returned from [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md) that handles a single deprecation from the configuration. + +Signature: + +```typescript +export declare type ConfigDeprecation = (config: Record, fromPath: string, logger: ConfigDeprecationLogger) => Record; +``` + +## Remarks + +This should only be manually implemented if [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) does not provide the proper helpers for a specific deprecation need. + diff --git a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.md b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.md index 0302797147cffa..c61907f3663012 100644 --- a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.md +++ b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.md @@ -1,36 +1,36 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) - -## ConfigDeprecationFactory interface - -Provides helpers to generates the most commonly used [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) when invoking a [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md). - -See methods documentation for more detailed examples. - -Signature: - -```typescript -export interface ConfigDeprecationFactory -``` - -## Example - - -```typescript -const provider: ConfigDeprecationProvider = ({ rename, unused }) => [ - rename('oldKey', 'newKey'), - unused('deprecatedKey'), -] - -``` - -## Methods - -| Method | Description | -| --- | --- | -| [rename(oldKey, newKey)](./kibana-plugin-server.configdeprecationfactory.rename.md) | Rename a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the oldKey was found and deprecation applied. | -| [renameFromRoot(oldKey, newKey)](./kibana-plugin-server.configdeprecationfactory.renamefromroot.md) | Rename a configuration property from the root configuration. Will log a deprecation warning if the oldKey was found and deprecation applied.This should be only used when renaming properties from different configuration's path. To rename properties from inside a plugin's configuration, use 'rename' instead. | -| [unused(unusedKey)](./kibana-plugin-server.configdeprecationfactory.unused.md) | Remove a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the unused key was found and deprecation applied. | -| [unusedFromRoot(unusedKey)](./kibana-plugin-server.configdeprecationfactory.unusedfromroot.md) | Remove a configuration property from the root configuration. Will log a deprecation warning if the unused key was found and deprecation applied.This should be only used when removing properties from outside of a plugin's configuration. To remove properties from inside a plugin's configuration, use 'unused' instead. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) + +## ConfigDeprecationFactory interface + +Provides helpers to generates the most commonly used [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) when invoking a [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md). + +See methods documentation for more detailed examples. + +Signature: + +```typescript +export interface ConfigDeprecationFactory +``` + +## Example + + +```typescript +const provider: ConfigDeprecationProvider = ({ rename, unused }) => [ + rename('oldKey', 'newKey'), + unused('deprecatedKey'), +] + +``` + +## Methods + +| Method | Description | +| --- | --- | +| [rename(oldKey, newKey)](./kibana-plugin-server.configdeprecationfactory.rename.md) | Rename a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the oldKey was found and deprecation applied. | +| [renameFromRoot(oldKey, newKey)](./kibana-plugin-server.configdeprecationfactory.renamefromroot.md) | Rename a configuration property from the root configuration. Will log a deprecation warning if the oldKey was found and deprecation applied.This should be only used when renaming properties from different configuration's path. To rename properties from inside a plugin's configuration, use 'rename' instead. | +| [unused(unusedKey)](./kibana-plugin-server.configdeprecationfactory.unused.md) | Remove a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the unused key was found and deprecation applied. | +| [unusedFromRoot(unusedKey)](./kibana-plugin-server.configdeprecationfactory.unusedfromroot.md) | Remove a configuration property from the root configuration. Will log a deprecation warning if the unused key was found and deprecation applied.This should be only used when removing properties from outside of a plugin's configuration. To remove properties from inside a plugin's configuration, use 'unused' instead. | + diff --git a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.rename.md b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.rename.md index 5bbbad763c545b..6d7ea00b3cab17 100644 --- a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.rename.md +++ b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.rename.md @@ -1,36 +1,36 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) > [rename](./kibana-plugin-server.configdeprecationfactory.rename.md) - -## ConfigDeprecationFactory.rename() method - -Rename a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the oldKey was found and deprecation applied. - -Signature: - -```typescript -rename(oldKey: string, newKey: string): ConfigDeprecation; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| oldKey | string | | -| newKey | string | | - -Returns: - -`ConfigDeprecation` - -## Example - -Rename 'myplugin.oldKey' to 'myplugin.newKey' - -```typescript -const provider: ConfigDeprecationProvider = ({ rename }) => [ - rename('oldKey', 'newKey'), -] - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) > [rename](./kibana-plugin-server.configdeprecationfactory.rename.md) + +## ConfigDeprecationFactory.rename() method + +Rename a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the oldKey was found and deprecation applied. + +Signature: + +```typescript +rename(oldKey: string, newKey: string): ConfigDeprecation; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| oldKey | string | | +| newKey | string | | + +Returns: + +`ConfigDeprecation` + +## Example + +Rename 'myplugin.oldKey' to 'myplugin.newKey' + +```typescript +const provider: ConfigDeprecationProvider = ({ rename }) => [ + rename('oldKey', 'newKey'), +] + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.renamefromroot.md b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.renamefromroot.md index d35ba25256fa1c..269f242ec35da6 100644 --- a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.renamefromroot.md +++ b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.renamefromroot.md @@ -1,38 +1,38 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) > [renameFromRoot](./kibana-plugin-server.configdeprecationfactory.renamefromroot.md) - -## ConfigDeprecationFactory.renameFromRoot() method - -Rename a configuration property from the root configuration. Will log a deprecation warning if the oldKey was found and deprecation applied. - -This should be only used when renaming properties from different configuration's path. To rename properties from inside a plugin's configuration, use 'rename' instead. - -Signature: - -```typescript -renameFromRoot(oldKey: string, newKey: string): ConfigDeprecation; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| oldKey | string | | -| newKey | string | | - -Returns: - -`ConfigDeprecation` - -## Example - -Rename 'oldplugin.key' to 'newplugin.key' - -```typescript -const provider: ConfigDeprecationProvider = ({ renameFromRoot }) => [ - renameFromRoot('oldplugin.key', 'newplugin.key'), -] - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) > [renameFromRoot](./kibana-plugin-server.configdeprecationfactory.renamefromroot.md) + +## ConfigDeprecationFactory.renameFromRoot() method + +Rename a configuration property from the root configuration. Will log a deprecation warning if the oldKey was found and deprecation applied. + +This should be only used when renaming properties from different configuration's path. To rename properties from inside a plugin's configuration, use 'rename' instead. + +Signature: + +```typescript +renameFromRoot(oldKey: string, newKey: string): ConfigDeprecation; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| oldKey | string | | +| newKey | string | | + +Returns: + +`ConfigDeprecation` + +## Example + +Rename 'oldplugin.key' to 'newplugin.key' + +```typescript +const provider: ConfigDeprecationProvider = ({ renameFromRoot }) => [ + renameFromRoot('oldplugin.key', 'newplugin.key'), +] + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.unused.md b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.unused.md index 0381480e84c4dc..87576936607d7c 100644 --- a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.unused.md +++ b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.unused.md @@ -1,35 +1,35 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) > [unused](./kibana-plugin-server.configdeprecationfactory.unused.md) - -## ConfigDeprecationFactory.unused() method - -Remove a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the unused key was found and deprecation applied. - -Signature: - -```typescript -unused(unusedKey: string): ConfigDeprecation; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| unusedKey | string | | - -Returns: - -`ConfigDeprecation` - -## Example - -Flags 'myplugin.deprecatedKey' as unused - -```typescript -const provider: ConfigDeprecationProvider = ({ unused }) => [ - unused('deprecatedKey'), -] - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) > [unused](./kibana-plugin-server.configdeprecationfactory.unused.md) + +## ConfigDeprecationFactory.unused() method + +Remove a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the unused key was found and deprecation applied. + +Signature: + +```typescript +unused(unusedKey: string): ConfigDeprecation; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unusedKey | string | | + +Returns: + +`ConfigDeprecation` + +## Example + +Flags 'myplugin.deprecatedKey' as unused + +```typescript +const provider: ConfigDeprecationProvider = ({ unused }) => [ + unused('deprecatedKey'), +] + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.unusedfromroot.md b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.unusedfromroot.md index ed37638b07375b..f7d81a010f8128 100644 --- a/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.unusedfromroot.md +++ b/docs/development/core/server/kibana-plugin-server.configdeprecationfactory.unusedfromroot.md @@ -1,37 +1,37 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) > [unusedFromRoot](./kibana-plugin-server.configdeprecationfactory.unusedfromroot.md) - -## ConfigDeprecationFactory.unusedFromRoot() method - -Remove a configuration property from the root configuration. Will log a deprecation warning if the unused key was found and deprecation applied. - -This should be only used when removing properties from outside of a plugin's configuration. To remove properties from inside a plugin's configuration, use 'unused' instead. - -Signature: - -```typescript -unusedFromRoot(unusedKey: string): ConfigDeprecation; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| unusedKey | string | | - -Returns: - -`ConfigDeprecation` - -## Example - -Flags 'somepath.deprecatedProperty' as unused - -```typescript -const provider: ConfigDeprecationProvider = ({ unusedFromRoot }) => [ - unusedFromRoot('somepath.deprecatedProperty'), -] - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) > [unusedFromRoot](./kibana-plugin-server.configdeprecationfactory.unusedfromroot.md) + +## ConfigDeprecationFactory.unusedFromRoot() method + +Remove a configuration property from the root configuration. Will log a deprecation warning if the unused key was found and deprecation applied. + +This should be only used when removing properties from outside of a plugin's configuration. To remove properties from inside a plugin's configuration, use 'unused' instead. + +Signature: + +```typescript +unusedFromRoot(unusedKey: string): ConfigDeprecation; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| unusedKey | string | | + +Returns: + +`ConfigDeprecation` + +## Example + +Flags 'somepath.deprecatedProperty' as unused + +```typescript +const provider: ConfigDeprecationProvider = ({ unusedFromRoot }) => [ + unusedFromRoot('somepath.deprecatedProperty'), +] + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.configdeprecationlogger.md b/docs/development/core/server/kibana-plugin-server.configdeprecationlogger.md index d2bb2a4e441b38..f3d6303a9f0d71 100644 --- a/docs/development/core/server/kibana-plugin-server.configdeprecationlogger.md +++ b/docs/development/core/server/kibana-plugin-server.configdeprecationlogger.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationLogger](./kibana-plugin-server.configdeprecationlogger.md) - -## ConfigDeprecationLogger type - -Logger interface used when invoking a [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) - -Signature: - -```typescript -export declare type ConfigDeprecationLogger = (message: string) => void; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationLogger](./kibana-plugin-server.configdeprecationlogger.md) + +## ConfigDeprecationLogger type + +Logger interface used when invoking a [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) + +Signature: + +```typescript +export declare type ConfigDeprecationLogger = (message: string) => void; +``` diff --git a/docs/development/core/server/kibana-plugin-server.configdeprecationprovider.md b/docs/development/core/server/kibana-plugin-server.configdeprecationprovider.md index f5da9e9452bb51..5d0619ef9e1711 100644 --- a/docs/development/core/server/kibana-plugin-server.configdeprecationprovider.md +++ b/docs/development/core/server/kibana-plugin-server.configdeprecationprovider.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md) - -## ConfigDeprecationProvider type - -A provider that should returns a list of [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md). - -See [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) for more usage examples. - -Signature: - -```typescript -export declare type ConfigDeprecationProvider = (factory: ConfigDeprecationFactory) => ConfigDeprecation[]; -``` - -## Example - - -```typescript -const provider: ConfigDeprecationProvider = ({ rename, unused }) => [ - rename('oldKey', 'newKey'), - unused('deprecatedKey'), - myCustomDeprecation, -] - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md) + +## ConfigDeprecationProvider type + +A provider that should returns a list of [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md). + +See [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) for more usage examples. + +Signature: + +```typescript +export declare type ConfigDeprecationProvider = (factory: ConfigDeprecationFactory) => ConfigDeprecation[]; +``` + +## Example + + +```typescript +const provider: ConfigDeprecationProvider = ({ rename, unused }) => [ + rename('oldKey', 'newKey'), + unused('deprecatedKey'), + myCustomDeprecation, +] + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.configpath.md b/docs/development/core/server/kibana-plugin-server.configpath.md index 674769115b1818..684e4c33d3c3b7 100644 --- a/docs/development/core/server/kibana-plugin-server.configpath.md +++ b/docs/development/core/server/kibana-plugin-server.configpath.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigPath](./kibana-plugin-server.configpath.md) - -## ConfigPath type - - -Signature: - -```typescript -export declare type ConfigPath = string | string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigPath](./kibana-plugin-server.configpath.md) + +## ConfigPath type + + +Signature: + +```typescript +export declare type ConfigPath = string | string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md b/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md index 7096bfc43a520b..323c131f2e9a81 100644 --- a/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ContextSetup](./kibana-plugin-server.contextsetup.md) > [createContextContainer](./kibana-plugin-server.contextsetup.createcontextcontainer.md) - -## ContextSetup.createContextContainer() method - -Creates a new [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for a service owner. - -Signature: - -```typescript -createContextContainer>(): IContextContainer; -``` -Returns: - -`IContextContainer` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ContextSetup](./kibana-plugin-server.contextsetup.md) > [createContextContainer](./kibana-plugin-server.contextsetup.createcontextcontainer.md) + +## ContextSetup.createContextContainer() method + +Creates a new [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for a service owner. + +Signature: + +```typescript +createContextContainer>(): IContextContainer; +``` +Returns: + +`IContextContainer` + diff --git a/docs/development/core/server/kibana-plugin-server.contextsetup.md b/docs/development/core/server/kibana-plugin-server.contextsetup.md index 1b2a1e2f1b621d..99d87c78ce57f6 100644 --- a/docs/development/core/server/kibana-plugin-server.contextsetup.md +++ b/docs/development/core/server/kibana-plugin-server.contextsetup.md @@ -1,138 +1,138 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ContextSetup](./kibana-plugin-server.contextsetup.md) - -## ContextSetup interface - -An object that handles registration of context providers and configuring handlers with context. - -Signature: - -```typescript -export interface ContextSetup -``` - -## Remarks - -A [IContextContainer](./kibana-plugin-server.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. - -Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. - -In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-server.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. - -When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. - -```ts -// Correct -class MyPlugin { - private readonly handlers = new Map(); - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - return { - registerContext(pluginOpaqueId, contextName, provider) { - this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); - }, - registerRoute(pluginOpaqueId, path, handler) { - this.handlers.set( - path, - this.contextContainer.createHandler(pluginOpaqueId, handler) - ); - } - } - } -} - -// Incorrect -class MyPlugin { - private readonly handlers = new Map(); - - constructor(private readonly initContext: PluginInitializerContext) {} - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - return { - registerContext(contextName, provider) { - // BUG! - // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. - this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); - }, - registerRoute(path, handler) { - this.handlers.set( - path, - // BUG! - // This handler will not receive any contexts provided by other dependencies of the calling plugin. - this.contextContainer.createHandler(this.initContext.opaqueId, handler) - ); - } - } - } -} - -``` - -## Example - -Say we're creating a plugin for rendering visualizations that allows new rendering methods to be registered. If we want to offer context to these rendering methods, we can leverage the ContextService to manage these contexts. - -```ts -export interface VizRenderContext { - core: { - i18n: I18nStart; - uiSettings: IUiSettingsClient; - } - [contextName: string]: unknown; -} - -export type VizRenderer = (context: VizRenderContext, domElement: HTMLElement) => () => void; -// When a renderer is bound via `contextContainer.createHandler` this is the type that will be returned. -type BoundVizRenderer = (domElement: HTMLElement) => () => void; - -class VizRenderingPlugin { - private readonly contextContainer?: IContextContainer; - private readonly vizRenderers = new Map(); - - constructor(private readonly initContext: PluginInitializerContext) {} - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - - return { - registerContext: this.contextContainer.registerContext, - registerVizRenderer: (plugin: PluginOpaqueId, renderMethod: string, renderer: VizTypeRenderer) => - this.vizRenderers.set(renderMethod, this.contextContainer.createHandler(plugin, renderer)), - }; - } - - start(core) { - // Register the core context available to all renderers. Use the VizRendererContext's opaqueId as the first arg. - this.contextContainer.registerContext(this.initContext.opaqueId, 'core', () => ({ - i18n: core.i18n, - uiSettings: core.uiSettings - })); - - return { - registerContext: this.contextContainer.registerContext, - - renderVizualization: (renderMethod: string, domElement: HTMLElement) => { - if (!this.vizRenderer.has(renderMethod)) { - throw new Error(`Render method '${renderMethod}' has not been registered`); - } - - // The handler can now be called directly with only an `HTMLElement` and will automatically - // have a new `context` object created and populated by the context container. - const handler = this.vizRenderers.get(renderMethod) - return handler(domElement); - } - }; - } -} - -``` - -## Methods - -| Method | Description | -| --- | --- | -| [createContextContainer()](./kibana-plugin-server.contextsetup.createcontextcontainer.md) | Creates a new [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for a service owner. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ContextSetup](./kibana-plugin-server.contextsetup.md) + +## ContextSetup interface + +An object that handles registration of context providers and configuring handlers with context. + +Signature: + +```typescript +export interface ContextSetup +``` + +## Remarks + +A [IContextContainer](./kibana-plugin-server.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. + +Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. + +In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-server.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. + +When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. + +```ts +// Correct +class MyPlugin { + private readonly handlers = new Map(); + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(pluginOpaqueId, contextName, provider) { + this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); + }, + registerRoute(pluginOpaqueId, path, handler) { + this.handlers.set( + path, + this.contextContainer.createHandler(pluginOpaqueId, handler) + ); + } + } + } +} + +// Incorrect +class MyPlugin { + private readonly handlers = new Map(); + + constructor(private readonly initContext: PluginInitializerContext) {} + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(contextName, provider) { + // BUG! + // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. + this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); + }, + registerRoute(path, handler) { + this.handlers.set( + path, + // BUG! + // This handler will not receive any contexts provided by other dependencies of the calling plugin. + this.contextContainer.createHandler(this.initContext.opaqueId, handler) + ); + } + } + } +} + +``` + +## Example + +Say we're creating a plugin for rendering visualizations that allows new rendering methods to be registered. If we want to offer context to these rendering methods, we can leverage the ContextService to manage these contexts. + +```ts +export interface VizRenderContext { + core: { + i18n: I18nStart; + uiSettings: IUiSettingsClient; + } + [contextName: string]: unknown; +} + +export type VizRenderer = (context: VizRenderContext, domElement: HTMLElement) => () => void; +// When a renderer is bound via `contextContainer.createHandler` this is the type that will be returned. +type BoundVizRenderer = (domElement: HTMLElement) => () => void; + +class VizRenderingPlugin { + private readonly contextContainer?: IContextContainer; + private readonly vizRenderers = new Map(); + + constructor(private readonly initContext: PluginInitializerContext) {} + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + + return { + registerContext: this.contextContainer.registerContext, + registerVizRenderer: (plugin: PluginOpaqueId, renderMethod: string, renderer: VizTypeRenderer) => + this.vizRenderers.set(renderMethod, this.contextContainer.createHandler(plugin, renderer)), + }; + } + + start(core) { + // Register the core context available to all renderers. Use the VizRendererContext's opaqueId as the first arg. + this.contextContainer.registerContext(this.initContext.opaqueId, 'core', () => ({ + i18n: core.i18n, + uiSettings: core.uiSettings + })); + + return { + registerContext: this.contextContainer.registerContext, + + renderVizualization: (renderMethod: string, domElement: HTMLElement) => { + if (!this.vizRenderer.has(renderMethod)) { + throw new Error(`Render method '${renderMethod}' has not been registered`); + } + + // The handler can now be called directly with only an `HTMLElement` and will automatically + // have a new `context` object created and populated by the context container. + const handler = this.vizRenderers.get(renderMethod) + return handler(domElement); + } + }; + } +} + +``` + +## Methods + +| Method | Description | +| --- | --- | +| [createContextContainer()](./kibana-plugin-server.contextsetup.createcontextcontainer.md) | Creates a new [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for a service owner. | + diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.capabilities.md b/docs/development/core/server/kibana-plugin-server.coresetup.capabilities.md index fe50347d97e3c4..413a4155aeb31e 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.capabilities.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.capabilities.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [capabilities](./kibana-plugin-server.coresetup.capabilities.md) - -## CoreSetup.capabilities property - -[CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) - -Signature: - -```typescript -capabilities: CapabilitiesSetup; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [capabilities](./kibana-plugin-server.coresetup.capabilities.md) + +## CoreSetup.capabilities property + +[CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) + +Signature: + +```typescript +capabilities: CapabilitiesSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.context.md b/docs/development/core/server/kibana-plugin-server.coresetup.context.md index 63c37eec70b057..0417203a92e23d 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.context.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.context.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [context](./kibana-plugin-server.coresetup.context.md) - -## CoreSetup.context property - -[ContextSetup](./kibana-plugin-server.contextsetup.md) - -Signature: - -```typescript -context: ContextSetup; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [context](./kibana-plugin-server.coresetup.context.md) + +## CoreSetup.context property + +[ContextSetup](./kibana-plugin-server.contextsetup.md) + +Signature: + +```typescript +context: ContextSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.elasticsearch.md b/docs/development/core/server/kibana-plugin-server.coresetup.elasticsearch.md index 9498e0223350dc..0933487f5dcefc 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.elasticsearch.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.elasticsearch.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) - -## CoreSetup.elasticsearch property - -[ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) - -Signature: - -```typescript -elasticsearch: ElasticsearchServiceSetup; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) + +## CoreSetup.elasticsearch property + +[ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) + +Signature: + +```typescript +elasticsearch: ElasticsearchServiceSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.http.md b/docs/development/core/server/kibana-plugin-server.coresetup.http.md index 09b12bca7b275c..cb77075ad1df6b 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.http.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.http.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [http](./kibana-plugin-server.coresetup.http.md) - -## CoreSetup.http property - -[HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) - -Signature: - -```typescript -http: HttpServiceSetup; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [http](./kibana-plugin-server.coresetup.http.md) + +## CoreSetup.http property + +[HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) + +Signature: + +```typescript +http: HttpServiceSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.savedobjects.md b/docs/development/core/server/kibana-plugin-server.coresetup.savedobjects.md index 96acc1ffce1944..e19ec235608a46 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.savedobjects.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.savedobjects.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [savedObjects](./kibana-plugin-server.coresetup.savedobjects.md) - -## CoreSetup.savedObjects property - -[SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) - -Signature: - -```typescript -savedObjects: SavedObjectsServiceSetup; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [savedObjects](./kibana-plugin-server.coresetup.savedobjects.md) + +## CoreSetup.savedObjects property + +[SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) + +Signature: + +```typescript +savedObjects: SavedObjectsServiceSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.uisettings.md b/docs/development/core/server/kibana-plugin-server.coresetup.uisettings.md index 54120d7c3fa8da..45c304a43fff61 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.uisettings.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.uisettings.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [uiSettings](./kibana-plugin-server.coresetup.uisettings.md) - -## CoreSetup.uiSettings property - -[UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) - -Signature: - -```typescript -uiSettings: UiSettingsServiceSetup; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [uiSettings](./kibana-plugin-server.coresetup.uisettings.md) + +## CoreSetup.uiSettings property + +[UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) + +Signature: + +```typescript +uiSettings: UiSettingsServiceSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.uuid.md b/docs/development/core/server/kibana-plugin-server.coresetup.uuid.md index 2b9077735d8e32..45adf1262470d5 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.uuid.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.uuid.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [uuid](./kibana-plugin-server.coresetup.uuid.md) - -## CoreSetup.uuid property - -[UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) - -Signature: - -```typescript -uuid: UuidServiceSetup; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreSetup](./kibana-plugin-server.coresetup.md) > [uuid](./kibana-plugin-server.coresetup.uuid.md) + +## CoreSetup.uuid property + +[UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) + +Signature: + +```typescript +uuid: UuidServiceSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-server.corestart.capabilities.md b/docs/development/core/server/kibana-plugin-server.corestart.capabilities.md index 03930d367ee75f..937f5f76cd803c 100644 --- a/docs/development/core/server/kibana-plugin-server.corestart.capabilities.md +++ b/docs/development/core/server/kibana-plugin-server.corestart.capabilities.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreStart](./kibana-plugin-server.corestart.md) > [capabilities](./kibana-plugin-server.corestart.capabilities.md) - -## CoreStart.capabilities property - -[CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) - -Signature: - -```typescript -capabilities: CapabilitiesStart; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreStart](./kibana-plugin-server.corestart.md) > [capabilities](./kibana-plugin-server.corestart.capabilities.md) + +## CoreStart.capabilities property + +[CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) + +Signature: + +```typescript +capabilities: CapabilitiesStart; +``` diff --git a/docs/development/core/server/kibana-plugin-server.corestart.md b/docs/development/core/server/kibana-plugin-server.corestart.md index 167c69d5fe3297..0dd69f7b1494ed 100644 --- a/docs/development/core/server/kibana-plugin-server.corestart.md +++ b/docs/development/core/server/kibana-plugin-server.corestart.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreStart](./kibana-plugin-server.corestart.md) - -## CoreStart interface - -Context passed to the plugins `start` method. - -Signature: - -```typescript -export interface CoreStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [capabilities](./kibana-plugin-server.corestart.capabilities.md) | CapabilitiesStart | [CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) | -| [savedObjects](./kibana-plugin-server.corestart.savedobjects.md) | SavedObjectsServiceStart | [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) | -| [uiSettings](./kibana-plugin-server.corestart.uisettings.md) | UiSettingsServiceStart | [UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreStart](./kibana-plugin-server.corestart.md) + +## CoreStart interface + +Context passed to the plugins `start` method. + +Signature: + +```typescript +export interface CoreStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [capabilities](./kibana-plugin-server.corestart.capabilities.md) | CapabilitiesStart | [CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) | +| [savedObjects](./kibana-plugin-server.corestart.savedobjects.md) | SavedObjectsServiceStart | [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) | +| [uiSettings](./kibana-plugin-server.corestart.uisettings.md) | UiSettingsServiceStart | [UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) | + diff --git a/docs/development/core/server/kibana-plugin-server.corestart.savedobjects.md b/docs/development/core/server/kibana-plugin-server.corestart.savedobjects.md index 531b04e9eed07a..516dd3d9532d41 100644 --- a/docs/development/core/server/kibana-plugin-server.corestart.savedobjects.md +++ b/docs/development/core/server/kibana-plugin-server.corestart.savedobjects.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreStart](./kibana-plugin-server.corestart.md) > [savedObjects](./kibana-plugin-server.corestart.savedobjects.md) - -## CoreStart.savedObjects property - -[SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) - -Signature: - -```typescript -savedObjects: SavedObjectsServiceStart; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreStart](./kibana-plugin-server.corestart.md) > [savedObjects](./kibana-plugin-server.corestart.savedobjects.md) + +## CoreStart.savedObjects property + +[SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) + +Signature: + +```typescript +savedObjects: SavedObjectsServiceStart; +``` diff --git a/docs/development/core/server/kibana-plugin-server.corestart.uisettings.md b/docs/development/core/server/kibana-plugin-server.corestart.uisettings.md index 323e929f2918e4..408a83585f01c5 100644 --- a/docs/development/core/server/kibana-plugin-server.corestart.uisettings.md +++ b/docs/development/core/server/kibana-plugin-server.corestart.uisettings.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreStart](./kibana-plugin-server.corestart.md) > [uiSettings](./kibana-plugin-server.corestart.uisettings.md) - -## CoreStart.uiSettings property - -[UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) - -Signature: - -```typescript -uiSettings: UiSettingsServiceStart; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CoreStart](./kibana-plugin-server.corestart.md) > [uiSettings](./kibana-plugin-server.corestart.uisettings.md) + +## CoreStart.uiSettings property + +[UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) + +Signature: + +```typescript +uiSettings: UiSettingsServiceStart; +``` diff --git a/docs/development/core/server/kibana-plugin-server.cspconfig.default.md b/docs/development/core/server/kibana-plugin-server.cspconfig.default.md index 56e6cf35cdd136..c031db6aa37497 100644 --- a/docs/development/core/server/kibana-plugin-server.cspconfig.default.md +++ b/docs/development/core/server/kibana-plugin-server.cspconfig.default.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [DEFAULT](./kibana-plugin-server.cspconfig.default.md) - -## CspConfig.DEFAULT property - -Signature: - -```typescript -static readonly DEFAULT: CspConfig; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [DEFAULT](./kibana-plugin-server.cspconfig.default.md) + +## CspConfig.DEFAULT property + +Signature: + +```typescript +static readonly DEFAULT: CspConfig; +``` diff --git a/docs/development/core/server/kibana-plugin-server.cspconfig.header.md b/docs/development/core/server/kibana-plugin-server.cspconfig.header.md index e3a3d5d712a420..79c69d0ddb452d 100644 --- a/docs/development/core/server/kibana-plugin-server.cspconfig.header.md +++ b/docs/development/core/server/kibana-plugin-server.cspconfig.header.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [header](./kibana-plugin-server.cspconfig.header.md) - -## CspConfig.header property - -Signature: - -```typescript -readonly header: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [header](./kibana-plugin-server.cspconfig.header.md) + +## CspConfig.header property + +Signature: + +```typescript +readonly header: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.cspconfig.md b/docs/development/core/server/kibana-plugin-server.cspconfig.md index 7e491cb0df9120..b0cd248db6e401 100644 --- a/docs/development/core/server/kibana-plugin-server.cspconfig.md +++ b/docs/development/core/server/kibana-plugin-server.cspconfig.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) - -## CspConfig class - -CSP configuration for use in Kibana. - -Signature: - -```typescript -export declare class CspConfig implements ICspConfig -``` - -## Remarks - -The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `CspConfig` class. - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [DEFAULT](./kibana-plugin-server.cspconfig.default.md) | static | CspConfig | | -| [header](./kibana-plugin-server.cspconfig.header.md) | | string | | -| [rules](./kibana-plugin-server.cspconfig.rules.md) | | string[] | | -| [strict](./kibana-plugin-server.cspconfig.strict.md) | | boolean | | -| [warnLegacyBrowsers](./kibana-plugin-server.cspconfig.warnlegacybrowsers.md) | | boolean | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) + +## CspConfig class + +CSP configuration for use in Kibana. + +Signature: + +```typescript +export declare class CspConfig implements ICspConfig +``` + +## Remarks + +The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `CspConfig` class. + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [DEFAULT](./kibana-plugin-server.cspconfig.default.md) | static | CspConfig | | +| [header](./kibana-plugin-server.cspconfig.header.md) | | string | | +| [rules](./kibana-plugin-server.cspconfig.rules.md) | | string[] | | +| [strict](./kibana-plugin-server.cspconfig.strict.md) | | boolean | | +| [warnLegacyBrowsers](./kibana-plugin-server.cspconfig.warnlegacybrowsers.md) | | boolean | | + diff --git a/docs/development/core/server/kibana-plugin-server.cspconfig.rules.md b/docs/development/core/server/kibana-plugin-server.cspconfig.rules.md index c5270c2375dc17..8110cf965386c6 100644 --- a/docs/development/core/server/kibana-plugin-server.cspconfig.rules.md +++ b/docs/development/core/server/kibana-plugin-server.cspconfig.rules.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [rules](./kibana-plugin-server.cspconfig.rules.md) - -## CspConfig.rules property - -Signature: - -```typescript -readonly rules: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [rules](./kibana-plugin-server.cspconfig.rules.md) + +## CspConfig.rules property + +Signature: + +```typescript +readonly rules: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.cspconfig.strict.md b/docs/development/core/server/kibana-plugin-server.cspconfig.strict.md index 3ac48edd374c95..046ab8d8fd5f47 100644 --- a/docs/development/core/server/kibana-plugin-server.cspconfig.strict.md +++ b/docs/development/core/server/kibana-plugin-server.cspconfig.strict.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [strict](./kibana-plugin-server.cspconfig.strict.md) - -## CspConfig.strict property - -Signature: - -```typescript -readonly strict: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [strict](./kibana-plugin-server.cspconfig.strict.md) + +## CspConfig.strict property + +Signature: + +```typescript +readonly strict: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.cspconfig.warnlegacybrowsers.md b/docs/development/core/server/kibana-plugin-server.cspconfig.warnlegacybrowsers.md index 59d661593d9402..b5ce89ccee33f5 100644 --- a/docs/development/core/server/kibana-plugin-server.cspconfig.warnlegacybrowsers.md +++ b/docs/development/core/server/kibana-plugin-server.cspconfig.warnlegacybrowsers.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [warnLegacyBrowsers](./kibana-plugin-server.cspconfig.warnlegacybrowsers.md) - -## CspConfig.warnLegacyBrowsers property - -Signature: - -```typescript -readonly warnLegacyBrowsers: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CspConfig](./kibana-plugin-server.cspconfig.md) > [warnLegacyBrowsers](./kibana-plugin-server.cspconfig.warnlegacybrowsers.md) + +## CspConfig.warnLegacyBrowsers property + +Signature: + +```typescript +readonly warnLegacyBrowsers: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.body.md b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.body.md index 1a2282aae23a44..3de5c93438f108 100644 --- a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.body.md +++ b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.body.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) > [body](./kibana-plugin-server.customhttpresponseoptions.body.md) - -## CustomHttpResponseOptions.body property - -HTTP message to send to the client - -Signature: - -```typescript -body?: T; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) > [body](./kibana-plugin-server.customhttpresponseoptions.body.md) + +## CustomHttpResponseOptions.body property + +HTTP message to send to the client + +Signature: + +```typescript +body?: T; +``` diff --git a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.headers.md b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.headers.md index 93a36bfe59f5e8..5cd2e6aa0795fe 100644 --- a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.headers.md +++ b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.headers.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) > [headers](./kibana-plugin-server.customhttpresponseoptions.headers.md) - -## CustomHttpResponseOptions.headers property - -HTTP Headers with additional information about response - -Signature: - -```typescript -headers?: ResponseHeaders; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) > [headers](./kibana-plugin-server.customhttpresponseoptions.headers.md) + +## CustomHttpResponseOptions.headers property + +HTTP Headers with additional information about response + +Signature: + +```typescript +headers?: ResponseHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.md b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.md index 3e100f709c8c7c..ef941a2e2bd630 100644 --- a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.md +++ b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) - -## CustomHttpResponseOptions interface - -HTTP response parameters for a response with adjustable status code. - -Signature: - -```typescript -export interface CustomHttpResponseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [body](./kibana-plugin-server.customhttpresponseoptions.body.md) | T | HTTP message to send to the client | -| [headers](./kibana-plugin-server.customhttpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | -| [statusCode](./kibana-plugin-server.customhttpresponseoptions.statuscode.md) | number | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) + +## CustomHttpResponseOptions interface + +HTTP response parameters for a response with adjustable status code. + +Signature: + +```typescript +export interface CustomHttpResponseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-server.customhttpresponseoptions.body.md) | T | HTTP message to send to the client | +| [headers](./kibana-plugin-server.customhttpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | +| [statusCode](./kibana-plugin-server.customhttpresponseoptions.statuscode.md) | number | | + diff --git a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.statuscode.md b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.statuscode.md index 5444ccd2ebb554..4fb6882275ad19 100644 --- a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.statuscode.md +++ b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.statuscode.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) > [statusCode](./kibana-plugin-server.customhttpresponseoptions.statuscode.md) - -## CustomHttpResponseOptions.statusCode property - -Signature: - -```typescript -statusCode: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) > [statusCode](./kibana-plugin-server.customhttpresponseoptions.statuscode.md) + +## CustomHttpResponseOptions.statusCode property + +Signature: + +```typescript +statusCode: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.md b/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.md index 47af79ae464b22..4797758bf1f556 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIClientParams](./kibana-plugin-server.deprecationapiclientparams.md) - -## DeprecationAPIClientParams interface - - -Signature: - -```typescript -export interface DeprecationAPIClientParams extends GenericParams -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [method](./kibana-plugin-server.deprecationapiclientparams.method.md) | 'GET' | | -| [path](./kibana-plugin-server.deprecationapiclientparams.path.md) | '/_migration/deprecations' | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIClientParams](./kibana-plugin-server.deprecationapiclientparams.md) + +## DeprecationAPIClientParams interface + + +Signature: + +```typescript +export interface DeprecationAPIClientParams extends GenericParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [method](./kibana-plugin-server.deprecationapiclientparams.method.md) | 'GET' | | +| [path](./kibana-plugin-server.deprecationapiclientparams.path.md) | '/_migration/deprecations' | | + diff --git a/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.method.md b/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.method.md index 7b9364009923b0..57107a03d10bbf 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.method.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.method.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIClientParams](./kibana-plugin-server.deprecationapiclientparams.md) > [method](./kibana-plugin-server.deprecationapiclientparams.method.md) - -## DeprecationAPIClientParams.method property - -Signature: - -```typescript -method: 'GET'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIClientParams](./kibana-plugin-server.deprecationapiclientparams.md) > [method](./kibana-plugin-server.deprecationapiclientparams.method.md) + +## DeprecationAPIClientParams.method property + +Signature: + +```typescript +method: 'GET'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.path.md b/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.path.md index dbddedf75171dc..f9dde4f08afa0e 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.path.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationapiclientparams.path.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIClientParams](./kibana-plugin-server.deprecationapiclientparams.md) > [path](./kibana-plugin-server.deprecationapiclientparams.path.md) - -## DeprecationAPIClientParams.path property - -Signature: - -```typescript -path: '/_migration/deprecations'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIClientParams](./kibana-plugin-server.deprecationapiclientparams.md) > [path](./kibana-plugin-server.deprecationapiclientparams.path.md) + +## DeprecationAPIClientParams.path property + +Signature: + +```typescript +path: '/_migration/deprecations'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.cluster_settings.md b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.cluster_settings.md index 5af134100407c2..74a0609dc8f5ab 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.cluster_settings.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.cluster_settings.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) > [cluster\_settings](./kibana-plugin-server.deprecationapiresponse.cluster_settings.md) - -## DeprecationAPIResponse.cluster\_settings property - -Signature: - -```typescript -cluster_settings: DeprecationInfo[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) > [cluster\_settings](./kibana-plugin-server.deprecationapiresponse.cluster_settings.md) + +## DeprecationAPIResponse.cluster\_settings property + +Signature: + +```typescript +cluster_settings: DeprecationInfo[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.index_settings.md b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.index_settings.md index c8d20c9696f63f..f5989247d67ea7 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.index_settings.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.index_settings.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) > [index\_settings](./kibana-plugin-server.deprecationapiresponse.index_settings.md) - -## DeprecationAPIResponse.index\_settings property - -Signature: - -```typescript -index_settings: IndexSettingsDeprecationInfo; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) > [index\_settings](./kibana-plugin-server.deprecationapiresponse.index_settings.md) + +## DeprecationAPIResponse.index\_settings property + +Signature: + +```typescript +index_settings: IndexSettingsDeprecationInfo; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.md b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.md index 5a2954d10c1614..f5d4017f10b5dc 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) - -## DeprecationAPIResponse interface - - -Signature: - -```typescript -export interface DeprecationAPIResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [cluster\_settings](./kibana-plugin-server.deprecationapiresponse.cluster_settings.md) | DeprecationInfo[] | | -| [index\_settings](./kibana-plugin-server.deprecationapiresponse.index_settings.md) | IndexSettingsDeprecationInfo | | -| [ml\_settings](./kibana-plugin-server.deprecationapiresponse.ml_settings.md) | DeprecationInfo[] | | -| [node\_settings](./kibana-plugin-server.deprecationapiresponse.node_settings.md) | DeprecationInfo[] | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) + +## DeprecationAPIResponse interface + + +Signature: + +```typescript +export interface DeprecationAPIResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [cluster\_settings](./kibana-plugin-server.deprecationapiresponse.cluster_settings.md) | DeprecationInfo[] | | +| [index\_settings](./kibana-plugin-server.deprecationapiresponse.index_settings.md) | IndexSettingsDeprecationInfo | | +| [ml\_settings](./kibana-plugin-server.deprecationapiresponse.ml_settings.md) | DeprecationInfo[] | | +| [node\_settings](./kibana-plugin-server.deprecationapiresponse.node_settings.md) | DeprecationInfo[] | | + diff --git a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.ml_settings.md b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.ml_settings.md index 5a4e273df69a68..ca1a2feaf8ed90 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.ml_settings.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.ml_settings.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) > [ml\_settings](./kibana-plugin-server.deprecationapiresponse.ml_settings.md) - -## DeprecationAPIResponse.ml\_settings property - -Signature: - -```typescript -ml_settings: DeprecationInfo[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) > [ml\_settings](./kibana-plugin-server.deprecationapiresponse.ml_settings.md) + +## DeprecationAPIResponse.ml\_settings property + +Signature: + +```typescript +ml_settings: DeprecationInfo[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.node_settings.md b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.node_settings.md index 5901c49d0edf1d..7c4fd592696561 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.node_settings.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationapiresponse.node_settings.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) > [node\_settings](./kibana-plugin-server.deprecationapiresponse.node_settings.md) - -## DeprecationAPIResponse.node\_settings property - -Signature: - -```typescript -node_settings: DeprecationInfo[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) > [node\_settings](./kibana-plugin-server.deprecationapiresponse.node_settings.md) + +## DeprecationAPIResponse.node\_settings property + +Signature: + +```typescript +node_settings: DeprecationInfo[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationinfo.details.md b/docs/development/core/server/kibana-plugin-server.deprecationinfo.details.md index 17dbeff942255d..6c6913622191e1 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationinfo.details.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationinfo.details.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) > [details](./kibana-plugin-server.deprecationinfo.details.md) - -## DeprecationInfo.details property - -Signature: - -```typescript -details?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) > [details](./kibana-plugin-server.deprecationinfo.details.md) + +## DeprecationInfo.details property + +Signature: + +```typescript +details?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationinfo.level.md b/docs/development/core/server/kibana-plugin-server.deprecationinfo.level.md index 99b629bbbb8cc4..03d3a4149af892 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationinfo.level.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationinfo.level.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) > [level](./kibana-plugin-server.deprecationinfo.level.md) - -## DeprecationInfo.level property - -Signature: - -```typescript -level: MIGRATION_DEPRECATION_LEVEL; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) > [level](./kibana-plugin-server.deprecationinfo.level.md) + +## DeprecationInfo.level property + +Signature: + +```typescript +level: MIGRATION_DEPRECATION_LEVEL; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationinfo.md b/docs/development/core/server/kibana-plugin-server.deprecationinfo.md index c27f5d3404c22c..252eec20d4a90d 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationinfo.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationinfo.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) - -## DeprecationInfo interface - - -Signature: - -```typescript -export interface DeprecationInfo -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [details](./kibana-plugin-server.deprecationinfo.details.md) | string | | -| [level](./kibana-plugin-server.deprecationinfo.level.md) | MIGRATION_DEPRECATION_LEVEL | | -| [message](./kibana-plugin-server.deprecationinfo.message.md) | string | | -| [url](./kibana-plugin-server.deprecationinfo.url.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) + +## DeprecationInfo interface + + +Signature: + +```typescript +export interface DeprecationInfo +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [details](./kibana-plugin-server.deprecationinfo.details.md) | string | | +| [level](./kibana-plugin-server.deprecationinfo.level.md) | MIGRATION_DEPRECATION_LEVEL | | +| [message](./kibana-plugin-server.deprecationinfo.message.md) | string | | +| [url](./kibana-plugin-server.deprecationinfo.url.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.deprecationinfo.message.md b/docs/development/core/server/kibana-plugin-server.deprecationinfo.message.md index f027ac83f3b6e6..84b1bb05ce1a39 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationinfo.message.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationinfo.message.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) > [message](./kibana-plugin-server.deprecationinfo.message.md) - -## DeprecationInfo.message property - -Signature: - -```typescript -message: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) > [message](./kibana-plugin-server.deprecationinfo.message.md) + +## DeprecationInfo.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationinfo.url.md b/docs/development/core/server/kibana-plugin-server.deprecationinfo.url.md index 4fdc9d544b7fff..26a955cb5b24ec 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationinfo.url.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationinfo.url.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) > [url](./kibana-plugin-server.deprecationinfo.url.md) - -## DeprecationInfo.url property - -Signature: - -```typescript -url: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) > [url](./kibana-plugin-server.deprecationinfo.url.md) + +## DeprecationInfo.url property + +Signature: + +```typescript +url: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationsettings.doclinkskey.md b/docs/development/core/server/kibana-plugin-server.deprecationsettings.doclinkskey.md index 4296d0d2299880..c0ef525834e649 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationsettings.doclinkskey.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationsettings.doclinkskey.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationSettings](./kibana-plugin-server.deprecationsettings.md) > [docLinksKey](./kibana-plugin-server.deprecationsettings.doclinkskey.md) - -## DeprecationSettings.docLinksKey property - -Key to documentation links - -Signature: - -```typescript -docLinksKey: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationSettings](./kibana-plugin-server.deprecationsettings.md) > [docLinksKey](./kibana-plugin-server.deprecationsettings.doclinkskey.md) + +## DeprecationSettings.docLinksKey property + +Key to documentation links + +Signature: + +```typescript +docLinksKey: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.deprecationsettings.md b/docs/development/core/server/kibana-plugin-server.deprecationsettings.md index 64a654c1bcea87..3d93902fa7ad48 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationsettings.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationsettings.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationSettings](./kibana-plugin-server.deprecationsettings.md) - -## DeprecationSettings interface - -UiSettings deprecation field options. - -Signature: - -```typescript -export interface DeprecationSettings -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [docLinksKey](./kibana-plugin-server.deprecationsettings.doclinkskey.md) | string | Key to documentation links | -| [message](./kibana-plugin-server.deprecationsettings.message.md) | string | Deprecation message | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationSettings](./kibana-plugin-server.deprecationsettings.md) + +## DeprecationSettings interface + +UiSettings deprecation field options. + +Signature: + +```typescript +export interface DeprecationSettings +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [docLinksKey](./kibana-plugin-server.deprecationsettings.doclinkskey.md) | string | Key to documentation links | +| [message](./kibana-plugin-server.deprecationsettings.message.md) | string | Deprecation message | + diff --git a/docs/development/core/server/kibana-plugin-server.deprecationsettings.message.md b/docs/development/core/server/kibana-plugin-server.deprecationsettings.message.md index ed52929c3551ea..36825160368ebe 100644 --- a/docs/development/core/server/kibana-plugin-server.deprecationsettings.message.md +++ b/docs/development/core/server/kibana-plugin-server.deprecationsettings.message.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationSettings](./kibana-plugin-server.deprecationsettings.md) > [message](./kibana-plugin-server.deprecationsettings.message.md) - -## DeprecationSettings.message property - -Deprecation message - -Signature: - -```typescript -message: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DeprecationSettings](./kibana-plugin-server.deprecationsettings.md) > [message](./kibana-plugin-server.deprecationsettings.message.md) + +## DeprecationSettings.message property + +Deprecation message + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.discoveredplugin.configpath.md b/docs/development/core/server/kibana-plugin-server.discoveredplugin.configpath.md index 4de20b9c6cccfe..d909907c2e1d68 100644 --- a/docs/development/core/server/kibana-plugin-server.discoveredplugin.configpath.md +++ b/docs/development/core/server/kibana-plugin-server.discoveredplugin.configpath.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) > [configPath](./kibana-plugin-server.discoveredplugin.configpath.md) - -## DiscoveredPlugin.configPath property - -Root configuration path used by the plugin, defaults to "id" in snake\_case format. - -Signature: - -```typescript -readonly configPath: ConfigPath; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) > [configPath](./kibana-plugin-server.discoveredplugin.configpath.md) + +## DiscoveredPlugin.configPath property + +Root configuration path used by the plugin, defaults to "id" in snake\_case format. + +Signature: + +```typescript +readonly configPath: ConfigPath; +``` diff --git a/docs/development/core/server/kibana-plugin-server.discoveredplugin.id.md b/docs/development/core/server/kibana-plugin-server.discoveredplugin.id.md index 54287ba69556fd..4de45321d1b589 100644 --- a/docs/development/core/server/kibana-plugin-server.discoveredplugin.id.md +++ b/docs/development/core/server/kibana-plugin-server.discoveredplugin.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) > [id](./kibana-plugin-server.discoveredplugin.id.md) - -## DiscoveredPlugin.id property - -Identifier of the plugin. - -Signature: - -```typescript -readonly id: PluginName; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) > [id](./kibana-plugin-server.discoveredplugin.id.md) + +## DiscoveredPlugin.id property + +Identifier of the plugin. + +Signature: + +```typescript +readonly id: PluginName; +``` diff --git a/docs/development/core/server/kibana-plugin-server.discoveredplugin.md b/docs/development/core/server/kibana-plugin-server.discoveredplugin.md index ea13422458c7fc..98931478da4af3 100644 --- a/docs/development/core/server/kibana-plugin-server.discoveredplugin.md +++ b/docs/development/core/server/kibana-plugin-server.discoveredplugin.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) - -## DiscoveredPlugin interface - -Small container object used to expose information about discovered plugins that may or may not have been started. - -Signature: - -```typescript -export interface DiscoveredPlugin -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [configPath](./kibana-plugin-server.discoveredplugin.configpath.md) | ConfigPath | Root configuration path used by the plugin, defaults to "id" in snake\_case format. | -| [id](./kibana-plugin-server.discoveredplugin.id.md) | PluginName | Identifier of the plugin. | -| [optionalPlugins](./kibana-plugin-server.discoveredplugin.optionalplugins.md) | readonly PluginName[] | An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. | -| [requiredPlugins](./kibana-plugin-server.discoveredplugin.requiredplugins.md) | readonly PluginName[] | An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) + +## DiscoveredPlugin interface + +Small container object used to expose information about discovered plugins that may or may not have been started. + +Signature: + +```typescript +export interface DiscoveredPlugin +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [configPath](./kibana-plugin-server.discoveredplugin.configpath.md) | ConfigPath | Root configuration path used by the plugin, defaults to "id" in snake\_case format. | +| [id](./kibana-plugin-server.discoveredplugin.id.md) | PluginName | Identifier of the plugin. | +| [optionalPlugins](./kibana-plugin-server.discoveredplugin.optionalplugins.md) | readonly PluginName[] | An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. | +| [requiredPlugins](./kibana-plugin-server.discoveredplugin.requiredplugins.md) | readonly PluginName[] | An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. | + diff --git a/docs/development/core/server/kibana-plugin-server.discoveredplugin.optionalplugins.md b/docs/development/core/server/kibana-plugin-server.discoveredplugin.optionalplugins.md index 065b3db6a8b712..9fc91464ced6ad 100644 --- a/docs/development/core/server/kibana-plugin-server.discoveredplugin.optionalplugins.md +++ b/docs/development/core/server/kibana-plugin-server.discoveredplugin.optionalplugins.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) > [optionalPlugins](./kibana-plugin-server.discoveredplugin.optionalplugins.md) - -## DiscoveredPlugin.optionalPlugins property - -An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. - -Signature: - -```typescript -readonly optionalPlugins: readonly PluginName[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) > [optionalPlugins](./kibana-plugin-server.discoveredplugin.optionalplugins.md) + +## DiscoveredPlugin.optionalPlugins property + +An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. + +Signature: + +```typescript +readonly optionalPlugins: readonly PluginName[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.discoveredplugin.requiredplugins.md b/docs/development/core/server/kibana-plugin-server.discoveredplugin.requiredplugins.md index 185675f055ad5a..2bcab0077a1539 100644 --- a/docs/development/core/server/kibana-plugin-server.discoveredplugin.requiredplugins.md +++ b/docs/development/core/server/kibana-plugin-server.discoveredplugin.requiredplugins.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) > [requiredPlugins](./kibana-plugin-server.discoveredplugin.requiredplugins.md) - -## DiscoveredPlugin.requiredPlugins property - -An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. - -Signature: - -```typescript -readonly requiredPlugins: readonly PluginName[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) > [requiredPlugins](./kibana-plugin-server.discoveredplugin.requiredplugins.md) + +## DiscoveredPlugin.requiredPlugins property + +An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. + +Signature: + +```typescript +readonly requiredPlugins: readonly PluginName[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearchclientconfig.md b/docs/development/core/server/kibana-plugin-server.elasticsearchclientconfig.md index 39e6ac428292be..97c01d16464e38 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearchclientconfig.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearchclientconfig.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchClientConfig](./kibana-plugin-server.elasticsearchclientconfig.md) - -## ElasticsearchClientConfig type - - -Signature: - -```typescript -export declare type ElasticsearchClientConfig = Pick & Pick & { - pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; - requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; - sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; - ssl?: Partial; -}; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchClientConfig](./kibana-plugin-server.elasticsearchclientconfig.md) + +## ElasticsearchClientConfig type + + +Signature: + +```typescript +export declare type ElasticsearchClientConfig = Pick & Pick & { + pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; + requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; + sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; + ssl?: Partial; +}; +``` diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearcherror._code_.md b/docs/development/core/server/kibana-plugin-server.elasticsearcherror._code_.md index 72556936db9bea..6d072a6a988245 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearcherror._code_.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearcherror._code_.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) > [\[code\]](./kibana-plugin-server.elasticsearcherror._code_.md) - -## ElasticsearchError.\[code\] property - -Signature: - -```typescript -[code]?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) > [\[code\]](./kibana-plugin-server.elasticsearcherror._code_.md) + +## ElasticsearchError.\[code\] property + +Signature: + +```typescript +[code]?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearcherror.md b/docs/development/core/server/kibana-plugin-server.elasticsearcherror.md index 9d9e21c44760c7..a13fe675303b8d 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearcherror.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearcherror.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) - -## ElasticsearchError interface - - -Signature: - -```typescript -export interface ElasticsearchError extends Boom -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [\[code\]](./kibana-plugin-server.elasticsearcherror._code_.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) + +## ElasticsearchError interface + + +Signature: + +```typescript +export interface ElasticsearchError extends Boom +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [\[code\]](./kibana-plugin-server.elasticsearcherror._code_.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md b/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md index de9223c6883574..75b03ff104a6cd 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-server.elasticsearcherrorhelpers.md) > [decorateNotAuthorizedError](./kibana-plugin-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md) - -## ElasticsearchErrorHelpers.decorateNotAuthorizedError() method - -Signature: - -```typescript -static decorateNotAuthorizedError(error: Error, reason?: string): ElasticsearchError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | | -| reason | string | | - -Returns: - -`ElasticsearchError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-server.elasticsearcherrorhelpers.md) > [decorateNotAuthorizedError](./kibana-plugin-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md) + +## ElasticsearchErrorHelpers.decorateNotAuthorizedError() method + +Signature: + +```typescript +static decorateNotAuthorizedError(error: Error, reason?: string): ElasticsearchError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`ElasticsearchError` + diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.isnotauthorizederror.md b/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.isnotauthorizederror.md index 6d6706ad2e767b..f8ddd13431f208 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.isnotauthorizederror.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.isnotauthorizederror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-server.elasticsearcherrorhelpers.md) > [isNotAuthorizedError](./kibana-plugin-server.elasticsearcherrorhelpers.isnotauthorizederror.md) - -## ElasticsearchErrorHelpers.isNotAuthorizedError() method - -Signature: - -```typescript -static isNotAuthorizedError(error: any): error is ElasticsearchError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | any | | - -Returns: - -`error is ElasticsearchError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-server.elasticsearcherrorhelpers.md) > [isNotAuthorizedError](./kibana-plugin-server.elasticsearcherrorhelpers.isnotauthorizederror.md) + +## ElasticsearchErrorHelpers.isNotAuthorizedError() method + +Signature: + +```typescript +static isNotAuthorizedError(error: any): error is ElasticsearchError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | any | | + +Returns: + +`error is ElasticsearchError` + diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.md b/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.md index 2e615acfeac6b1..fd3e21e32ba216 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearcherrorhelpers.md @@ -1,35 +1,35 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-server.elasticsearcherrorhelpers.md) - -## ElasticsearchErrorHelpers class - -Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as `body.error.header[WWW-Authenticate]` - -Signature: - -```typescript -export declare class ElasticsearchErrorHelpers -``` - -## Example - -Handle errors - -```js -try { - await client.asScoped(request).callAsCurrentUser(...); -} catch (err) { - if (ElasticsearchErrorHelpers.isNotAuthorizedError(err)) { - const authHeader = err.output.headers['WWW-Authenticate']; - } - -``` - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [decorateNotAuthorizedError(error, reason)](./kibana-plugin-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md) | static | | -| [isNotAuthorizedError(error)](./kibana-plugin-server.elasticsearcherrorhelpers.isnotauthorizederror.md) | static | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-server.elasticsearcherrorhelpers.md) + +## ElasticsearchErrorHelpers class + +Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as `body.error.header[WWW-Authenticate]` + +Signature: + +```typescript +export declare class ElasticsearchErrorHelpers +``` + +## Example + +Handle errors + +```js +try { + await client.asScoped(request).callAsCurrentUser(...); +} catch (err) { + if (ElasticsearchErrorHelpers.isNotAuthorizedError(err)) { + const authHeader = err.output.headers['WWW-Authenticate']; + } + +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [decorateNotAuthorizedError(error, reason)](./kibana-plugin-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md) | static | | +| [isNotAuthorizedError(error)](./kibana-plugin-server.elasticsearcherrorhelpers.isnotauthorizederror.md) | static | | + diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.adminclient.md b/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.adminclient.md index 415423f555266d..f9858b44b80ff4 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.adminclient.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.adminclient.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) > [adminClient](./kibana-plugin-server.elasticsearchservicesetup.adminclient.md) - -## ElasticsearchServiceSetup.adminClient property - -A client for the `admin` cluster. All Elasticsearch config value changes are processed under the hood. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). - -Signature: - -```typescript -readonly adminClient: IClusterClient; -``` - -## Example - - -```js -const client = core.elasticsearch.adminClient; - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) > [adminClient](./kibana-plugin-server.elasticsearchservicesetup.adminclient.md) + +## ElasticsearchServiceSetup.adminClient property + +A client for the `admin` cluster. All Elasticsearch config value changes are processed under the hood. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). + +Signature: + +```typescript +readonly adminClient: IClusterClient; +``` + +## Example + + +```js +const client = core.elasticsearch.adminClient; + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.createclient.md b/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.createclient.md index 797f402cc25807..565ef1f7588e8c 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.createclient.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.createclient.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) > [createClient](./kibana-plugin-server.elasticsearchservicesetup.createclient.md) - -## ElasticsearchServiceSetup.createClient property - -Create application specific Elasticsearch cluster API client with customized config. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). - -Signature: - -```typescript -readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; -``` - -## Example - - -```js -const client = elasticsearch.createCluster('my-app-name', config); -const data = await client.callAsInternalUser(); - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) > [createClient](./kibana-plugin-server.elasticsearchservicesetup.createclient.md) + +## ElasticsearchServiceSetup.createClient property + +Create application specific Elasticsearch cluster API client with customized config. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). + +Signature: + +```typescript +readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; +``` + +## Example + + +```js +const client = elasticsearch.createCluster('my-app-name', config); +const data = await client.callAsInternalUser(); + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.dataclient.md b/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.dataclient.md index e9845dce6915d0..60ce859f8c109c 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.dataclient.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.dataclient.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) > [dataClient](./kibana-plugin-server.elasticsearchservicesetup.dataclient.md) - -## ElasticsearchServiceSetup.dataClient property - -A client for the `data` cluster. All Elasticsearch config value changes are processed under the hood. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). - -Signature: - -```typescript -readonly dataClient: IClusterClient; -``` - -## Example - - -```js -const client = core.elasticsearch.dataClient; - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) > [dataClient](./kibana-plugin-server.elasticsearchservicesetup.dataclient.md) + +## ElasticsearchServiceSetup.dataClient property + +A client for the `data` cluster. All Elasticsearch config value changes are processed under the hood. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). + +Signature: + +```typescript +readonly dataClient: IClusterClient; +``` + +## Example + + +```js +const client = core.elasticsearch.dataClient; + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.md b/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.md index 2de3f6e6d1bbca..56221f905cbc1a 100644 --- a/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) - -## ElasticsearchServiceSetup interface - - -Signature: - -```typescript -export interface ElasticsearchServiceSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [adminClient](./kibana-plugin-server.elasticsearchservicesetup.adminclient.md) | IClusterClient | A client for the admin cluster. All Elasticsearch config value changes are processed under the hood. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). | -| [createClient](./kibana-plugin-server.elasticsearchservicesetup.createclient.md) | (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ICustomClusterClient | Create application specific Elasticsearch cluster API client with customized config. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). | -| [dataClient](./kibana-plugin-server.elasticsearchservicesetup.dataclient.md) | IClusterClient | A client for the data cluster. All Elasticsearch config value changes are processed under the hood. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) + +## ElasticsearchServiceSetup interface + + +Signature: + +```typescript +export interface ElasticsearchServiceSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [adminClient](./kibana-plugin-server.elasticsearchservicesetup.adminclient.md) | IClusterClient | A client for the admin cluster. All Elasticsearch config value changes are processed under the hood. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). | +| [createClient](./kibana-plugin-server.elasticsearchservicesetup.createclient.md) | (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ICustomClusterClient | Create application specific Elasticsearch cluster API client with customized config. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). | +| [dataClient](./kibana-plugin-server.elasticsearchservicesetup.dataclient.md) | IClusterClient | A client for the data cluster. All Elasticsearch config value changes are processed under the hood. See [IClusterClient](./kibana-plugin-server.iclusterclient.md). | + diff --git a/docs/development/core/server/kibana-plugin-server.environmentmode.dev.md b/docs/development/core/server/kibana-plugin-server.environmentmode.dev.md index d60fcc58d1b60b..8e40310eeb86d0 100644 --- a/docs/development/core/server/kibana-plugin-server.environmentmode.dev.md +++ b/docs/development/core/server/kibana-plugin-server.environmentmode.dev.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [EnvironmentMode](./kibana-plugin-server.environmentmode.md) > [dev](./kibana-plugin-server.environmentmode.dev.md) - -## EnvironmentMode.dev property - -Signature: - -```typescript -dev: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [EnvironmentMode](./kibana-plugin-server.environmentmode.md) > [dev](./kibana-plugin-server.environmentmode.dev.md) + +## EnvironmentMode.dev property + +Signature: + +```typescript +dev: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.environmentmode.md b/docs/development/core/server/kibana-plugin-server.environmentmode.md index b325f74a0a44fa..89273b15deb011 100644 --- a/docs/development/core/server/kibana-plugin-server.environmentmode.md +++ b/docs/development/core/server/kibana-plugin-server.environmentmode.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [EnvironmentMode](./kibana-plugin-server.environmentmode.md) - -## EnvironmentMode interface - - -Signature: - -```typescript -export interface EnvironmentMode -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [dev](./kibana-plugin-server.environmentmode.dev.md) | boolean | | -| [name](./kibana-plugin-server.environmentmode.name.md) | 'development' | 'production' | | -| [prod](./kibana-plugin-server.environmentmode.prod.md) | boolean | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [EnvironmentMode](./kibana-plugin-server.environmentmode.md) + +## EnvironmentMode interface + + +Signature: + +```typescript +export interface EnvironmentMode +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [dev](./kibana-plugin-server.environmentmode.dev.md) | boolean | | +| [name](./kibana-plugin-server.environmentmode.name.md) | 'development' | 'production' | | +| [prod](./kibana-plugin-server.environmentmode.prod.md) | boolean | | + diff --git a/docs/development/core/server/kibana-plugin-server.environmentmode.name.md b/docs/development/core/server/kibana-plugin-server.environmentmode.name.md index c3243075866f25..9b09be3ef7976c 100644 --- a/docs/development/core/server/kibana-plugin-server.environmentmode.name.md +++ b/docs/development/core/server/kibana-plugin-server.environmentmode.name.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [EnvironmentMode](./kibana-plugin-server.environmentmode.md) > [name](./kibana-plugin-server.environmentmode.name.md) - -## EnvironmentMode.name property - -Signature: - -```typescript -name: 'development' | 'production'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [EnvironmentMode](./kibana-plugin-server.environmentmode.md) > [name](./kibana-plugin-server.environmentmode.name.md) + +## EnvironmentMode.name property + +Signature: + +```typescript +name: 'development' | 'production'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.environmentmode.prod.md b/docs/development/core/server/kibana-plugin-server.environmentmode.prod.md index 86a94775358e9b..60ceef4d408c7c 100644 --- a/docs/development/core/server/kibana-plugin-server.environmentmode.prod.md +++ b/docs/development/core/server/kibana-plugin-server.environmentmode.prod.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [EnvironmentMode](./kibana-plugin-server.environmentmode.md) > [prod](./kibana-plugin-server.environmentmode.prod.md) - -## EnvironmentMode.prod property - -Signature: - -```typescript -prod: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [EnvironmentMode](./kibana-plugin-server.environmentmode.md) > [prod](./kibana-plugin-server.environmentmode.prod.md) + +## EnvironmentMode.prod property + +Signature: + +```typescript +prod: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.body.md b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.body.md index acc800ff4879e3..8e6656512fb0e4 100644 --- a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.body.md +++ b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.body.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) > [body](./kibana-plugin-server.errorhttpresponseoptions.body.md) - -## ErrorHttpResponseOptions.body property - -HTTP message to send to the client - -Signature: - -```typescript -body?: ResponseError; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) > [body](./kibana-plugin-server.errorhttpresponseoptions.body.md) + +## ErrorHttpResponseOptions.body property + +HTTP message to send to the client + +Signature: + +```typescript +body?: ResponseError; +``` diff --git a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.headers.md b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.headers.md index 4bf78f8325c133..df12976995732c 100644 --- a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.headers.md +++ b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.headers.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) > [headers](./kibana-plugin-server.errorhttpresponseoptions.headers.md) - -## ErrorHttpResponseOptions.headers property - -HTTP Headers with additional information about response - -Signature: - -```typescript -headers?: ResponseHeaders; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) > [headers](./kibana-plugin-server.errorhttpresponseoptions.headers.md) + +## ErrorHttpResponseOptions.headers property + +HTTP Headers with additional information about response + +Signature: + +```typescript +headers?: ResponseHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.md b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.md index 9a5c96881f26cf..338f948201b006 100644 --- a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.md +++ b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) - -## ErrorHttpResponseOptions interface - -HTTP response parameters - -Signature: - -```typescript -export interface ErrorHttpResponseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [body](./kibana-plugin-server.errorhttpresponseoptions.body.md) | ResponseError | HTTP message to send to the client | -| [headers](./kibana-plugin-server.errorhttpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) + +## ErrorHttpResponseOptions interface + +HTTP response parameters + +Signature: + +```typescript +export interface ErrorHttpResponseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-server.errorhttpresponseoptions.body.md) | ResponseError | HTTP message to send to the client | +| [headers](./kibana-plugin-server.errorhttpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | + diff --git a/docs/development/core/server/kibana-plugin-server.fakerequest.headers.md b/docs/development/core/server/kibana-plugin-server.fakerequest.headers.md index 14cca9bc02ff8e..a56588a1250d2a 100644 --- a/docs/development/core/server/kibana-plugin-server.fakerequest.headers.md +++ b/docs/development/core/server/kibana-plugin-server.fakerequest.headers.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [FakeRequest](./kibana-plugin-server.fakerequest.md) > [headers](./kibana-plugin-server.fakerequest.headers.md) - -## FakeRequest.headers property - -Headers used for authentication against Elasticsearch - -Signature: - -```typescript -headers: Headers; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [FakeRequest](./kibana-plugin-server.fakerequest.md) > [headers](./kibana-plugin-server.fakerequest.headers.md) + +## FakeRequest.headers property + +Headers used for authentication against Elasticsearch + +Signature: + +```typescript +headers: Headers; +``` diff --git a/docs/development/core/server/kibana-plugin-server.fakerequest.md b/docs/development/core/server/kibana-plugin-server.fakerequest.md index a0ac5733c315bd..3c05e7418919e7 100644 --- a/docs/development/core/server/kibana-plugin-server.fakerequest.md +++ b/docs/development/core/server/kibana-plugin-server.fakerequest.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [FakeRequest](./kibana-plugin-server.fakerequest.md) - -## FakeRequest interface - -Fake request object created manually by Kibana plugins. - -Signature: - -```typescript -export interface FakeRequest -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [headers](./kibana-plugin-server.fakerequest.headers.md) | Headers | Headers used for authentication against Elasticsearch | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [FakeRequest](./kibana-plugin-server.fakerequest.md) + +## FakeRequest interface + +Fake request object created manually by Kibana plugins. + +Signature: + +```typescript +export interface FakeRequest +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [headers](./kibana-plugin-server.fakerequest.headers.md) | Headers | Headers used for authentication against Elasticsearch | + diff --git a/docs/development/core/server/kibana-plugin-server.getauthheaders.md b/docs/development/core/server/kibana-plugin-server.getauthheaders.md index fba8b8ca8ee3a4..c56e2357a8b390 100644 --- a/docs/development/core/server/kibana-plugin-server.getauthheaders.md +++ b/docs/development/core/server/kibana-plugin-server.getauthheaders.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [GetAuthHeaders](./kibana-plugin-server.getauthheaders.md) - -## GetAuthHeaders type - -Get headers to authenticate a user against Elasticsearch. - -Signature: - -```typescript -export declare type GetAuthHeaders = (request: KibanaRequest | LegacyRequest) => AuthHeaders | undefined; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [GetAuthHeaders](./kibana-plugin-server.getauthheaders.md) + +## GetAuthHeaders type + +Get headers to authenticate a user against Elasticsearch. + +Signature: + +```typescript +export declare type GetAuthHeaders = (request: KibanaRequest | LegacyRequest) => AuthHeaders | undefined; +``` diff --git a/docs/development/core/server/kibana-plugin-server.getauthstate.md b/docs/development/core/server/kibana-plugin-server.getauthstate.md index 47fc38c28f5e0a..4e96c776677fb2 100644 --- a/docs/development/core/server/kibana-plugin-server.getauthstate.md +++ b/docs/development/core/server/kibana-plugin-server.getauthstate.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [GetAuthState](./kibana-plugin-server.getauthstate.md) - -## GetAuthState type - -Get authentication state for a request. Returned by `auth` interceptor. - -Signature: - -```typescript -export declare type GetAuthState = (request: KibanaRequest | LegacyRequest) => { - status: AuthStatus; - state: unknown; -}; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [GetAuthState](./kibana-plugin-server.getauthstate.md) + +## GetAuthState type + +Gets authentication state for a request. Returned by `auth` interceptor. + +Signature: + +```typescript +export declare type GetAuthState = (request: KibanaRequest | LegacyRequest) => { + status: AuthStatus; + state: T; +}; +``` diff --git a/docs/development/core/server/kibana-plugin-server.handlercontexttype.md b/docs/development/core/server/kibana-plugin-server.handlercontexttype.md index e8f1f346e8b8e7..cd59c2411cf862 100644 --- a/docs/development/core/server/kibana-plugin-server.handlercontexttype.md +++ b/docs/development/core/server/kibana-plugin-server.handlercontexttype.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerContextType](./kibana-plugin-server.handlercontexttype.md) - -## HandlerContextType type - -Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md) to represent the type of the context. - -Signature: - -```typescript -export declare type HandlerContextType> = T extends HandlerFunction ? U : never; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerContextType](./kibana-plugin-server.handlercontexttype.md) + +## HandlerContextType type + +Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md) to represent the type of the context. + +Signature: + +```typescript +export declare type HandlerContextType> = T extends HandlerFunction ? U : never; +``` diff --git a/docs/development/core/server/kibana-plugin-server.handlerfunction.md b/docs/development/core/server/kibana-plugin-server.handlerfunction.md index 97acd37946fc94..d24f7181d1d29d 100644 --- a/docs/development/core/server/kibana-plugin-server.handlerfunction.md +++ b/docs/development/core/server/kibana-plugin-server.handlerfunction.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerFunction](./kibana-plugin-server.handlerfunction.md) - -## HandlerFunction type - -A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-server.icontextcontainer.md) - -Signature: - -```typescript -export declare type HandlerFunction = (context: T, ...args: any[]) => any; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerFunction](./kibana-plugin-server.handlerfunction.md) + +## HandlerFunction type + +A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-server.icontextcontainer.md) + +Signature: + +```typescript +export declare type HandlerFunction = (context: T, ...args: any[]) => any; +``` diff --git a/docs/development/core/server/kibana-plugin-server.handlerparameters.md b/docs/development/core/server/kibana-plugin-server.handlerparameters.md index 3dd7998a71a1f2..40cc0b37b9251c 100644 --- a/docs/development/core/server/kibana-plugin-server.handlerparameters.md +++ b/docs/development/core/server/kibana-plugin-server.handlerparameters.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerParameters](./kibana-plugin-server.handlerparameters.md) - -## HandlerParameters type - -Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-server.handlercontexttype.md). - -Signature: - -```typescript -export declare type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerParameters](./kibana-plugin-server.handlerparameters.md) + +## HandlerParameters type + +Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-server.handlercontexttype.md). + +Signature: + +```typescript +export declare type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; +``` diff --git a/docs/development/core/server/kibana-plugin-server.headers.md b/docs/development/core/server/kibana-plugin-server.headers.md index cd73d4de43b9db..30798e4bfeb00e 100644 --- a/docs/development/core/server/kibana-plugin-server.headers.md +++ b/docs/development/core/server/kibana-plugin-server.headers.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Headers](./kibana-plugin-server.headers.md) - -## Headers type - -Http request headers to read. - -Signature: - -```typescript -export declare type Headers = { - [header in KnownHeaders]?: string | string[] | undefined; -} & { - [header: string]: string | string[] | undefined; -}; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Headers](./kibana-plugin-server.headers.md) + +## Headers type + +Http request headers to read. + +Signature: + +```typescript +export declare type Headers = { + [header in KnownHeaders]?: string | string[] | undefined; +} & { + [header: string]: string | string[] | undefined; +}; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.body.md b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.body.md index fb663c3c878a71..020c55c2c08749 100644 --- a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.body.md +++ b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.body.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) > [body](./kibana-plugin-server.httpresponseoptions.body.md) - -## HttpResponseOptions.body property - -HTTP message to send to the client - -Signature: - -```typescript -body?: HttpResponsePayload; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) > [body](./kibana-plugin-server.httpresponseoptions.body.md) + +## HttpResponseOptions.body property + +HTTP message to send to the client + +Signature: + +```typescript +body?: HttpResponsePayload; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.headers.md b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.headers.md index ee347f99a41a46..4f66005e881d83 100644 --- a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.headers.md +++ b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.headers.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) > [headers](./kibana-plugin-server.httpresponseoptions.headers.md) - -## HttpResponseOptions.headers property - -HTTP Headers with additional information about response - -Signature: - -```typescript -headers?: ResponseHeaders; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) > [headers](./kibana-plugin-server.httpresponseoptions.headers.md) + +## HttpResponseOptions.headers property + +HTTP Headers with additional information about response + +Signature: + +```typescript +headers?: ResponseHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.md b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.md index aa0e6cc40b861a..c5cbe471f45e6f 100644 --- a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.md +++ b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) - -## HttpResponseOptions interface - -HTTP response parameters - -Signature: - -```typescript -export interface HttpResponseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [body](./kibana-plugin-server.httpresponseoptions.body.md) | HttpResponsePayload | HTTP message to send to the client | -| [headers](./kibana-plugin-server.httpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) + +## HttpResponseOptions interface + +HTTP response parameters + +Signature: + +```typescript +export interface HttpResponseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-server.httpresponseoptions.body.md) | HttpResponsePayload | HTTP message to send to the client | +| [headers](./kibana-plugin-server.httpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | + diff --git a/docs/development/core/server/kibana-plugin-server.httpresponsepayload.md b/docs/development/core/server/kibana-plugin-server.httpresponsepayload.md index 3dc4e2c7956f75..a2a8e28b1f33ee 100644 --- a/docs/development/core/server/kibana-plugin-server.httpresponsepayload.md +++ b/docs/development/core/server/kibana-plugin-server.httpresponsepayload.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponsePayload](./kibana-plugin-server.httpresponsepayload.md) - -## HttpResponsePayload type - -Data send to the client as a response payload. - -Signature: - -```typescript -export declare type HttpResponsePayload = undefined | string | Record | Buffer | Stream; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponsePayload](./kibana-plugin-server.httpresponsepayload.md) + +## HttpResponsePayload type + +Data send to the client as a response payload. + +Signature: + +```typescript +export declare type HttpResponsePayload = undefined | string | Record | Buffer | Stream; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.auth.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.auth.md new file mode 100644 index 00000000000000..4ff7967a6a6431 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.auth.md @@ -0,0 +1,14 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [auth](./kibana-plugin-server.httpservicesetup.auth.md) + +## HttpServiceSetup.auth property + +Signature: + +```typescript +auth: { + get: GetAuthState; + isAuthenticated: IsAuthenticated; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.basepath.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.basepath.md index 61390773bd7262..81221f303b5663 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.basepath.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.basepath.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [basePath](./kibana-plugin-server.httpservicesetup.basepath.md) - -## HttpServiceSetup.basePath property - -Access or manipulate the Kibana base path See [IBasePath](./kibana-plugin-server.ibasepath.md). - -Signature: - -```typescript -basePath: IBasePath; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [basePath](./kibana-plugin-server.httpservicesetup.basepath.md) + +## HttpServiceSetup.basePath property + +Access or manipulate the Kibana base path See [IBasePath](./kibana-plugin-server.ibasepath.md). + +Signature: + +```typescript +basePath: IBasePath; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.createcookiesessionstoragefactory.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.createcookiesessionstoragefactory.md index 4771836bea4773..1aabee9d255b44 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.createcookiesessionstoragefactory.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.createcookiesessionstoragefactory.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [createCookieSessionStorageFactory](./kibana-plugin-server.httpservicesetup.createcookiesessionstoragefactory.md) - -## HttpServiceSetup.createCookieSessionStorageFactory property - -Creates cookie based session storage factory [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) - -Signature: - -```typescript -createCookieSessionStorageFactory: (cookieOptions: SessionStorageCookieOptions) => Promise>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [createCookieSessionStorageFactory](./kibana-plugin-server.httpservicesetup.createcookiesessionstoragefactory.md) + +## HttpServiceSetup.createCookieSessionStorageFactory property + +Creates cookie based session storage factory [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) + +Signature: + +```typescript +createCookieSessionStorageFactory: (cookieOptions: SessionStorageCookieOptions) => Promise>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.createrouter.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.createrouter.md index 71a7fd8fb6a228..ea0850fa01c53e 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.createrouter.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.createrouter.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [createRouter](./kibana-plugin-server.httpservicesetup.createrouter.md) - -## HttpServiceSetup.createRouter property - -Provides ability to declare a handler function for a particular path and HTTP request method. - -Signature: - -```typescript -createRouter: () => IRouter; -``` - -## Remarks - -Each route can have only one handler function, which is executed when the route is matched. See the [IRouter](./kibana-plugin-server.irouter.md) documentation for more information. - -## Example - - -```ts -const router = createRouter(); -// handler is called when '/path' resource is requested with `GET` method -router.get({ path: '/path', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [createRouter](./kibana-plugin-server.httpservicesetup.createrouter.md) + +## HttpServiceSetup.createRouter property + +Provides ability to declare a handler function for a particular path and HTTP request method. + +Signature: + +```typescript +createRouter: () => IRouter; +``` + +## Remarks + +Each route can have only one handler function, which is executed when the route is matched. See the [IRouter](./kibana-plugin-server.irouter.md) documentation for more information. + +## Example + + +```ts +const router = createRouter(); +// handler is called when '/path' resource is requested with `GET` method +router.get({ path: '/path', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.csp.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.csp.md index 7bf83305613eaf..cc1a2ba7136a1d 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.csp.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.csp.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [csp](./kibana-plugin-server.httpservicesetup.csp.md) - -## HttpServiceSetup.csp property - -The CSP config used for Kibana. - -Signature: - -```typescript -csp: ICspConfig; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [csp](./kibana-plugin-server.httpservicesetup.csp.md) + +## HttpServiceSetup.csp property + +The CSP config used for Kibana. + +Signature: + +```typescript +csp: ICspConfig; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.istlsenabled.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.istlsenabled.md index 06a99e8bf30135..2d5a8e9ea791bd 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.istlsenabled.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.istlsenabled.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [isTlsEnabled](./kibana-plugin-server.httpservicesetup.istlsenabled.md) - -## HttpServiceSetup.isTlsEnabled property - -Flag showing whether a server was configured to use TLS connection. - -Signature: - -```typescript -isTlsEnabled: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [isTlsEnabled](./kibana-plugin-server.httpservicesetup.istlsenabled.md) + +## HttpServiceSetup.isTlsEnabled property + +Flag showing whether a server was configured to use TLS connection. + +Signature: + +```typescript +isTlsEnabled: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.md index 3b1993841339df..2a4b0e09977c1c 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.md @@ -1,94 +1,95 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) - -## HttpServiceSetup interface - -Kibana HTTP Service provides own abstraction for work with HTTP stack. Plugins don't have direct access to `hapi` server and its primitives anymore. Moreover, plugins shouldn't rely on the fact that HTTP Service uses one or another library under the hood. This gives the platform flexibility to upgrade or changing our internal HTTP stack without breaking plugins. If the HTTP Service lacks functionality you need, we are happy to discuss and support your needs. - -Signature: - -```typescript -export interface HttpServiceSetup -``` - -## Example - -To handle an incoming request in your plugin you should: - Create a `Router` instance. - -```ts -const router = httpSetup.createRouter(); - -``` -- Use `@kbn/config-schema` package to create a schema to validate the request `params`, `query`, and `body`. Every incoming request will be validated against the created schema. If validation failed, the request is rejected with `400` status and `Bad request` error without calling the route's handler. To opt out of validating the request, specify `false`. - -```ts -import { schema, TypeOf } from '@kbn/config-schema'; -const validate = { - params: schema.object({ - id: schema.string(), - }), -}; - -``` -- Declare a function to respond to incoming request. The function will receive `request` object containing request details: url, headers, matched route, as well as validated `params`, `query`, `body`. And `response` object instructing HTTP server to create HTTP response with information sent back to the client as the response body, headers, and HTTP status. Unlike, `hapi` route handler in the Legacy platform, any exception raised during the handler call will generate `500 Server error` response and log error details for further investigation. See below for returning custom error responses. - -```ts -const handler = async (context: RequestHandlerContext, request: KibanaRequest, response: ResponseFactory) => { - const data = await findObject(request.params.id); - // creates a command to respond with 'not found' error - if (!data) return response.notFound(); - // creates a command to send found data to the client and set response headers - return response.ok({ - body: data, - headers: { - 'content-type': 'application/json' - } - }); -} - -``` -- Register route handler for GET request to 'path/{id}' path - -```ts -import { schema, TypeOf } from '@kbn/config-schema'; -const router = httpSetup.createRouter(); - -const validate = { - params: schema.object({ - id: schema.string(), - }), -}; - -router.get({ - path: 'path/{id}', - validate -}, -async (context, request, response) => { - const data = await findObject(request.params.id); - if (!data) return response.notFound(); - return response.ok({ - body: data, - headers: { - 'content-type': 'application/json' - } - }); -}); - -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [basePath](./kibana-plugin-server.httpservicesetup.basepath.md) | IBasePath | Access or manipulate the Kibana base path See [IBasePath](./kibana-plugin-server.ibasepath.md). | -| [createCookieSessionStorageFactory](./kibana-plugin-server.httpservicesetup.createcookiesessionstoragefactory.md) | <T>(cookieOptions: SessionStorageCookieOptions<T>) => Promise<SessionStorageFactory<T>> | Creates cookie based session storage factory [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) | -| [createRouter](./kibana-plugin-server.httpservicesetup.createrouter.md) | () => IRouter | Provides ability to declare a handler function for a particular path and HTTP request method. | -| [csp](./kibana-plugin-server.httpservicesetup.csp.md) | ICspConfig | The CSP config used for Kibana. | -| [isTlsEnabled](./kibana-plugin-server.httpservicesetup.istlsenabled.md) | boolean | Flag showing whether a server was configured to use TLS connection. | -| [registerAuth](./kibana-plugin-server.httpservicesetup.registerauth.md) | (handler: AuthenticationHandler) => void | To define custom authentication and/or authorization mechanism for incoming requests. | -| [registerOnPostAuth](./kibana-plugin-server.httpservicesetup.registeronpostauth.md) | (handler: OnPostAuthHandler) => void | To define custom logic to perform for incoming requests. | -| [registerOnPreAuth](./kibana-plugin-server.httpservicesetup.registeronpreauth.md) | (handler: OnPreAuthHandler) => void | To define custom logic to perform for incoming requests. | -| [registerOnPreResponse](./kibana-plugin-server.httpservicesetup.registeronpreresponse.md) | (handler: OnPreResponseHandler) => void | To define custom logic to perform for the server response. | -| [registerRouteHandlerContext](./kibana-plugin-server.httpservicesetup.registerroutehandlercontext.md) | <T extends keyof RequestHandlerContext>(contextName: T, provider: RequestHandlerContextProvider<T>) => RequestHandlerContextContainer | Register a context provider for a route handler. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) + +## HttpServiceSetup interface + +Kibana HTTP Service provides own abstraction for work with HTTP stack. Plugins don't have direct access to `hapi` server and its primitives anymore. Moreover, plugins shouldn't rely on the fact that HTTP Service uses one or another library under the hood. This gives the platform flexibility to upgrade or changing our internal HTTP stack without breaking plugins. If the HTTP Service lacks functionality you need, we are happy to discuss and support your needs. + +Signature: + +```typescript +export interface HttpServiceSetup +``` + +## Example + +To handle an incoming request in your plugin you should: - Create a `Router` instance. + +```ts +const router = httpSetup.createRouter(); + +``` +- Use `@kbn/config-schema` package to create a schema to validate the request `params`, `query`, and `body`. Every incoming request will be validated against the created schema. If validation failed, the request is rejected with `400` status and `Bad request` error without calling the route's handler. To opt out of validating the request, specify `false`. + +```ts +import { schema, TypeOf } from '@kbn/config-schema'; +const validate = { + params: schema.object({ + id: schema.string(), + }), +}; + +``` +- Declare a function to respond to incoming request. The function will receive `request` object containing request details: url, headers, matched route, as well as validated `params`, `query`, `body`. And `response` object instructing HTTP server to create HTTP response with information sent back to the client as the response body, headers, and HTTP status. Unlike, `hapi` route handler in the Legacy platform, any exception raised during the handler call will generate `500 Server error` response and log error details for further investigation. See below for returning custom error responses. + +```ts +const handler = async (context: RequestHandlerContext, request: KibanaRequest, response: ResponseFactory) => { + const data = await findObject(request.params.id); + // creates a command to respond with 'not found' error + if (!data) return response.notFound(); + // creates a command to send found data to the client and set response headers + return response.ok({ + body: data, + headers: { + 'content-type': 'application/json' + } + }); +} + +``` +- Register route handler for GET request to 'path/{id}' path + +```ts +import { schema, TypeOf } from '@kbn/config-schema'; +const router = httpSetup.createRouter(); + +const validate = { + params: schema.object({ + id: schema.string(), + }), +}; + +router.get({ + path: 'path/{id}', + validate +}, +async (context, request, response) => { + const data = await findObject(request.params.id); + if (!data) return response.notFound(); + return response.ok({ + body: data, + headers: { + 'content-type': 'application/json' + } + }); +}); + +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [auth](./kibana-plugin-server.httpservicesetup.auth.md) | {
get: GetAuthState;
isAuthenticated: IsAuthenticated;
} | | +| [basePath](./kibana-plugin-server.httpservicesetup.basepath.md) | IBasePath | Access or manipulate the Kibana base path See [IBasePath](./kibana-plugin-server.ibasepath.md). | +| [createCookieSessionStorageFactory](./kibana-plugin-server.httpservicesetup.createcookiesessionstoragefactory.md) | <T>(cookieOptions: SessionStorageCookieOptions<T>) => Promise<SessionStorageFactory<T>> | Creates cookie based session storage factory [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) | +| [createRouter](./kibana-plugin-server.httpservicesetup.createrouter.md) | () => IRouter | Provides ability to declare a handler function for a particular path and HTTP request method. | +| [csp](./kibana-plugin-server.httpservicesetup.csp.md) | ICspConfig | The CSP config used for Kibana. | +| [isTlsEnabled](./kibana-plugin-server.httpservicesetup.istlsenabled.md) | boolean | Flag showing whether a server was configured to use TLS connection. | +| [registerAuth](./kibana-plugin-server.httpservicesetup.registerauth.md) | (handler: AuthenticationHandler) => void | To define custom authentication and/or authorization mechanism for incoming requests. | +| [registerOnPostAuth](./kibana-plugin-server.httpservicesetup.registeronpostauth.md) | (handler: OnPostAuthHandler) => void | To define custom logic to perform for incoming requests. | +| [registerOnPreAuth](./kibana-plugin-server.httpservicesetup.registeronpreauth.md) | (handler: OnPreAuthHandler) => void | To define custom logic to perform for incoming requests. | +| [registerOnPreResponse](./kibana-plugin-server.httpservicesetup.registeronpreresponse.md) | (handler: OnPreResponseHandler) => void | To define custom logic to perform for the server response. | +| [registerRouteHandlerContext](./kibana-plugin-server.httpservicesetup.registerroutehandlercontext.md) | <T extends keyof RequestHandlerContext>(contextName: T, provider: RequestHandlerContextProvider<T>) => RequestHandlerContextContainer | Register a context provider for a route handler. | + diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registerauth.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registerauth.md index be3da1ca1131f5..1258f8e83bafd7 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registerauth.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registerauth.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerAuth](./kibana-plugin-server.httpservicesetup.registerauth.md) - -## HttpServiceSetup.registerAuth property - -To define custom authentication and/or authorization mechanism for incoming requests. - -Signature: - -```typescript -registerAuth: (handler: AuthenticationHandler) => void; -``` - -## Remarks - -A handler should return a state to associate with the incoming request. The state can be retrieved later via http.auth.get(..) Only one AuthenticationHandler can be registered. See [AuthenticationHandler](./kibana-plugin-server.authenticationhandler.md). - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerAuth](./kibana-plugin-server.httpservicesetup.registerauth.md) + +## HttpServiceSetup.registerAuth property + +To define custom authentication and/or authorization mechanism for incoming requests. + +Signature: + +```typescript +registerAuth: (handler: AuthenticationHandler) => void; +``` + +## Remarks + +A handler should return a state to associate with the incoming request. The state can be retrieved later via http.auth.get(..) Only one AuthenticationHandler can be registered. See [AuthenticationHandler](./kibana-plugin-server.authenticationhandler.md). + diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpostauth.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpostauth.md index a3f875c999af14..f1849192919b9a 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpostauth.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpostauth.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerOnPostAuth](./kibana-plugin-server.httpservicesetup.registeronpostauth.md) - -## HttpServiceSetup.registerOnPostAuth property - -To define custom logic to perform for incoming requests. - -Signature: - -```typescript -registerOnPostAuth: (handler: OnPostAuthHandler) => void; -``` - -## Remarks - -Runs the handler after Auth interceptor did make sure a user has access to the requested resource. The auth state is available at stage via http.auth.get(..) Can register any number of registerOnPreAuth, which are called in sequence (from the first registered to the last). See [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md). - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerOnPostAuth](./kibana-plugin-server.httpservicesetup.registeronpostauth.md) + +## HttpServiceSetup.registerOnPostAuth property + +To define custom logic to perform for incoming requests. + +Signature: + +```typescript +registerOnPostAuth: (handler: OnPostAuthHandler) => void; +``` + +## Remarks + +Runs the handler after Auth interceptor did make sure a user has access to the requested resource. The auth state is available at stage via http.auth.get(..) Can register any number of registerOnPreAuth, which are called in sequence (from the first registered to the last). See [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md). + diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpreauth.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpreauth.md index 4c7b688619319b..25462081548e79 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpreauth.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpreauth.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerOnPreAuth](./kibana-plugin-server.httpservicesetup.registeronpreauth.md) - -## HttpServiceSetup.registerOnPreAuth property - -To define custom logic to perform for incoming requests. - -Signature: - -```typescript -registerOnPreAuth: (handler: OnPreAuthHandler) => void; -``` - -## Remarks - -Runs the handler before Auth interceptor performs a check that user has access to requested resources, so it's the only place when you can forward a request to another URL right on the server. Can register any number of registerOnPostAuth, which are called in sequence (from the first registered to the last). See [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md). - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerOnPreAuth](./kibana-plugin-server.httpservicesetup.registeronpreauth.md) + +## HttpServiceSetup.registerOnPreAuth property + +To define custom logic to perform for incoming requests. + +Signature: + +```typescript +registerOnPreAuth: (handler: OnPreAuthHandler) => void; +``` + +## Remarks + +Runs the handler before Auth interceptor performs a check that user has access to requested resources, so it's the only place when you can forward a request to another URL right on the server. Can register any number of registerOnPostAuth, which are called in sequence (from the first registered to the last). See [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md). + diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpreresponse.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpreresponse.md index 9f0eaae8830e10..25248066cbc256 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpreresponse.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registeronpreresponse.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerOnPreResponse](./kibana-plugin-server.httpservicesetup.registeronpreresponse.md) - -## HttpServiceSetup.registerOnPreResponse property - -To define custom logic to perform for the server response. - -Signature: - -```typescript -registerOnPreResponse: (handler: OnPreResponseHandler) => void; -``` - -## Remarks - -Doesn't provide the whole response object. Supports extending response with custom headers. See [OnPreResponseHandler](./kibana-plugin-server.onpreresponsehandler.md). - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerOnPreResponse](./kibana-plugin-server.httpservicesetup.registeronpreresponse.md) + +## HttpServiceSetup.registerOnPreResponse property + +To define custom logic to perform for the server response. + +Signature: + +```typescript +registerOnPreResponse: (handler: OnPreResponseHandler) => void; +``` + +## Remarks + +Doesn't provide the whole response object. Supports extending response with custom headers. See [OnPreResponseHandler](./kibana-plugin-server.onpreresponsehandler.md). + diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registerroutehandlercontext.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registerroutehandlercontext.md index 339f2eb329c7b9..69358cbf975bc5 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.registerroutehandlercontext.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.registerroutehandlercontext.md @@ -1,37 +1,37 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerRouteHandlerContext](./kibana-plugin-server.httpservicesetup.registerroutehandlercontext.md) - -## HttpServiceSetup.registerRouteHandlerContext property - -Register a context provider for a route handler. - -Signature: - -```typescript -registerRouteHandlerContext: (contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; -``` - -## Example - - -```ts - // my-plugin.ts - deps.http.registerRouteHandlerContext( - 'myApp', - (context, req) => { - async function search (id: string) { - return await context.elasticsearch.adminClient.callAsInternalUser('endpoint', id); - } - return { search }; - } - ); - -// my-route-handler.ts - router.get({ path: '/', validate: false }, async (context, req, res) => { - const response = await context.myApp.search(...); - return res.ok(response); - }); - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) > [registerRouteHandlerContext](./kibana-plugin-server.httpservicesetup.registerroutehandlercontext.md) + +## HttpServiceSetup.registerRouteHandlerContext property + +Register a context provider for a route handler. + +Signature: + +```typescript +registerRouteHandlerContext: (contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; +``` + +## Example + + +```ts + // my-plugin.ts + deps.http.registerRouteHandlerContext( + 'myApp', + (context, req) => { + async function search (id: string) { + return await context.elasticsearch.adminClient.callAsInternalUser('endpoint', id); + } + return { search }; + } + ); + +// my-route-handler.ts + router.get({ path: '/', validate: false }, async (context, req, res) => { + const response = await context.myApp.search(...); + return res.ok(response); + }); + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.httpservicestart.islistening.md b/docs/development/core/server/kibana-plugin-server.httpservicestart.islistening.md index 2818d6ead2c23b..2453a6abd2d22c 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicestart.islistening.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicestart.islistening.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) > [isListening](./kibana-plugin-server.httpservicestart.islistening.md) - -## HttpServiceStart.isListening property - -Indicates if http server is listening on a given port - -Signature: - -```typescript -isListening: (port: number) => boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) > [isListening](./kibana-plugin-server.httpservicestart.islistening.md) + +## HttpServiceStart.isListening property + +Indicates if http server is listening on a given port + +Signature: + +```typescript +isListening: (port: number) => boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpservicestart.md b/docs/development/core/server/kibana-plugin-server.httpservicestart.md index 2c9c4c8408f6b2..47d6a4d146686e 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicestart.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicestart.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) - -## HttpServiceStart interface - - -Signature: - -```typescript -export interface HttpServiceStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [isListening](./kibana-plugin-server.httpservicestart.islistening.md) | (port: number) => boolean | Indicates if http server is listening on a given port | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) + +## HttpServiceStart interface + + +Signature: + +```typescript +export interface HttpServiceStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [isListening](./kibana-plugin-server.httpservicestart.islistening.md) | (port: number) => boolean | Indicates if http server is listening on a given port | + diff --git a/docs/development/core/server/kibana-plugin-server.ibasepath.md b/docs/development/core/server/kibana-plugin-server.ibasepath.md index 2baa8d623ce97b..d2779a49d3e213 100644 --- a/docs/development/core/server/kibana-plugin-server.ibasepath.md +++ b/docs/development/core/server/kibana-plugin-server.ibasepath.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IBasePath](./kibana-plugin-server.ibasepath.md) - -## IBasePath type - -Access or manipulate the Kibana base path - -[BasePath](./kibana-plugin-server.basepath.md) - -Signature: - -```typescript -export declare type IBasePath = Pick; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IBasePath](./kibana-plugin-server.ibasepath.md) + +## IBasePath type + +Access or manipulate the Kibana base path + +[BasePath](./kibana-plugin-server.basepath.md) + +Signature: + +```typescript +export declare type IBasePath = Pick; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iclusterclient.md b/docs/development/core/server/kibana-plugin-server.iclusterclient.md index e7435a9d91a74d..a78ebb1400fddd 100644 --- a/docs/development/core/server/kibana-plugin-server.iclusterclient.md +++ b/docs/development/core/server/kibana-plugin-server.iclusterclient.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IClusterClient](./kibana-plugin-server.iclusterclient.md) - -## IClusterClient type - -Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). - -See [ClusterClient](./kibana-plugin-server.clusterclient.md). - -Signature: - -```typescript -export declare type IClusterClient = Pick; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IClusterClient](./kibana-plugin-server.iclusterclient.md) + +## IClusterClient type + +Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). + +See [ClusterClient](./kibana-plugin-server.clusterclient.md). + +Signature: + +```typescript +export declare type IClusterClient = Pick; +``` diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md index 09a9e28d6d0fe8..7bc18e819ae44c 100644 --- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) > [createHandler](./kibana-plugin-server.icontextcontainer.createhandler.md) - -## IContextContainer.createHandler() method - -Create a new handler function pre-wired to context for the plugin. - -Signature: - -```typescript -createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. | -| handler | THandler | Handler function to pass context object to. | - -Returns: - -`(...rest: HandlerParameters) => ShallowPromise>` - -A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) > [createHandler](./kibana-plugin-server.icontextcontainer.createhandler.md) + +## IContextContainer.createHandler() method + +Create a new handler function pre-wired to context for the plugin. + +Signature: + +```typescript +createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. | +| handler | THandler | Handler function to pass context object to. | + +Returns: + +`(...rest: HandlerParameters) => ShallowPromise>` + +A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. + diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.md index 8235c401315363..b54b84070b1f8b 100644 --- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.md @@ -1,80 +1,80 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) - -## IContextContainer interface - -An object that handles registration of context providers and configuring handlers with context. - -Signature: - -```typescript -export interface IContextContainer> -``` - -## Remarks - -A [IContextContainer](./kibana-plugin-server.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. - -Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. - -In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-server.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. - -When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. - -```ts -// Correct -class MyPlugin { - private readonly handlers = new Map(); - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - return { - registerContext(pluginOpaqueId, contextName, provider) { - this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); - }, - registerRoute(pluginOpaqueId, path, handler) { - this.handlers.set( - path, - this.contextContainer.createHandler(pluginOpaqueId, handler) - ); - } - } - } -} - -// Incorrect -class MyPlugin { - private readonly handlers = new Map(); - - constructor(private readonly initContext: PluginInitializerContext) {} - - setup(core) { - this.contextContainer = core.context.createContextContainer(); - return { - registerContext(contextName, provider) { - // BUG! - // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. - this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); - }, - registerRoute(path, handler) { - this.handlers.set( - path, - // BUG! - // This handler will not receive any contexts provided by other dependencies of the calling plugin. - this.contextContainer.createHandler(this.initContext.opaqueId, handler) - ); - } - } - } -} - -``` - -## Methods - -| Method | Description | -| --- | --- | -| [createHandler(pluginOpaqueId, handler)](./kibana-plugin-server.icontextcontainer.createhandler.md) | Create a new handler function pre-wired to context for the plugin. | -| [registerContext(pluginOpaqueId, contextName, provider)](./kibana-plugin-server.icontextcontainer.registercontext.md) | Register a new context provider. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) + +## IContextContainer interface + +An object that handles registration of context providers and configuring handlers with context. + +Signature: + +```typescript +export interface IContextContainer> +``` + +## Remarks + +A [IContextContainer](./kibana-plugin-server.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. + +Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. + +In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-server.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. + +When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. + +```ts +// Correct +class MyPlugin { + private readonly handlers = new Map(); + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(pluginOpaqueId, contextName, provider) { + this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); + }, + registerRoute(pluginOpaqueId, path, handler) { + this.handlers.set( + path, + this.contextContainer.createHandler(pluginOpaqueId, handler) + ); + } + } + } +} + +// Incorrect +class MyPlugin { + private readonly handlers = new Map(); + + constructor(private readonly initContext: PluginInitializerContext) {} + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(contextName, provider) { + // BUG! + // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. + this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); + }, + registerRoute(path, handler) { + this.handlers.set( + path, + // BUG! + // This handler will not receive any contexts provided by other dependencies of the calling plugin. + this.contextContainer.createHandler(this.initContext.opaqueId, handler) + ); + } + } + } +} + +``` + +## Methods + +| Method | Description | +| --- | --- | +| [createHandler(pluginOpaqueId, handler)](./kibana-plugin-server.icontextcontainer.createhandler.md) | Create a new handler function pre-wired to context for the plugin. | +| [registerContext(pluginOpaqueId, contextName, provider)](./kibana-plugin-server.icontextcontainer.registercontext.md) | Register a new context provider. | + diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md index 30d3fc154d1e93..ee2cffdf155a73 100644 --- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md @@ -1,34 +1,34 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) > [registerContext](./kibana-plugin-server.icontextcontainer.registercontext.md) - -## IContextContainer.registerContext() method - -Register a new context provider. - -Signature: - -```typescript -registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this context. | -| contextName | TContextName | The key of the TContext object this provider supplies the value for. | -| provider | IContextProvider<THandler, TContextName> | A [IContextProvider](./kibana-plugin-server.icontextprovider.md) to be called each time a new context is created. | - -Returns: - -`this` - -The [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for method chaining. - -## Remarks - -The value (or resolved Promise value) returned by the `provider` function will be attached to the context object on the key specified by `contextName`. - -Throws an exception if more than one provider is registered for the same `contextName`. - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) > [registerContext](./kibana-plugin-server.icontextcontainer.registercontext.md) + +## IContextContainer.registerContext() method + +Register a new context provider. + +Signature: + +```typescript +registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this context. | +| contextName | TContextName | The key of the TContext object this provider supplies the value for. | +| provider | IContextProvider<THandler, TContextName> | A [IContextProvider](./kibana-plugin-server.icontextprovider.md) to be called each time a new context is created. | + +Returns: + +`this` + +The [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for method chaining. + +## Remarks + +The value (or resolved Promise value) returned by the `provider` function will be attached to the context object on the key specified by `contextName`. + +Throws an exception if more than one provider is registered for the same `contextName`. + diff --git a/docs/development/core/server/kibana-plugin-server.icontextprovider.md b/docs/development/core/server/kibana-plugin-server.icontextprovider.md index 39ace8b9bc57ee..63c4e1a0f9acf9 100644 --- a/docs/development/core/server/kibana-plugin-server.icontextprovider.md +++ b/docs/development/core/server/kibana-plugin-server.icontextprovider.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextProvider](./kibana-plugin-server.icontextprovider.md) - -## IContextProvider type - -A function that returns a context value for a specific key of given context type. - -Signature: - -```typescript -export declare type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName]; -``` - -## Remarks - -This function will be called each time a new context is built for a handler invocation. - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextProvider](./kibana-plugin-server.icontextprovider.md) + +## IContextProvider type + +A function that returns a context value for a specific key of given context type. + +Signature: + +```typescript +export declare type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName]; +``` + +## Remarks + +This function will be called each time a new context is built for a handler invocation. + diff --git a/docs/development/core/server/kibana-plugin-server.icspconfig.header.md b/docs/development/core/server/kibana-plugin-server.icspconfig.header.md index d757863fdc12da..444b79b86eb937 100644 --- a/docs/development/core/server/kibana-plugin-server.icspconfig.header.md +++ b/docs/development/core/server/kibana-plugin-server.icspconfig.header.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) > [header](./kibana-plugin-server.icspconfig.header.md) - -## ICspConfig.header property - -The CSP rules in a formatted directives string for use in a `Content-Security-Policy` header. - -Signature: - -```typescript -readonly header: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) > [header](./kibana-plugin-server.icspconfig.header.md) + +## ICspConfig.header property + +The CSP rules in a formatted directives string for use in a `Content-Security-Policy` header. + +Signature: + +```typescript +readonly header: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.icspconfig.md b/docs/development/core/server/kibana-plugin-server.icspconfig.md index fb8188386a3766..5d14c20bd8973d 100644 --- a/docs/development/core/server/kibana-plugin-server.icspconfig.md +++ b/docs/development/core/server/kibana-plugin-server.icspconfig.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) - -## ICspConfig interface - -CSP configuration for use in Kibana. - -Signature: - -```typescript -export interface ICspConfig -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [header](./kibana-plugin-server.icspconfig.header.md) | string | The CSP rules in a formatted directives string for use in a Content-Security-Policy header. | -| [rules](./kibana-plugin-server.icspconfig.rules.md) | string[] | The CSP rules used for Kibana. | -| [strict](./kibana-plugin-server.icspconfig.strict.md) | boolean | Specify whether browsers that do not support CSP should be able to use Kibana. Use true to block and false to allow. | -| [warnLegacyBrowsers](./kibana-plugin-server.icspconfig.warnlegacybrowsers.md) | boolean | Specify whether users with legacy browsers should be warned about their lack of Kibana security compliance. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) + +## ICspConfig interface + +CSP configuration for use in Kibana. + +Signature: + +```typescript +export interface ICspConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [header](./kibana-plugin-server.icspconfig.header.md) | string | The CSP rules in a formatted directives string for use in a Content-Security-Policy header. | +| [rules](./kibana-plugin-server.icspconfig.rules.md) | string[] | The CSP rules used for Kibana. | +| [strict](./kibana-plugin-server.icspconfig.strict.md) | boolean | Specify whether browsers that do not support CSP should be able to use Kibana. Use true to block and false to allow. | +| [warnLegacyBrowsers](./kibana-plugin-server.icspconfig.warnlegacybrowsers.md) | boolean | Specify whether users with legacy browsers should be warned about their lack of Kibana security compliance. | + diff --git a/docs/development/core/server/kibana-plugin-server.icspconfig.rules.md b/docs/development/core/server/kibana-plugin-server.icspconfig.rules.md index 6216e6d8171360..04276e2148a795 100644 --- a/docs/development/core/server/kibana-plugin-server.icspconfig.rules.md +++ b/docs/development/core/server/kibana-plugin-server.icspconfig.rules.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) > [rules](./kibana-plugin-server.icspconfig.rules.md) - -## ICspConfig.rules property - -The CSP rules used for Kibana. - -Signature: - -```typescript -readonly rules: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) > [rules](./kibana-plugin-server.icspconfig.rules.md) + +## ICspConfig.rules property + +The CSP rules used for Kibana. + +Signature: + +```typescript +readonly rules: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.icspconfig.strict.md b/docs/development/core/server/kibana-plugin-server.icspconfig.strict.md index 4ab97ad9f665a6..88b25d9c7ea845 100644 --- a/docs/development/core/server/kibana-plugin-server.icspconfig.strict.md +++ b/docs/development/core/server/kibana-plugin-server.icspconfig.strict.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) > [strict](./kibana-plugin-server.icspconfig.strict.md) - -## ICspConfig.strict property - -Specify whether browsers that do not support CSP should be able to use Kibana. Use `true` to block and `false` to allow. - -Signature: - -```typescript -readonly strict: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) > [strict](./kibana-plugin-server.icspconfig.strict.md) + +## ICspConfig.strict property + +Specify whether browsers that do not support CSP should be able to use Kibana. Use `true` to block and `false` to allow. + +Signature: + +```typescript +readonly strict: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.icspconfig.warnlegacybrowsers.md b/docs/development/core/server/kibana-plugin-server.icspconfig.warnlegacybrowsers.md index aea35f05694483..b6cd70a7c16e58 100644 --- a/docs/development/core/server/kibana-plugin-server.icspconfig.warnlegacybrowsers.md +++ b/docs/development/core/server/kibana-plugin-server.icspconfig.warnlegacybrowsers.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) > [warnLegacyBrowsers](./kibana-plugin-server.icspconfig.warnlegacybrowsers.md) - -## ICspConfig.warnLegacyBrowsers property - -Specify whether users with legacy browsers should be warned about their lack of Kibana security compliance. - -Signature: - -```typescript -readonly warnLegacyBrowsers: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICspConfig](./kibana-plugin-server.icspconfig.md) > [warnLegacyBrowsers](./kibana-plugin-server.icspconfig.warnlegacybrowsers.md) + +## ICspConfig.warnLegacyBrowsers property + +Specify whether users with legacy browsers should be warned about their lack of Kibana security compliance. + +Signature: + +```typescript +readonly warnLegacyBrowsers: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.icustomclusterclient.md b/docs/development/core/server/kibana-plugin-server.icustomclusterclient.md index d7511a119fc0ff..888d4a1aa34545 100644 --- a/docs/development/core/server/kibana-plugin-server.icustomclusterclient.md +++ b/docs/development/core/server/kibana-plugin-server.icustomclusterclient.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICustomClusterClient](./kibana-plugin-server.icustomclusterclient.md) - -## ICustomClusterClient type - -Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). - -See [ClusterClient](./kibana-plugin-server.clusterclient.md). - -Signature: - -```typescript -export declare type ICustomClusterClient = Pick; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ICustomClusterClient](./kibana-plugin-server.icustomclusterclient.md) + +## ICustomClusterClient type + +Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). + +See [ClusterClient](./kibana-plugin-server.clusterclient.md). + +Signature: + +```typescript +export declare type ICustomClusterClient = Pick; +``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanaresponse.md b/docs/development/core/server/kibana-plugin-server.ikibanaresponse.md index 4971d6eb97a284..6c1ded748cf548 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanaresponse.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanaresponse.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) - -## IKibanaResponse interface - -A response data object, expected to returned as a result of [RequestHandler](./kibana-plugin-server.requesthandler.md) execution - -Signature: - -```typescript -export interface IKibanaResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [options](./kibana-plugin-server.ikibanaresponse.options.md) | HttpResponseOptions | | -| [payload](./kibana-plugin-server.ikibanaresponse.payload.md) | T | | -| [status](./kibana-plugin-server.ikibanaresponse.status.md) | number | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) + +## IKibanaResponse interface + +A response data object, expected to returned as a result of [RequestHandler](./kibana-plugin-server.requesthandler.md) execution + +Signature: + +```typescript +export interface IKibanaResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [options](./kibana-plugin-server.ikibanaresponse.options.md) | HttpResponseOptions | | +| [payload](./kibana-plugin-server.ikibanaresponse.payload.md) | T | | +| [status](./kibana-plugin-server.ikibanaresponse.status.md) | number | | + diff --git a/docs/development/core/server/kibana-plugin-server.ikibanaresponse.options.md b/docs/development/core/server/kibana-plugin-server.ikibanaresponse.options.md index 988d873c088feb..0d14a4ac2d8734 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanaresponse.options.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanaresponse.options.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) > [options](./kibana-plugin-server.ikibanaresponse.options.md) - -## IKibanaResponse.options property - -Signature: - -```typescript -readonly options: HttpResponseOptions; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) > [options](./kibana-plugin-server.ikibanaresponse.options.md) + +## IKibanaResponse.options property + +Signature: + +```typescript +readonly options: HttpResponseOptions; +``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanaresponse.payload.md b/docs/development/core/server/kibana-plugin-server.ikibanaresponse.payload.md index f1d10c5d22a429..8285a68e7780b8 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanaresponse.payload.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanaresponse.payload.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) > [payload](./kibana-plugin-server.ikibanaresponse.payload.md) - -## IKibanaResponse.payload property - -Signature: - -```typescript -readonly payload?: T; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) > [payload](./kibana-plugin-server.ikibanaresponse.payload.md) + +## IKibanaResponse.payload property + +Signature: + +```typescript +readonly payload?: T; +``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanaresponse.status.md b/docs/development/core/server/kibana-plugin-server.ikibanaresponse.status.md index b766ff66c357fe..5ffc8330aadf97 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanaresponse.status.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanaresponse.status.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) > [status](./kibana-plugin-server.ikibanaresponse.status.md) - -## IKibanaResponse.status property - -Signature: - -```typescript -readonly status: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) > [status](./kibana-plugin-server.ikibanaresponse.status.md) + +## IKibanaResponse.status property + +Signature: + +```typescript +readonly status: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorizationerror.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorizationerror.md index 0629b8e2b9ade8..aa1d72f5f104c1 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorizationerror.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorizationerror.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [authorizationError](./kibana-plugin-server.ikibanasocket.authorizationerror.md) - -## IKibanaSocket.authorizationError property - -The reason why the peer's certificate has not been verified. This property becomes available only when `authorized` is `false`. - -Signature: - -```typescript -readonly authorizationError?: Error; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [authorizationError](./kibana-plugin-server.ikibanasocket.authorizationerror.md) + +## IKibanaSocket.authorizationError property + +The reason why the peer's certificate has not been verified. This property becomes available only when `authorized` is `false`. + +Signature: + +```typescript +readonly authorizationError?: Error; +``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorized.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorized.md index abb68f8e8f0e0a..8cd608e4ea6118 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorized.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorized.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [authorized](./kibana-plugin-server.ikibanasocket.authorized.md) - -## IKibanaSocket.authorized property - -Indicates whether or not the peer certificate was signed by one of the specified CAs. When TLS isn't used the value is `undefined`. - -Signature: - -```typescript -readonly authorized?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [authorized](./kibana-plugin-server.ikibanasocket.authorized.md) + +## IKibanaSocket.authorized property + +Indicates whether or not the peer certificate was signed by one of the specified CAs. When TLS isn't used the value is `undefined`. + +Signature: + +```typescript +readonly authorized?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate.md index 8bd8f900579eab..e1b07393cd92d9 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [getPeerCertificate](./kibana-plugin-server.ikibanasocket.getpeercertificate.md) - -## IKibanaSocket.getPeerCertificate() method - -Signature: - -```typescript -getPeerCertificate(detailed: true): DetailedPeerCertificate | null; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| detailed | true | | - -Returns: - -`DetailedPeerCertificate | null` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [getPeerCertificate](./kibana-plugin-server.ikibanasocket.getpeercertificate.md) + +## IKibanaSocket.getPeerCertificate() method + +Signature: + +```typescript +getPeerCertificate(detailed: true): DetailedPeerCertificate | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| detailed | true | | + +Returns: + +`DetailedPeerCertificate | null` + diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate_1.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate_1.md index 5ac763032e72bf..90e02fd5c53bb1 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate_1.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate_1.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [getPeerCertificate](./kibana-plugin-server.ikibanasocket.getpeercertificate_1.md) - -## IKibanaSocket.getPeerCertificate() method - -Signature: - -```typescript -getPeerCertificate(detailed: false): PeerCertificate | null; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| detailed | false | | - -Returns: - -`PeerCertificate | null` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [getPeerCertificate](./kibana-plugin-server.ikibanasocket.getpeercertificate_1.md) + +## IKibanaSocket.getPeerCertificate() method + +Signature: + +```typescript +getPeerCertificate(detailed: false): PeerCertificate | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| detailed | false | | + +Returns: + +`PeerCertificate | null` + diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate_2.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate_2.md index 19d2dc137d2573..20a99d1639fdd9 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate_2.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.getpeercertificate_2.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [getPeerCertificate](./kibana-plugin-server.ikibanasocket.getpeercertificate_2.md) - -## IKibanaSocket.getPeerCertificate() method - -Returns an object representing the peer's certificate. The returned object has some properties corresponding to the field of the certificate. If detailed argument is true the full chain with issuer property will be returned, if false only the top certificate without issuer property. If the peer does not provide a certificate, it returns null. - -Signature: - -```typescript -getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate | null; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| detailed | boolean | If true; the full chain with issuer property will be returned. | - -Returns: - -`PeerCertificate | DetailedPeerCertificate | null` - -An object representing the peer's certificate. - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [getPeerCertificate](./kibana-plugin-server.ikibanasocket.getpeercertificate_2.md) + +## IKibanaSocket.getPeerCertificate() method + +Returns an object representing the peer's certificate. The returned object has some properties corresponding to the field of the certificate. If detailed argument is true the full chain with issuer property will be returned, if false only the top certificate without issuer property. If the peer does not provide a certificate, it returns null. + +Signature: + +```typescript +getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| detailed | boolean | If true; the full chain with issuer property will be returned. | + +Returns: + +`PeerCertificate | DetailedPeerCertificate | null` + +An object representing the peer's certificate. + diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.md index 2718111fb0fb3f..d69e194d2246b9 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanasocket.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.md @@ -1,29 +1,29 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) - -## IKibanaSocket interface - -A tiny abstraction for TCP socket. - -Signature: - -```typescript -export interface IKibanaSocket -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [authorizationError](./kibana-plugin-server.ikibanasocket.authorizationerror.md) | Error | The reason why the peer's certificate has not been verified. This property becomes available only when authorized is false. | -| [authorized](./kibana-plugin-server.ikibanasocket.authorized.md) | boolean | Indicates whether or not the peer certificate was signed by one of the specified CAs. When TLS isn't used the value is undefined. | - -## Methods - -| Method | Description | -| --- | --- | -| [getPeerCertificate(detailed)](./kibana-plugin-server.ikibanasocket.getpeercertificate.md) | | -| [getPeerCertificate(detailed)](./kibana-plugin-server.ikibanasocket.getpeercertificate_1.md) | | -| [getPeerCertificate(detailed)](./kibana-plugin-server.ikibanasocket.getpeercertificate_2.md) | Returns an object representing the peer's certificate. The returned object has some properties corresponding to the field of the certificate. If detailed argument is true the full chain with issuer property will be returned, if false only the top certificate without issuer property. If the peer does not provide a certificate, it returns null. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) + +## IKibanaSocket interface + +A tiny abstraction for TCP socket. + +Signature: + +```typescript +export interface IKibanaSocket +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [authorizationError](./kibana-plugin-server.ikibanasocket.authorizationerror.md) | Error | The reason why the peer's certificate has not been verified. This property becomes available only when authorized is false. | +| [authorized](./kibana-plugin-server.ikibanasocket.authorized.md) | boolean | Indicates whether or not the peer certificate was signed by one of the specified CAs. When TLS isn't used the value is undefined. | + +## Methods + +| Method | Description | +| --- | --- | +| [getPeerCertificate(detailed)](./kibana-plugin-server.ikibanasocket.getpeercertificate.md) | | +| [getPeerCertificate(detailed)](./kibana-plugin-server.ikibanasocket.getpeercertificate_1.md) | | +| [getPeerCertificate(detailed)](./kibana-plugin-server.ikibanasocket.getpeercertificate_2.md) | Returns an object representing the peer's certificate. The returned object has some properties corresponding to the field of the certificate. If detailed argument is true the full chain with issuer property will be returned, if false only the top certificate without issuer property. If the peer does not provide a certificate, it returns null. | + diff --git a/docs/development/core/server/kibana-plugin-server.imagevalidation.maxsize.md b/docs/development/core/server/kibana-plugin-server.imagevalidation.maxsize.md index 9b03924ad2e0fd..058c9f61c206b0 100644 --- a/docs/development/core/server/kibana-plugin-server.imagevalidation.maxsize.md +++ b/docs/development/core/server/kibana-plugin-server.imagevalidation.maxsize.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ImageValidation](./kibana-plugin-server.imagevalidation.md) > [maxSize](./kibana-plugin-server.imagevalidation.maxsize.md) - -## ImageValidation.maxSize property - -Signature: - -```typescript -maxSize: { - length: number; - description: string; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ImageValidation](./kibana-plugin-server.imagevalidation.md) > [maxSize](./kibana-plugin-server.imagevalidation.maxsize.md) + +## ImageValidation.maxSize property + +Signature: + +```typescript +maxSize: { + length: number; + description: string; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.imagevalidation.md b/docs/development/core/server/kibana-plugin-server.imagevalidation.md index 8d81a7eae19156..cd39b6ef4e7960 100644 --- a/docs/development/core/server/kibana-plugin-server.imagevalidation.md +++ b/docs/development/core/server/kibana-plugin-server.imagevalidation.md @@ -1,18 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ImageValidation](./kibana-plugin-server.imagevalidation.md) - -## ImageValidation interface - -Signature: - -```typescript -export interface ImageValidation -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [maxSize](./kibana-plugin-server.imagevalidation.maxsize.md) | {
length: number;
description: string;
} | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ImageValidation](./kibana-plugin-server.imagevalidation.md) + +## ImageValidation interface + + +Signature: + +```typescript +export interface ImageValidation +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [maxSize](./kibana-plugin-server.imagevalidation.maxsize.md) | {
length: number;
description: string;
} | | + diff --git a/docs/development/core/server/kibana-plugin-server.indexsettingsdeprecationinfo.md b/docs/development/core/server/kibana-plugin-server.indexsettingsdeprecationinfo.md index 66b15e532e2adb..800f9c42984261 100644 --- a/docs/development/core/server/kibana-plugin-server.indexsettingsdeprecationinfo.md +++ b/docs/development/core/server/kibana-plugin-server.indexsettingsdeprecationinfo.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IndexSettingsDeprecationInfo](./kibana-plugin-server.indexsettingsdeprecationinfo.md) - -## IndexSettingsDeprecationInfo interface - - -Signature: - -```typescript -export interface IndexSettingsDeprecationInfo -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IndexSettingsDeprecationInfo](./kibana-plugin-server.indexsettingsdeprecationinfo.md) + +## IndexSettingsDeprecationInfo interface + + +Signature: + +```typescript +export interface IndexSettingsDeprecationInfo +``` diff --git a/docs/development/core/server/kibana-plugin-server.irenderoptions.includeusersettings.md b/docs/development/core/server/kibana-plugin-server.irenderoptions.includeusersettings.md index cedf3d27d0887d..a3ae5724b18544 100644 --- a/docs/development/core/server/kibana-plugin-server.irenderoptions.includeusersettings.md +++ b/docs/development/core/server/kibana-plugin-server.irenderoptions.includeusersettings.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRenderOptions](./kibana-plugin-server.irenderoptions.md) > [includeUserSettings](./kibana-plugin-server.irenderoptions.includeusersettings.md) - -## IRenderOptions.includeUserSettings property - -Set whether to output user settings in the page metadata. `true` by default. - -Signature: - -```typescript -includeUserSettings?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRenderOptions](./kibana-plugin-server.irenderoptions.md) > [includeUserSettings](./kibana-plugin-server.irenderoptions.includeusersettings.md) + +## IRenderOptions.includeUserSettings property + +Set whether to output user settings in the page metadata. `true` by default. + +Signature: + +```typescript +includeUserSettings?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.irenderoptions.md b/docs/development/core/server/kibana-plugin-server.irenderoptions.md index 34bed8b5e078c1..27e462b58849d5 100644 --- a/docs/development/core/server/kibana-plugin-server.irenderoptions.md +++ b/docs/development/core/server/kibana-plugin-server.irenderoptions.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRenderOptions](./kibana-plugin-server.irenderoptions.md) - -## IRenderOptions interface - - -Signature: - -```typescript -export interface IRenderOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [includeUserSettings](./kibana-plugin-server.irenderoptions.includeusersettings.md) | boolean | Set whether to output user settings in the page metadata. true by default. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRenderOptions](./kibana-plugin-server.irenderoptions.md) + +## IRenderOptions interface + + +Signature: + +```typescript +export interface IRenderOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [includeUserSettings](./kibana-plugin-server.irenderoptions.includeusersettings.md) | boolean | Set whether to output user settings in the page metadata. true by default. | + diff --git a/docs/development/core/server/kibana-plugin-server.irouter.delete.md b/docs/development/core/server/kibana-plugin-server.irouter.delete.md index a479c03ecede3a..0b87dbcda3316d 100644 --- a/docs/development/core/server/kibana-plugin-server.irouter.delete.md +++ b/docs/development/core/server/kibana-plugin-server.irouter.delete.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [delete](./kibana-plugin-server.irouter.delete.md) - -## IRouter.delete property - -Register a route handler for `DELETE` request. - -Signature: - -```typescript -delete: RouteRegistrar<'delete'>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [delete](./kibana-plugin-server.irouter.delete.md) + +## IRouter.delete property + +Register a route handler for `DELETE` request. + +Signature: + +```typescript +delete: RouteRegistrar<'delete'>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.irouter.get.md b/docs/development/core/server/kibana-plugin-server.irouter.get.md index 0d52ef26f008c7..e6f80378e007d5 100644 --- a/docs/development/core/server/kibana-plugin-server.irouter.get.md +++ b/docs/development/core/server/kibana-plugin-server.irouter.get.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [get](./kibana-plugin-server.irouter.get.md) - -## IRouter.get property - -Register a route handler for `GET` request. - -Signature: - -```typescript -get: RouteRegistrar<'get'>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [get](./kibana-plugin-server.irouter.get.md) + +## IRouter.get property + +Register a route handler for `GET` request. + +Signature: + +```typescript +get: RouteRegistrar<'get'>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.irouter.handlelegacyerrors.md b/docs/development/core/server/kibana-plugin-server.irouter.handlelegacyerrors.md index ff71f13466cf88..86679d1f0c0c0e 100644 --- a/docs/development/core/server/kibana-plugin-server.irouter.handlelegacyerrors.md +++ b/docs/development/core/server/kibana-plugin-server.irouter.handlelegacyerrors.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [handleLegacyErrors](./kibana-plugin-server.irouter.handlelegacyerrors.md) - -## IRouter.handleLegacyErrors property - -Wrap a router handler to catch and converts legacy boom errors to proper custom errors. - -Signature: - -```typescript -handleLegacyErrors: (handler: RequestHandler) => RequestHandler; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [handleLegacyErrors](./kibana-plugin-server.irouter.handlelegacyerrors.md) + +## IRouter.handleLegacyErrors property + +Wrap a router handler to catch and converts legacy boom errors to proper custom errors. + +Signature: + +```typescript +handleLegacyErrors: (handler: RequestHandler) => RequestHandler; +``` diff --git a/docs/development/core/server/kibana-plugin-server.irouter.md b/docs/development/core/server/kibana-plugin-server.irouter.md index a6536d2ed67634..3d82cd82451410 100644 --- a/docs/development/core/server/kibana-plugin-server.irouter.md +++ b/docs/development/core/server/kibana-plugin-server.irouter.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) - -## IRouter interface - -Registers route handlers for specified resource path and method. See [RouteConfig](./kibana-plugin-server.routeconfig.md) and [RequestHandler](./kibana-plugin-server.requesthandler.md) for more information about arguments to route registrations. - -Signature: - -```typescript -export interface IRouter -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [delete](./kibana-plugin-server.irouter.delete.md) | RouteRegistrar<'delete'> | Register a route handler for DELETE request. | -| [get](./kibana-plugin-server.irouter.get.md) | RouteRegistrar<'get'> | Register a route handler for GET request. | -| [handleLegacyErrors](./kibana-plugin-server.irouter.handlelegacyerrors.md) | <P, Q, B>(handler: RequestHandler<P, Q, B>) => RequestHandler<P, Q, B> | Wrap a router handler to catch and converts legacy boom errors to proper custom errors. | -| [patch](./kibana-plugin-server.irouter.patch.md) | RouteRegistrar<'patch'> | Register a route handler for PATCH request. | -| [post](./kibana-plugin-server.irouter.post.md) | RouteRegistrar<'post'> | Register a route handler for POST request. | -| [put](./kibana-plugin-server.irouter.put.md) | RouteRegistrar<'put'> | Register a route handler for PUT request. | -| [routerPath](./kibana-plugin-server.irouter.routerpath.md) | string | Resulted path | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) + +## IRouter interface + +Registers route handlers for specified resource path and method. See [RouteConfig](./kibana-plugin-server.routeconfig.md) and [RequestHandler](./kibana-plugin-server.requesthandler.md) for more information about arguments to route registrations. + +Signature: + +```typescript +export interface IRouter +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [delete](./kibana-plugin-server.irouter.delete.md) | RouteRegistrar<'delete'> | Register a route handler for DELETE request. | +| [get](./kibana-plugin-server.irouter.get.md) | RouteRegistrar<'get'> | Register a route handler for GET request. | +| [handleLegacyErrors](./kibana-plugin-server.irouter.handlelegacyerrors.md) | <P, Q, B>(handler: RequestHandler<P, Q, B>) => RequestHandler<P, Q, B> | Wrap a router handler to catch and converts legacy boom errors to proper custom errors. | +| [patch](./kibana-plugin-server.irouter.patch.md) | RouteRegistrar<'patch'> | Register a route handler for PATCH request. | +| [post](./kibana-plugin-server.irouter.post.md) | RouteRegistrar<'post'> | Register a route handler for POST request. | +| [put](./kibana-plugin-server.irouter.put.md) | RouteRegistrar<'put'> | Register a route handler for PUT request. | +| [routerPath](./kibana-plugin-server.irouter.routerpath.md) | string | Resulted path | + diff --git a/docs/development/core/server/kibana-plugin-server.irouter.patch.md b/docs/development/core/server/kibana-plugin-server.irouter.patch.md index 460f1b9d23640f..ef7ea6f18d6469 100644 --- a/docs/development/core/server/kibana-plugin-server.irouter.patch.md +++ b/docs/development/core/server/kibana-plugin-server.irouter.patch.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [patch](./kibana-plugin-server.irouter.patch.md) - -## IRouter.patch property - -Register a route handler for `PATCH` request. - -Signature: - -```typescript -patch: RouteRegistrar<'patch'>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [patch](./kibana-plugin-server.irouter.patch.md) + +## IRouter.patch property + +Register a route handler for `PATCH` request. + +Signature: + +```typescript +patch: RouteRegistrar<'patch'>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.irouter.post.md b/docs/development/core/server/kibana-plugin-server.irouter.post.md index a2ac27ebc731ae..6e4a858cd342c8 100644 --- a/docs/development/core/server/kibana-plugin-server.irouter.post.md +++ b/docs/development/core/server/kibana-plugin-server.irouter.post.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [post](./kibana-plugin-server.irouter.post.md) - -## IRouter.post property - -Register a route handler for `POST` request. - -Signature: - -```typescript -post: RouteRegistrar<'post'>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [post](./kibana-plugin-server.irouter.post.md) + +## IRouter.post property + +Register a route handler for `POST` request. + +Signature: + +```typescript +post: RouteRegistrar<'post'>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.irouter.put.md b/docs/development/core/server/kibana-plugin-server.irouter.put.md index 219c5d8805661f..be6c235250fdd2 100644 --- a/docs/development/core/server/kibana-plugin-server.irouter.put.md +++ b/docs/development/core/server/kibana-plugin-server.irouter.put.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [put](./kibana-plugin-server.irouter.put.md) - -## IRouter.put property - -Register a route handler for `PUT` request. - -Signature: - -```typescript -put: RouteRegistrar<'put'>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [put](./kibana-plugin-server.irouter.put.md) + +## IRouter.put property + +Register a route handler for `PUT` request. + +Signature: + +```typescript +put: RouteRegistrar<'put'>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.irouter.routerpath.md b/docs/development/core/server/kibana-plugin-server.irouter.routerpath.md index ab1b4a6baa7e95..0b777ae056d1ac 100644 --- a/docs/development/core/server/kibana-plugin-server.irouter.routerpath.md +++ b/docs/development/core/server/kibana-plugin-server.irouter.routerpath.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [routerPath](./kibana-plugin-server.irouter.routerpath.md) - -## IRouter.routerPath property - -Resulted path - -Signature: - -```typescript -routerPath: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IRouter](./kibana-plugin-server.irouter.md) > [routerPath](./kibana-plugin-server.irouter.routerpath.md) + +## IRouter.routerPath property + +Resulted path + +Signature: + +```typescript +routerPath: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.isauthenticated.md b/docs/development/core/server/kibana-plugin-server.isauthenticated.md index 15f412710412a2..bcc82bc6149526 100644 --- a/docs/development/core/server/kibana-plugin-server.isauthenticated.md +++ b/docs/development/core/server/kibana-plugin-server.isauthenticated.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) - -## IsAuthenticated type - -Return authentication status for a request. - -Signature: - -```typescript -export declare type IsAuthenticated = (request: KibanaRequest | LegacyRequest) => boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) + +## IsAuthenticated type + +Returns authentication status for a request. + +Signature: + +```typescript +export declare type IsAuthenticated = (request: KibanaRequest | LegacyRequest) => boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.isavedobjectsrepository.md b/docs/development/core/server/kibana-plugin-server.isavedobjectsrepository.md index 7863d1b0ca49dd..e6121a20875690 100644 --- a/docs/development/core/server/kibana-plugin-server.isavedobjectsrepository.md +++ b/docs/development/core/server/kibana-plugin-server.isavedobjectsrepository.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ISavedObjectsRepository](./kibana-plugin-server.isavedobjectsrepository.md) - -## ISavedObjectsRepository type - -See [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) - -Signature: - -```typescript -export declare type ISavedObjectsRepository = Pick; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ISavedObjectsRepository](./kibana-plugin-server.isavedobjectsrepository.md) + +## ISavedObjectsRepository type + +See [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) + +Signature: + +```typescript +export declare type ISavedObjectsRepository = Pick; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md b/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md index becd1d26d24738..54320473e0400a 100644 --- a/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md +++ b/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) - -## IScopedClusterClient type - -Serves the same purpose as "normal" `ClusterClient` but exposes additional `callAsCurrentUser` method that doesn't use credentials of the Kibana internal user (as `callAsInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API. - -See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). - -Signature: - -```typescript -export declare type IScopedClusterClient = Pick; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) + +## IScopedClusterClient type + +Serves the same purpose as "normal" `ClusterClient` but exposes additional `callAsCurrentUser` method that doesn't use credentials of the Kibana internal user (as `callAsInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API. + +See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). + +Signature: + +```typescript +export declare type IScopedClusterClient = Pick; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.md b/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.md index 2e6daa58db25fa..ad21f573d2048a 100644 --- a/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.md +++ b/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IScopedRenderingClient](./kibana-plugin-server.iscopedrenderingclient.md) - -## IScopedRenderingClient interface - - -Signature: - -```typescript -export interface IScopedRenderingClient -``` - -## Methods - -| Method | Description | -| --- | --- | -| [render(options)](./kibana-plugin-server.iscopedrenderingclient.render.md) | Generate a KibanaResponse which renders an HTML page bootstrapped with the core bundle. Intended as a response body for HTTP route handlers. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IScopedRenderingClient](./kibana-plugin-server.iscopedrenderingclient.md) + +## IScopedRenderingClient interface + + +Signature: + +```typescript +export interface IScopedRenderingClient +``` + +## Methods + +| Method | Description | +| --- | --- | +| [render(options)](./kibana-plugin-server.iscopedrenderingclient.render.md) | Generate a KibanaResponse which renders an HTML page bootstrapped with the core bundle. Intended as a response body for HTTP route handlers. | + diff --git a/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.render.md b/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.render.md index 42cbc59c536a62..107df060ad3069 100644 --- a/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.render.md +++ b/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.render.md @@ -1,41 +1,41 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IScopedRenderingClient](./kibana-plugin-server.iscopedrenderingclient.md) > [render](./kibana-plugin-server.iscopedrenderingclient.render.md) - -## IScopedRenderingClient.render() method - -Generate a `KibanaResponse` which renders an HTML page bootstrapped with the `core` bundle. Intended as a response body for HTTP route handlers. - -Signature: - -```typescript -render(options?: Pick): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| options | Pick<IRenderOptions, 'includeUserSettings'> | | - -Returns: - -`Promise` - -## Example - - -```ts -router.get( - { path: '/', validate: false }, - (context, request, response) => - response.ok({ - body: await context.core.rendering.render(), - headers: { - 'content-security-policy': context.core.http.csp.header, - }, - }) -); - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IScopedRenderingClient](./kibana-plugin-server.iscopedrenderingclient.md) > [render](./kibana-plugin-server.iscopedrenderingclient.render.md) + +## IScopedRenderingClient.render() method + +Generate a `KibanaResponse` which renders an HTML page bootstrapped with the `core` bundle. Intended as a response body for HTTP route handlers. + +Signature: + +```typescript +render(options?: Pick): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | Pick<IRenderOptions, 'includeUserSettings'> | | + +Returns: + +`Promise` + +## Example + + +```ts +router.get( + { path: '/', validate: false }, + (context, request, response) => + response.ok({ + body: await context.core.rendering.render(), + headers: { + 'content-security-policy': context.core.http.csp.header, + }, + }) +); + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.get.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.get.md index a73061f457a4bb..aa266dc06429eb 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.get.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.get.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [get](./kibana-plugin-server.iuisettingsclient.get.md) - -## IUiSettingsClient.get property - -Retrieves uiSettings values set by the user with fallbacks to default values if not specified. - -Signature: - -```typescript -get: (key: string) => Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [get](./kibana-plugin-server.iuisettingsclient.get.md) + +## IUiSettingsClient.get property + +Retrieves uiSettings values set by the user with fallbacks to default values if not specified. + +Signature: + +```typescript +get: (key: string) => Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getall.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getall.md index 600116b86d1c03..a7d7550c272e15 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getall.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getall.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [getAll](./kibana-plugin-server.iuisettingsclient.getall.md) - -## IUiSettingsClient.getAll property - -Retrieves a set of all uiSettings values set by the user with fallbacks to default values if not specified. - -Signature: - -```typescript -getAll: () => Promise>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [getAll](./kibana-plugin-server.iuisettingsclient.getall.md) + +## IUiSettingsClient.getAll property + +Retrieves a set of all uiSettings values set by the user with fallbacks to default values if not specified. + +Signature: + +```typescript +getAll: () => Promise>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getregistered.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getregistered.md index 16ae4c3dd8b364..ca2649aeec02e4 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getregistered.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getregistered.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [getRegistered](./kibana-plugin-server.iuisettingsclient.getregistered.md) - -## IUiSettingsClient.getRegistered property - -Returns registered uiSettings values [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) - -Signature: - -```typescript -getRegistered: () => Readonly>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [getRegistered](./kibana-plugin-server.iuisettingsclient.getregistered.md) + +## IUiSettingsClient.getRegistered property + +Returns registered uiSettings values [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) + +Signature: + +```typescript +getRegistered: () => Readonly>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getuserprovided.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getuserprovided.md index 94b7575519cee0..5828b2718fc431 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getuserprovided.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.getuserprovided.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [getUserProvided](./kibana-plugin-server.iuisettingsclient.getuserprovided.md) - -## IUiSettingsClient.getUserProvided property - -Retrieves a set of all uiSettings values set by the user. - -Signature: - -```typescript -getUserProvided: () => Promise>>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [getUserProvided](./kibana-plugin-server.iuisettingsclient.getuserprovided.md) + +## IUiSettingsClient.getUserProvided property + +Retrieves a set of all uiSettings values set by the user. + +Signature: + +```typescript +getUserProvided: () => Promise>>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.isoverridden.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.isoverridden.md index a53655763a79b9..447aa3278b0ee3 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.isoverridden.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.isoverridden.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [isOverridden](./kibana-plugin-server.iuisettingsclient.isoverridden.md) - -## IUiSettingsClient.isOverridden property - -Shows whether the uiSettings value set by the user. - -Signature: - -```typescript -isOverridden: (key: string) => boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [isOverridden](./kibana-plugin-server.iuisettingsclient.isoverridden.md) + +## IUiSettingsClient.isOverridden property + +Shows whether the uiSettings value set by the user. + +Signature: + +```typescript +isOverridden: (key: string) => boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.md index c254321e02291f..f25da163758a1f 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) - -## IUiSettingsClient interface - -Server-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. - -Signature: - -```typescript -export interface IUiSettingsClient -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [get](./kibana-plugin-server.iuisettingsclient.get.md) | <T = any>(key: string) => Promise<T> | Retrieves uiSettings values set by the user with fallbacks to default values if not specified. | -| [getAll](./kibana-plugin-server.iuisettingsclient.getall.md) | <T = any>() => Promise<Record<string, T>> | Retrieves a set of all uiSettings values set by the user with fallbacks to default values if not specified. | -| [getRegistered](./kibana-plugin-server.iuisettingsclient.getregistered.md) | () => Readonly<Record<string, UiSettingsParams>> | Returns registered uiSettings values [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) | -| [getUserProvided](./kibana-plugin-server.iuisettingsclient.getuserprovided.md) | <T = any>() => Promise<Record<string, UserProvidedValues<T>>> | Retrieves a set of all uiSettings values set by the user. | -| [isOverridden](./kibana-plugin-server.iuisettingsclient.isoverridden.md) | (key: string) => boolean | Shows whether the uiSettings value set by the user. | -| [remove](./kibana-plugin-server.iuisettingsclient.remove.md) | (key: string) => Promise<void> | Removes uiSettings value by key. | -| [removeMany](./kibana-plugin-server.iuisettingsclient.removemany.md) | (keys: string[]) => Promise<void> | Removes multiple uiSettings values by keys. | -| [set](./kibana-plugin-server.iuisettingsclient.set.md) | (key: string, value: any) => Promise<void> | Writes uiSettings value and marks it as set by the user. | -| [setMany](./kibana-plugin-server.iuisettingsclient.setmany.md) | (changes: Record<string, any>) => Promise<void> | Writes multiple uiSettings values and marks them as set by the user. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) + +## IUiSettingsClient interface + +Server-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. + +Signature: + +```typescript +export interface IUiSettingsClient +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [get](./kibana-plugin-server.iuisettingsclient.get.md) | <T = any>(key: string) => Promise<T> | Retrieves uiSettings values set by the user with fallbacks to default values if not specified. | +| [getAll](./kibana-plugin-server.iuisettingsclient.getall.md) | <T = any>() => Promise<Record<string, T>> | Retrieves a set of all uiSettings values set by the user with fallbacks to default values if not specified. | +| [getRegistered](./kibana-plugin-server.iuisettingsclient.getregistered.md) | () => Readonly<Record<string, UiSettingsParams>> | Returns registered uiSettings values [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) | +| [getUserProvided](./kibana-plugin-server.iuisettingsclient.getuserprovided.md) | <T = any>() => Promise<Record<string, UserProvidedValues<T>>> | Retrieves a set of all uiSettings values set by the user. | +| [isOverridden](./kibana-plugin-server.iuisettingsclient.isoverridden.md) | (key: string) => boolean | Shows whether the uiSettings value set by the user. | +| [remove](./kibana-plugin-server.iuisettingsclient.remove.md) | (key: string) => Promise<void> | Removes uiSettings value by key. | +| [removeMany](./kibana-plugin-server.iuisettingsclient.removemany.md) | (keys: string[]) => Promise<void> | Removes multiple uiSettings values by keys. | +| [set](./kibana-plugin-server.iuisettingsclient.set.md) | (key: string, value: any) => Promise<void> | Writes uiSettings value and marks it as set by the user. | +| [setMany](./kibana-plugin-server.iuisettingsclient.setmany.md) | (changes: Record<string, any>) => Promise<void> | Writes multiple uiSettings values and marks them as set by the user. | + diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.remove.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.remove.md index fa15b11fd76e4a..8ef4072479600a 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.remove.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.remove.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [remove](./kibana-plugin-server.iuisettingsclient.remove.md) - -## IUiSettingsClient.remove property - -Removes uiSettings value by key. - -Signature: - -```typescript -remove: (key: string) => Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [remove](./kibana-plugin-server.iuisettingsclient.remove.md) + +## IUiSettingsClient.remove property + +Removes uiSettings value by key. + +Signature: + +```typescript +remove: (key: string) => Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.removemany.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.removemany.md index ef5f994707aaec..850d51d041900b 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.removemany.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.removemany.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [removeMany](./kibana-plugin-server.iuisettingsclient.removemany.md) - -## IUiSettingsClient.removeMany property - -Removes multiple uiSettings values by keys. - -Signature: - -```typescript -removeMany: (keys: string[]) => Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [removeMany](./kibana-plugin-server.iuisettingsclient.removemany.md) + +## IUiSettingsClient.removeMany property + +Removes multiple uiSettings values by keys. + +Signature: + +```typescript +removeMany: (keys: string[]) => Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.set.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.set.md index 5d5897a7159ad7..e647948f416a80 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.set.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.set.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [set](./kibana-plugin-server.iuisettingsclient.set.md) - -## IUiSettingsClient.set property - -Writes uiSettings value and marks it as set by the user. - -Signature: - -```typescript -set: (key: string, value: any) => Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [set](./kibana-plugin-server.iuisettingsclient.set.md) + +## IUiSettingsClient.set property + +Writes uiSettings value and marks it as set by the user. + +Signature: + +```typescript +set: (key: string, value: any) => Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.setmany.md b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.setmany.md index e1d2595d8e1c76..a724427fe5e165 100644 --- a/docs/development/core/server/kibana-plugin-server.iuisettingsclient.setmany.md +++ b/docs/development/core/server/kibana-plugin-server.iuisettingsclient.setmany.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [setMany](./kibana-plugin-server.iuisettingsclient.setmany.md) - -## IUiSettingsClient.setMany property - -Writes multiple uiSettings values and marks them as set by the user. - -Signature: - -```typescript -setMany: (changes: Record) => Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) > [setMany](./kibana-plugin-server.iuisettingsclient.setmany.md) + +## IUiSettingsClient.setMany property + +Writes multiple uiSettings values and marks them as set by the user. + +Signature: + +```typescript +setMany: (changes: Record) => Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest._constructor_.md b/docs/development/core/server/kibana-plugin-server.kibanarequest._constructor_.md index 1ef6beb82ea984..9d96515f3e2a04 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest._constructor_.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest._constructor_.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [(constructor)](./kibana-plugin-server.kibanarequest._constructor_.md) - -## KibanaRequest.(constructor) - -Constructs a new instance of the `KibanaRequest` class - -Signature: - -```typescript -constructor(request: Request, params: Params, query: Query, body: Body, withoutSecretHeaders: boolean); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | Request | | -| params | Params | | -| query | Query | | -| body | Body | | -| withoutSecretHeaders | boolean | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [(constructor)](./kibana-plugin-server.kibanarequest._constructor_.md) + +## KibanaRequest.(constructor) + +Constructs a new instance of the `KibanaRequest` class + +Signature: + +```typescript +constructor(request: Request, params: Params, query: Query, body: Body, withoutSecretHeaders: boolean); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | Request | | +| params | Params | | +| query | Query | | +| body | Body | | +| withoutSecretHeaders | boolean | | + diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.body.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.body.md index b1284f58c6815b..cd19639fc5af2a 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest.body.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.body.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [body](./kibana-plugin-server.kibanarequest.body.md) - -## KibanaRequest.body property - -Signature: - -```typescript -readonly body: Body; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [body](./kibana-plugin-server.kibanarequest.body.md) + +## KibanaRequest.body property + +Signature: + +```typescript +readonly body: Body; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.events.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.events.md new file mode 100644 index 00000000000000..f9056075ef7f8e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.events.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [events](./kibana-plugin-server.kibanarequest.events.md) + +## KibanaRequest.events property + +Request events [KibanaRequestEvents](./kibana-plugin-server.kibanarequestevents.md) + +Signature: + +```typescript +readonly events: KibanaRequestEvents; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.headers.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.headers.md index 8bd50e23608de6..a5a2cf0d6c3147 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest.headers.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.headers.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [headers](./kibana-plugin-server.kibanarequest.headers.md) - -## KibanaRequest.headers property - -Readonly copy of incoming request headers. - -Signature: - -```typescript -readonly headers: Headers; -``` - -## Remarks - -This property will contain a `filtered` copy of request headers. - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [headers](./kibana-plugin-server.kibanarequest.headers.md) + +## KibanaRequest.headers property + +Readonly copy of incoming request headers. + +Signature: + +```typescript +readonly headers: Headers; +``` + +## Remarks + +This property will contain a `filtered` copy of request headers. + diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.issystemrequest.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.issystemrequest.md new file mode 100644 index 00000000000000..a643c70632d539 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.issystemrequest.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [isSystemRequest](./kibana-plugin-server.kibanarequest.issystemrequest.md) + +## KibanaRequest.isSystemRequest property + +Whether or not the request is a "system request" rather than an application-level request. Can be set on the client using the `HttpFetchOptions#asSystemRequest` option. + +Signature: + +```typescript +readonly isSystemRequest: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.md index bc805fdc0b86f1..cb6745623e3818 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.md @@ -1,32 +1,34 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) - -## KibanaRequest class - -Kibana specific abstraction for an incoming request. - -Signature: - -```typescript -export declare class KibanaRequest -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(request, params, query, body, withoutSecretHeaders)](./kibana-plugin-server.kibanarequest._constructor_.md) | | Constructs a new instance of the KibanaRequest class | - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [body](./kibana-plugin-server.kibanarequest.body.md) | | Body | | -| [headers](./kibana-plugin-server.kibanarequest.headers.md) | | Headers | Readonly copy of incoming request headers. | -| [params](./kibana-plugin-server.kibanarequest.params.md) | | Params | | -| [query](./kibana-plugin-server.kibanarequest.query.md) | | Query | | -| [route](./kibana-plugin-server.kibanarequest.route.md) | | RecursiveReadonly<KibanaRequestRoute<Method>> | matched route details | -| [socket](./kibana-plugin-server.kibanarequest.socket.md) | | IKibanaSocket | | -| [url](./kibana-plugin-server.kibanarequest.url.md) | | Url | a WHATWG URL standard object. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) + +## KibanaRequest class + +Kibana specific abstraction for an incoming request. + +Signature: + +```typescript +export declare class KibanaRequest +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(request, params, query, body, withoutSecretHeaders)](./kibana-plugin-server.kibanarequest._constructor_.md) | | Constructs a new instance of the KibanaRequest class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [body](./kibana-plugin-server.kibanarequest.body.md) | | Body | | +| [events](./kibana-plugin-server.kibanarequest.events.md) | | KibanaRequestEvents | Request events [KibanaRequestEvents](./kibana-plugin-server.kibanarequestevents.md) | +| [headers](./kibana-plugin-server.kibanarequest.headers.md) | | Headers | Readonly copy of incoming request headers. | +| [isSystemRequest](./kibana-plugin-server.kibanarequest.issystemrequest.md) | | boolean | Whether or not the request is a "system request" rather than an application-level request. Can be set on the client using the HttpFetchOptions#asSystemRequest option. | +| [params](./kibana-plugin-server.kibanarequest.params.md) | | Params | | +| [query](./kibana-plugin-server.kibanarequest.query.md) | | Query | | +| [route](./kibana-plugin-server.kibanarequest.route.md) | | RecursiveReadonly<KibanaRequestRoute<Method>> | matched route details | +| [socket](./kibana-plugin-server.kibanarequest.socket.md) | | IKibanaSocket | [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) | +| [url](./kibana-plugin-server.kibanarequest.url.md) | | Url | a WHATWG URL standard object. | + diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.params.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.params.md index c8902be737d818..37f4a3a28a41a8 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest.params.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.params.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [params](./kibana-plugin-server.kibanarequest.params.md) - -## KibanaRequest.params property - -Signature: - -```typescript -readonly params: Params; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [params](./kibana-plugin-server.kibanarequest.params.md) + +## KibanaRequest.params property + +Signature: + +```typescript +readonly params: Params; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.query.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.query.md index 30a5739676403a..3ec5d877283b34 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest.query.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.query.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [query](./kibana-plugin-server.kibanarequest.query.md) - -## KibanaRequest.query property - -Signature: - -```typescript -readonly query: Query; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [query](./kibana-plugin-server.kibanarequest.query.md) + +## KibanaRequest.query property + +Signature: + +```typescript +readonly query: Query; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.route.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.route.md index 1905070a99068b..fb71327a7d1294 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest.route.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.route.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [route](./kibana-plugin-server.kibanarequest.route.md) - -## KibanaRequest.route property - -matched route details - -Signature: - -```typescript -readonly route: RecursiveReadonly>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [route](./kibana-plugin-server.kibanarequest.route.md) + +## KibanaRequest.route property + +matched route details + +Signature: + +```typescript +readonly route: RecursiveReadonly>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.socket.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.socket.md index 3880428273ac9c..b1b83ab6145cd1 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest.socket.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.socket.md @@ -1,11 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [socket](./kibana-plugin-server.kibanarequest.socket.md) - -## KibanaRequest.socket property - -Signature: - -```typescript -readonly socket: IKibanaSocket; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [socket](./kibana-plugin-server.kibanarequest.socket.md) + +## KibanaRequest.socket property + +[IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) + +Signature: + +```typescript +readonly socket: IKibanaSocket; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequest.url.md b/docs/development/core/server/kibana-plugin-server.kibanarequest.url.md index 62d1f971594764..e77b77edede4d6 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequest.url.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequest.url.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [url](./kibana-plugin-server.kibanarequest.url.md) - -## KibanaRequest.url property - -a WHATWG URL standard object. - -Signature: - -```typescript -readonly url: Url; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequest](./kibana-plugin-server.kibanarequest.md) > [url](./kibana-plugin-server.kibanarequest.url.md) + +## KibanaRequest.url property + +a WHATWG URL standard object. + +Signature: + +```typescript +readonly url: Url; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequestevents.aborted_.md b/docs/development/core/server/kibana-plugin-server.kibanarequestevents.aborted_.md new file mode 100644 index 00000000000000..25d228e6ec2768 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.kibanarequestevents.aborted_.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestEvents](./kibana-plugin-server.kibanarequestevents.md) > [aborted$](./kibana-plugin-server.kibanarequestevents.aborted_.md) + +## KibanaRequestEvents.aborted$ property + +Observable that emits once if and when the request has been aborted. + +Signature: + +```typescript +aborted$: Observable; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequestevents.md b/docs/development/core/server/kibana-plugin-server.kibanarequestevents.md new file mode 100644 index 00000000000000..85cb6e397c3ecd --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.kibanarequestevents.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestEvents](./kibana-plugin-server.kibanarequestevents.md) + +## KibanaRequestEvents interface + +Request events. + +Signature: + +```typescript +export interface KibanaRequestEvents +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [aborted$](./kibana-plugin-server.kibanarequestevents.aborted_.md) | Observable<void> | Observable that emits once if and when the request has been aborted. | + diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequestroute.md b/docs/development/core/server/kibana-plugin-server.kibanarequestroute.md index 29836394582007..8a63aa52c0c9db 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequestroute.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequestroute.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) - -## KibanaRequestRoute interface - -Request specific route information exposed to a handler. - -Signature: - -```typescript -export interface KibanaRequestRoute -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [method](./kibana-plugin-server.kibanarequestroute.method.md) | Method | | -| [options](./kibana-plugin-server.kibanarequestroute.options.md) | KibanaRequestRouteOptions<Method> | | -| [path](./kibana-plugin-server.kibanarequestroute.path.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) + +## KibanaRequestRoute interface + +Request specific route information exposed to a handler. + +Signature: + +```typescript +export interface KibanaRequestRoute +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [method](./kibana-plugin-server.kibanarequestroute.method.md) | Method | | +| [options](./kibana-plugin-server.kibanarequestroute.options.md) | KibanaRequestRouteOptions<Method> | | +| [path](./kibana-plugin-server.kibanarequestroute.path.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequestroute.method.md b/docs/development/core/server/kibana-plugin-server.kibanarequestroute.method.md index 5775d28b1e053b..9a60a502557560 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequestroute.method.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequestroute.method.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) > [method](./kibana-plugin-server.kibanarequestroute.method.md) - -## KibanaRequestRoute.method property - -Signature: - -```typescript -method: Method; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) > [method](./kibana-plugin-server.kibanarequestroute.method.md) + +## KibanaRequestRoute.method property + +Signature: + +```typescript +method: Method; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequestroute.options.md b/docs/development/core/server/kibana-plugin-server.kibanarequestroute.options.md index 438263f61eb20a..82a46c09b0aa6a 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequestroute.options.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequestroute.options.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) > [options](./kibana-plugin-server.kibanarequestroute.options.md) - -## KibanaRequestRoute.options property - -Signature: - -```typescript -options: KibanaRequestRouteOptions; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) > [options](./kibana-plugin-server.kibanarequestroute.options.md) + +## KibanaRequestRoute.options property + +Signature: + +```typescript +options: KibanaRequestRouteOptions; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequestroute.path.md b/docs/development/core/server/kibana-plugin-server.kibanarequestroute.path.md index 17d4b588e6d44c..01e623a2f47c5b 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequestroute.path.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequestroute.path.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) > [path](./kibana-plugin-server.kibanarequestroute.path.md) - -## KibanaRequestRoute.path property - -Signature: - -```typescript -path: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) > [path](./kibana-plugin-server.kibanarequestroute.path.md) + +## KibanaRequestRoute.path property + +Signature: + +```typescript +path: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanarequestrouteoptions.md b/docs/development/core/server/kibana-plugin-server.kibanarequestrouteoptions.md index f48711ac11f927..71e0169137a720 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanarequestrouteoptions.md +++ b/docs/development/core/server/kibana-plugin-server.kibanarequestrouteoptions.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRouteOptions](./kibana-plugin-server.kibanarequestrouteoptions.md) - -## KibanaRequestRouteOptions type - -Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. - -Signature: - -```typescript -export declare type KibanaRequestRouteOptions = Method extends 'get' | 'options' ? Required, 'body'>> : Required>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KibanaRequestRouteOptions](./kibana-plugin-server.kibanarequestrouteoptions.md) + +## KibanaRequestRouteOptions type + +Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. + +Signature: + +```typescript +export declare type KibanaRequestRouteOptions = Method extends 'get' | 'options' ? Required, 'body'>> : Required>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.kibanaresponsefactory.md b/docs/development/core/server/kibana-plugin-server.kibanaresponsefactory.md index 2e496aa0c46fc7..cfedaa2d23dd20 100644 --- a/docs/development/core/server/kibana-plugin-server.kibanaresponsefactory.md +++ b/docs/development/core/server/kibana-plugin-server.kibanaresponsefactory.md @@ -1,118 +1,118 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [kibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) - -## kibanaResponseFactory variable - -Set of helpers used to create `KibanaResponse` to form HTTP response on an incoming request. Should be returned as a result of [RequestHandler](./kibana-plugin-server.requesthandler.md) execution. - -Signature: - -```typescript -kibanaResponseFactory: { - custom: | { - message: string | Error; - attributes?: Record | undefined; - } | undefined>(options: CustomHttpResponseOptions) => KibanaResponse; - badRequest: (options?: ErrorHttpResponseOptions) => KibanaResponse; - unauthorized: (options?: ErrorHttpResponseOptions) => KibanaResponse; - forbidden: (options?: ErrorHttpResponseOptions) => KibanaResponse; - notFound: (options?: ErrorHttpResponseOptions) => KibanaResponse; - conflict: (options?: ErrorHttpResponseOptions) => KibanaResponse; - internalError: (options?: ErrorHttpResponseOptions) => KibanaResponse; - customError: (options: CustomHttpResponseOptions) => KibanaResponse; - redirected: (options: RedirectResponseOptions) => KibanaResponse>; - ok: (options?: HttpResponseOptions) => KibanaResponse>; - accepted: (options?: HttpResponseOptions) => KibanaResponse>; - noContent: (options?: HttpResponseOptions) => KibanaResponse; -} -``` - -## Example - -1. Successful response. Supported types of response body are: - `undefined`, no content to send. - `string`, send text - `JSON`, send JSON object, HTTP server will throw if given object is not valid (has circular references, for example) - `Stream` send data stream - `Buffer` send binary stream - -```js -return response.ok(); -return response.ok({ body: 'ack' }); -return response.ok({ body: { id: '1' } }); -return response.ok({ body: Buffer.from(...) }); - -const stream = new Stream.PassThrough(); -fs.createReadStream('./file').pipe(stream); -return res.ok({ body: stream }); - -``` -HTTP headers are configurable via response factory parameter `options` [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md). - -```js -return response.ok({ - body: { id: '1' }, - headers: { - 'content-type': 'application/json' - } -}); - -``` -2. Redirection response. Redirection URL is configures via 'Location' header. - -```js -return response.redirected({ - body: 'The document has moved', - headers: { - location: '/new-url', - }, -}); - -``` -3. Error response. You may pass an error message to the client, where error message can be: - `string` send message text - `Error` send the message text of given Error object. - `{ message: string | Error, attributes: {data: Record, ...} }` - send message text and attach additional error data. - -```js -return response.unauthorized({ - body: 'User has no access to the requested resource.', - headers: { - 'WWW-Authenticate': 'challenge', - } -}) -return response.badRequest(); -return response.badRequest({ body: 'validation error' }); - -try { - // ... -} catch(error){ - return response.badRequest({ body: error }); -} - -return response.badRequest({ - body:{ - message: 'validation error', - attributes: { - requestBody: request.body, - failedFields: validationResult - } - } -}); - -try { - // ... -} catch(error) { - return response.badRequest({ - body: error - }); -} - - -``` -4. Custom response. `ResponseFactory` may not cover your use case, so you can use the `custom` function to customize the response. - -```js -return response.custom({ - body: 'ok', - statusCode: 201, - headers: { - location: '/created-url' - } -}) - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [kibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) + +## kibanaResponseFactory variable + +Set of helpers used to create `KibanaResponse` to form HTTP response on an incoming request. Should be returned as a result of [RequestHandler](./kibana-plugin-server.requesthandler.md) execution. + +Signature: + +```typescript +kibanaResponseFactory: { + custom: | { + message: string | Error; + attributes?: Record | undefined; + } | undefined>(options: CustomHttpResponseOptions) => KibanaResponse; + badRequest: (options?: ErrorHttpResponseOptions) => KibanaResponse; + unauthorized: (options?: ErrorHttpResponseOptions) => KibanaResponse; + forbidden: (options?: ErrorHttpResponseOptions) => KibanaResponse; + notFound: (options?: ErrorHttpResponseOptions) => KibanaResponse; + conflict: (options?: ErrorHttpResponseOptions) => KibanaResponse; + internalError: (options?: ErrorHttpResponseOptions) => KibanaResponse; + customError: (options: CustomHttpResponseOptions) => KibanaResponse; + redirected: (options: RedirectResponseOptions) => KibanaResponse>; + ok: (options?: HttpResponseOptions) => KibanaResponse>; + accepted: (options?: HttpResponseOptions) => KibanaResponse>; + noContent: (options?: HttpResponseOptions) => KibanaResponse; +} +``` + +## Example + +1. Successful response. Supported types of response body are: - `undefined`, no content to send. - `string`, send text - `JSON`, send JSON object, HTTP server will throw if given object is not valid (has circular references, for example) - `Stream` send data stream - `Buffer` send binary stream + +```js +return response.ok(); +return response.ok({ body: 'ack' }); +return response.ok({ body: { id: '1' } }); +return response.ok({ body: Buffer.from(...) }); + +const stream = new Stream.PassThrough(); +fs.createReadStream('./file').pipe(stream); +return res.ok({ body: stream }); + +``` +HTTP headers are configurable via response factory parameter `options` [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md). + +```js +return response.ok({ + body: { id: '1' }, + headers: { + 'content-type': 'application/json' + } +}); + +``` +2. Redirection response. Redirection URL is configures via 'Location' header. + +```js +return response.redirected({ + body: 'The document has moved', + headers: { + location: '/new-url', + }, +}); + +``` +3. Error response. You may pass an error message to the client, where error message can be: - `string` send message text - `Error` send the message text of given Error object. - `{ message: string | Error, attributes: {data: Record, ...} }` - send message text and attach additional error data. + +```js +return response.unauthorized({ + body: 'User has no access to the requested resource.', + headers: { + 'WWW-Authenticate': 'challenge', + } +}) +return response.badRequest(); +return response.badRequest({ body: 'validation error' }); + +try { + // ... +} catch(error){ + return response.badRequest({ body: error }); +} + +return response.badRequest({ + body:{ + message: 'validation error', + attributes: { + requestBody: request.body, + failedFields: validationResult + } + } +}); + +try { + // ... +} catch(error) { + return response.badRequest({ + body: error + }); +} + + +``` +4. Custom response. `ResponseFactory` may not cover your use case, so you can use the `custom` function to customize the response. + +```js +return response.custom({ + body: 'ok', + statusCode: 201, + headers: { + location: '/created-url' + } +}) + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.knownheaders.md b/docs/development/core/server/kibana-plugin-server.knownheaders.md index 986794f3aaa61d..69c3939cfa084a 100644 --- a/docs/development/core/server/kibana-plugin-server.knownheaders.md +++ b/docs/development/core/server/kibana-plugin-server.knownheaders.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KnownHeaders](./kibana-plugin-server.knownheaders.md) - -## KnownHeaders type - -Set of well-known HTTP headers. - -Signature: - -```typescript -export declare type KnownHeaders = KnownKeys; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [KnownHeaders](./kibana-plugin-server.knownheaders.md) + +## KnownHeaders type + +Set of well-known HTTP headers. + +Signature: + +```typescript +export declare type KnownHeaders = KnownKeys; +``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyrequest.md b/docs/development/core/server/kibana-plugin-server.legacyrequest.md index a794b3bbe87c7d..329c2fb8053123 100644 --- a/docs/development/core/server/kibana-plugin-server.legacyrequest.md +++ b/docs/development/core/server/kibana-plugin-server.legacyrequest.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyRequest](./kibana-plugin-server.legacyrequest.md) - -## LegacyRequest interface - -> Warning: This API is now obsolete. -> -> `hapi` request object, supported during migration process only for backward compatibility. -> - -Signature: - -```typescript -export interface LegacyRequest extends Request -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyRequest](./kibana-plugin-server.legacyrequest.md) + +## LegacyRequest interface + +> Warning: This API is now obsolete. +> +> `hapi` request object, supported during migration process only for backward compatibility. +> + +Signature: + +```typescript +export interface LegacyRequest extends Request +``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.core.md b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.core.md index c4c043a903d06c..2fa3e587df7147 100644 --- a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.core.md +++ b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.core.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) > [core](./kibana-plugin-server.legacyservicesetupdeps.core.md) - -## LegacyServiceSetupDeps.core property - -Signature: - -```typescript -core: LegacyCoreSetup; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) > [core](./kibana-plugin-server.legacyservicesetupdeps.core.md) + +## LegacyServiceSetupDeps.core property + +Signature: + +```typescript +core: LegacyCoreSetup; +``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.md b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.md index 7961cedd2c0548..5ee3c9a2113fdb 100644 --- a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.md +++ b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) - -## LegacyServiceSetupDeps interface - -> Warning: This API is now obsolete. -> -> - -Signature: - -```typescript -export interface LegacyServiceSetupDeps -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [core](./kibana-plugin-server.legacyservicesetupdeps.core.md) | LegacyCoreSetup | | -| [plugins](./kibana-plugin-server.legacyservicesetupdeps.plugins.md) | Record<string, unknown> | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) + +## LegacyServiceSetupDeps interface + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +export interface LegacyServiceSetupDeps +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [core](./kibana-plugin-server.legacyservicesetupdeps.core.md) | LegacyCoreSetup | | +| [plugins](./kibana-plugin-server.legacyservicesetupdeps.plugins.md) | Record<string, unknown> | | + diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.plugins.md b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.plugins.md index a51aa478caab51..3917b7c9ac7521 100644 --- a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.plugins.md +++ b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.plugins.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) > [plugins](./kibana-plugin-server.legacyservicesetupdeps.plugins.md) - -## LegacyServiceSetupDeps.plugins property - -Signature: - -```typescript -plugins: Record; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) > [plugins](./kibana-plugin-server.legacyservicesetupdeps.plugins.md) + +## LegacyServiceSetupDeps.plugins property + +Signature: + +```typescript +plugins: Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.core.md b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.core.md index 47018f4594967f..bcd7789698b08c 100644 --- a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.core.md +++ b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.core.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) > [core](./kibana-plugin-server.legacyservicestartdeps.core.md) - -## LegacyServiceStartDeps.core property - -Signature: - -```typescript -core: LegacyCoreStart; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) > [core](./kibana-plugin-server.legacyservicestartdeps.core.md) + +## LegacyServiceStartDeps.core property + +Signature: + +```typescript +core: LegacyCoreStart; +``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.md b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.md index 602fe5356d5251..4005c643fdb32e 100644 --- a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.md +++ b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) - -## LegacyServiceStartDeps interface - -> Warning: This API is now obsolete. -> -> - -Signature: - -```typescript -export interface LegacyServiceStartDeps -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [core](./kibana-plugin-server.legacyservicestartdeps.core.md) | LegacyCoreStart | | -| [plugins](./kibana-plugin-server.legacyservicestartdeps.plugins.md) | Record<string, unknown> | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) + +## LegacyServiceStartDeps interface + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +export interface LegacyServiceStartDeps +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [core](./kibana-plugin-server.legacyservicestartdeps.core.md) | LegacyCoreStart | | +| [plugins](./kibana-plugin-server.legacyservicestartdeps.plugins.md) | Record<string, unknown> | | + diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.plugins.md b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.plugins.md index a6d774d35e42e9..5f77289ce0a527 100644 --- a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.plugins.md +++ b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.plugins.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) > [plugins](./kibana-plugin-server.legacyservicestartdeps.plugins.md) - -## LegacyServiceStartDeps.plugins property - -Signature: - -```typescript -plugins: Record; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) > [plugins](./kibana-plugin-server.legacyservicestartdeps.plugins.md) + +## LegacyServiceStartDeps.plugins property + +Signature: + +```typescript +plugins: Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.lifecycleresponsefactory.md b/docs/development/core/server/kibana-plugin-server.lifecycleresponsefactory.md index f1c427203dd24e..ade2e5091df8ef 100644 --- a/docs/development/core/server/kibana-plugin-server.lifecycleresponsefactory.md +++ b/docs/development/core/server/kibana-plugin-server.lifecycleresponsefactory.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LifecycleResponseFactory](./kibana-plugin-server.lifecycleresponsefactory.md) - -## LifecycleResponseFactory type - -Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. - -Signature: - -```typescript -export declare type LifecycleResponseFactory = typeof lifecycleResponseFactory; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LifecycleResponseFactory](./kibana-plugin-server.lifecycleresponsefactory.md) + +## LifecycleResponseFactory type + +Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. + +Signature: + +```typescript +export declare type LifecycleResponseFactory = typeof lifecycleResponseFactory; +``` diff --git a/docs/development/core/server/kibana-plugin-server.logger.debug.md b/docs/development/core/server/kibana-plugin-server.logger.debug.md index 9a775896f618fd..3a37615ecc8c53 100644 --- a/docs/development/core/server/kibana-plugin-server.logger.debug.md +++ b/docs/development/core/server/kibana-plugin-server.logger.debug.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [debug](./kibana-plugin-server.logger.debug.md) - -## Logger.debug() method - -Log messages useful for debugging and interactive investigation - -Signature: - -```typescript -debug(message: string, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| message | string | The log message | -| meta | LogMeta | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [debug](./kibana-plugin-server.logger.debug.md) + +## Logger.debug() method + +Log messages useful for debugging and interactive investigation + +Signature: + +```typescript +debug(message: string, meta?: LogMeta): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| message | string | The log message | +| meta | LogMeta | | + +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.logger.error.md b/docs/development/core/server/kibana-plugin-server.logger.error.md index 482770d267095e..d59ccad3536a0b 100644 --- a/docs/development/core/server/kibana-plugin-server.logger.error.md +++ b/docs/development/core/server/kibana-plugin-server.logger.error.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [error](./kibana-plugin-server.logger.error.md) - -## Logger.error() method - -Logs abnormal or unexpected errors or messages that caused a failure in the application flow - -Signature: - -```typescript -error(errorOrMessage: string | Error, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| errorOrMessage | string | Error | An Error object or message string to log | -| meta | LogMeta | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [error](./kibana-plugin-server.logger.error.md) + +## Logger.error() method + +Logs abnormal or unexpected errors or messages that caused a failure in the application flow + +Signature: + +```typescript +error(errorOrMessage: string | Error, meta?: LogMeta): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| errorOrMessage | string | Error | An Error object or message string to log | +| meta | LogMeta | | + +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.logger.fatal.md b/docs/development/core/server/kibana-plugin-server.logger.fatal.md index 68f502a54f5605..41751be46627d3 100644 --- a/docs/development/core/server/kibana-plugin-server.logger.fatal.md +++ b/docs/development/core/server/kibana-plugin-server.logger.fatal.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [fatal](./kibana-plugin-server.logger.fatal.md) - -## Logger.fatal() method - -Logs abnormal or unexpected errors or messages that caused an unrecoverable failure - -Signature: - -```typescript -fatal(errorOrMessage: string | Error, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| errorOrMessage | string | Error | An Error object or message string to log | -| meta | LogMeta | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [fatal](./kibana-plugin-server.logger.fatal.md) + +## Logger.fatal() method + +Logs abnormal or unexpected errors or messages that caused an unrecoverable failure + +Signature: + +```typescript +fatal(errorOrMessage: string | Error, meta?: LogMeta): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| errorOrMessage | string | Error | An Error object or message string to log | +| meta | LogMeta | | + +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.logger.get.md b/docs/development/core/server/kibana-plugin-server.logger.get.md index b4a2d8a124260d..6b84f276880038 100644 --- a/docs/development/core/server/kibana-plugin-server.logger.get.md +++ b/docs/development/core/server/kibana-plugin-server.logger.get.md @@ -1,33 +1,33 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [get](./kibana-plugin-server.logger.get.md) - -## Logger.get() method - -Returns a new [Logger](./kibana-plugin-server.logger.md) instance extending the current logger context. - -Signature: - -```typescript -get(...childContextPaths: string[]): Logger; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| childContextPaths | string[] | | - -Returns: - -`Logger` - -## Example - - -```typescript -const logger = loggerFactory.get('plugin', 'service'); // 'plugin.service' context -const subLogger = logger.get('feature'); // 'plugin.service.feature' context - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [get](./kibana-plugin-server.logger.get.md) + +## Logger.get() method + +Returns a new [Logger](./kibana-plugin-server.logger.md) instance extending the current logger context. + +Signature: + +```typescript +get(...childContextPaths: string[]): Logger; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| childContextPaths | string[] | | + +Returns: + +`Logger` + +## Example + + +```typescript +const logger = loggerFactory.get('plugin', 'service'); // 'plugin.service' context +const subLogger = logger.get('feature'); // 'plugin.service.feature' context + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.logger.info.md b/docs/development/core/server/kibana-plugin-server.logger.info.md index 28a15f538f7394..f70ff3e750ab1f 100644 --- a/docs/development/core/server/kibana-plugin-server.logger.info.md +++ b/docs/development/core/server/kibana-plugin-server.logger.info.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [info](./kibana-plugin-server.logger.info.md) - -## Logger.info() method - -Logs messages related to general application flow - -Signature: - -```typescript -info(message: string, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| message | string | The log message | -| meta | LogMeta | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [info](./kibana-plugin-server.logger.info.md) + +## Logger.info() method + +Logs messages related to general application flow + +Signature: + +```typescript +info(message: string, meta?: LogMeta): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| message | string | The log message | +| meta | LogMeta | | + +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.logger.md b/docs/development/core/server/kibana-plugin-server.logger.md index 068f51f409f093..a8205dd5915a0e 100644 --- a/docs/development/core/server/kibana-plugin-server.logger.md +++ b/docs/development/core/server/kibana-plugin-server.logger.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) - -## Logger interface - -Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. - -Signature: - -```typescript -export interface Logger -``` - -## Methods - -| Method | Description | -| --- | --- | -| [debug(message, meta)](./kibana-plugin-server.logger.debug.md) | Log messages useful for debugging and interactive investigation | -| [error(errorOrMessage, meta)](./kibana-plugin-server.logger.error.md) | Logs abnormal or unexpected errors or messages that caused a failure in the application flow | -| [fatal(errorOrMessage, meta)](./kibana-plugin-server.logger.fatal.md) | Logs abnormal or unexpected errors or messages that caused an unrecoverable failure | -| [get(childContextPaths)](./kibana-plugin-server.logger.get.md) | Returns a new [Logger](./kibana-plugin-server.logger.md) instance extending the current logger context. | -| [info(message, meta)](./kibana-plugin-server.logger.info.md) | Logs messages related to general application flow | -| [trace(message, meta)](./kibana-plugin-server.logger.trace.md) | Log messages at the most detailed log level | -| [warn(errorOrMessage, meta)](./kibana-plugin-server.logger.warn.md) | Logs abnormal or unexpected errors or messages | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) + +## Logger interface + +Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. + +Signature: + +```typescript +export interface Logger +``` + +## Methods + +| Method | Description | +| --- | --- | +| [debug(message, meta)](./kibana-plugin-server.logger.debug.md) | Log messages useful for debugging and interactive investigation | +| [error(errorOrMessage, meta)](./kibana-plugin-server.logger.error.md) | Logs abnormal or unexpected errors or messages that caused a failure in the application flow | +| [fatal(errorOrMessage, meta)](./kibana-plugin-server.logger.fatal.md) | Logs abnormal or unexpected errors or messages that caused an unrecoverable failure | +| [get(childContextPaths)](./kibana-plugin-server.logger.get.md) | Returns a new [Logger](./kibana-plugin-server.logger.md) instance extending the current logger context. | +| [info(message, meta)](./kibana-plugin-server.logger.info.md) | Logs messages related to general application flow | +| [trace(message, meta)](./kibana-plugin-server.logger.trace.md) | Log messages at the most detailed log level | +| [warn(errorOrMessage, meta)](./kibana-plugin-server.logger.warn.md) | Logs abnormal or unexpected errors or messages | + diff --git a/docs/development/core/server/kibana-plugin-server.logger.trace.md b/docs/development/core/server/kibana-plugin-server.logger.trace.md index e7aeeec21243b0..8e9613ec39d5cb 100644 --- a/docs/development/core/server/kibana-plugin-server.logger.trace.md +++ b/docs/development/core/server/kibana-plugin-server.logger.trace.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [trace](./kibana-plugin-server.logger.trace.md) - -## Logger.trace() method - -Log messages at the most detailed log level - -Signature: - -```typescript -trace(message: string, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| message | string | The log message | -| meta | LogMeta | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [trace](./kibana-plugin-server.logger.trace.md) + +## Logger.trace() method + +Log messages at the most detailed log level + +Signature: + +```typescript +trace(message: string, meta?: LogMeta): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| message | string | The log message | +| meta | LogMeta | | + +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.logger.warn.md b/docs/development/core/server/kibana-plugin-server.logger.warn.md index 10e5cd5612fb2a..935718c0de7880 100644 --- a/docs/development/core/server/kibana-plugin-server.logger.warn.md +++ b/docs/development/core/server/kibana-plugin-server.logger.warn.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [warn](./kibana-plugin-server.logger.warn.md) - -## Logger.warn() method - -Logs abnormal or unexpected errors or messages - -Signature: - -```typescript -warn(errorOrMessage: string | Error, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| errorOrMessage | string | Error | An Error object or message string to log | -| meta | LogMeta | | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Logger](./kibana-plugin-server.logger.md) > [warn](./kibana-plugin-server.logger.warn.md) + +## Logger.warn() method + +Logs abnormal or unexpected errors or messages + +Signature: + +```typescript +warn(errorOrMessage: string | Error, meta?: LogMeta): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| errorOrMessage | string | Error | An Error object or message string to log | +| meta | LogMeta | | + +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.loggerfactory.get.md b/docs/development/core/server/kibana-plugin-server.loggerfactory.get.md index b38820f6ba4bab..95765157665a03 100644 --- a/docs/development/core/server/kibana-plugin-server.loggerfactory.get.md +++ b/docs/development/core/server/kibana-plugin-server.loggerfactory.get.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LoggerFactory](./kibana-plugin-server.loggerfactory.md) > [get](./kibana-plugin-server.loggerfactory.get.md) - -## LoggerFactory.get() method - -Returns a `Logger` instance for the specified context. - -Signature: - -```typescript -get(...contextParts: string[]): Logger; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| contextParts | string[] | Parts of the context to return logger for. For example get('plugins', 'pid') will return a logger for the plugins.pid context. | - -Returns: - -`Logger` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LoggerFactory](./kibana-plugin-server.loggerfactory.md) > [get](./kibana-plugin-server.loggerfactory.get.md) + +## LoggerFactory.get() method + +Returns a `Logger` instance for the specified context. + +Signature: + +```typescript +get(...contextParts: string[]): Logger; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| contextParts | string[] | Parts of the context to return logger for. For example get('plugins', 'pid') will return a logger for the plugins.pid context. | + +Returns: + +`Logger` + diff --git a/docs/development/core/server/kibana-plugin-server.loggerfactory.md b/docs/development/core/server/kibana-plugin-server.loggerfactory.md index 07d5a4c012c4a3..31e18ba4bb47bd 100644 --- a/docs/development/core/server/kibana-plugin-server.loggerfactory.md +++ b/docs/development/core/server/kibana-plugin-server.loggerfactory.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LoggerFactory](./kibana-plugin-server.loggerfactory.md) - -## LoggerFactory interface - -The single purpose of `LoggerFactory` interface is to define a way to retrieve a context-based logger instance. - -Signature: - -```typescript -export interface LoggerFactory -``` - -## Methods - -| Method | Description | -| --- | --- | -| [get(contextParts)](./kibana-plugin-server.loggerfactory.get.md) | Returns a Logger instance for the specified context. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LoggerFactory](./kibana-plugin-server.loggerfactory.md) + +## LoggerFactory interface + +The single purpose of `LoggerFactory` interface is to define a way to retrieve a context-based logger instance. + +Signature: + +```typescript +export interface LoggerFactory +``` + +## Methods + +| Method | Description | +| --- | --- | +| [get(contextParts)](./kibana-plugin-server.loggerfactory.get.md) | Returns a Logger instance for the specified context. | + diff --git a/docs/development/core/server/kibana-plugin-server.logmeta.md b/docs/development/core/server/kibana-plugin-server.logmeta.md index 268cb7419db169..11dbd01d7c8dc8 100644 --- a/docs/development/core/server/kibana-plugin-server.logmeta.md +++ b/docs/development/core/server/kibana-plugin-server.logmeta.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LogMeta](./kibana-plugin-server.logmeta.md) - -## LogMeta interface - -Contextual metadata - -Signature: - -```typescript -export interface LogMeta -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LogMeta](./kibana-plugin-server.logmeta.md) + +## LogMeta interface + +Contextual metadata + +Signature: + +```typescript +export interface LogMeta +``` diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md index 00ab83123319ac..e7b13346525406 100644 --- a/docs/development/core/server/kibana-plugin-server.md +++ b/docs/development/core/server/kibana-plugin-server.md @@ -1,223 +1,228 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) - -## kibana-plugin-server package - -The Kibana Core APIs for server-side plugins. - -A plugin requires a `kibana.json` file at it's root directory that follows [the manfiest schema](./kibana-plugin-server.pluginmanifest.md) to define static plugin information required to load the plugin. - -A plugin's `server/index` file must contain a named import, `plugin`, that implements [PluginInitializer](./kibana-plugin-server.plugininitializer.md) which returns an object that implements [Plugin](./kibana-plugin-server.plugin.md). - -The plugin integrates with the core system via lifecycle events: `setup`, `start`, and `stop`. In each lifecycle method, the plugin will receive the corresponding core services available (either [CoreSetup](./kibana-plugin-server.coresetup.md) or [CoreStart](./kibana-plugin-server.corestart.md)) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. - -## Classes - -| Class | Description | -| --- | --- | -| [BasePath](./kibana-plugin-server.basepath.md) | Access or manipulate the Kibana base path | -| [ClusterClient](./kibana-plugin-server.clusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). | -| [CspConfig](./kibana-plugin-server.cspconfig.md) | CSP configuration for use in Kibana. | -| [ElasticsearchErrorHelpers](./kibana-plugin-server.elasticsearcherrorhelpers.md) | Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as body.error.header[WWW-Authenticate] | -| [KibanaRequest](./kibana-plugin-server.kibanarequest.md) | Kibana specific abstraction for an incoming request. | -| [RouteValidationError](./kibana-plugin-server.routevalidationerror.md) | Error to return when the validation is not successful. | -| [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) | | -| [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) | | -| [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) | | -| [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). | - -## Enumerations - -| Enumeration | Description | -| --- | --- | -| [AuthResultType](./kibana-plugin-server.authresulttype.md) | | -| [AuthStatus](./kibana-plugin-server.authstatus.md) | Status indicating an outcome of the authentication. | - -## Interfaces - -| Interface | Description | -| --- | --- | -| [APICaller](./kibana-plugin-server.apicaller.md) | | -| [AssistanceAPIResponse](./kibana-plugin-server.assistanceapiresponse.md) | | -| [AssistantAPIClientParams](./kibana-plugin-server.assistantapiclientparams.md) | | -| [Authenticated](./kibana-plugin-server.authenticated.md) | | -| [AuthResultParams](./kibana-plugin-server.authresultparams.md) | Result of an incoming request authentication. | -| [AuthToolkit](./kibana-plugin-server.authtoolkit.md) | A tool set defining an outcome of Auth interceptor for incoming request. | -| [CallAPIOptions](./kibana-plugin-server.callapioptions.md) | The set of options that defines how API call should be made and result be processed. | -| [Capabilities](./kibana-plugin-server.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | -| [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) | APIs to manage the [Capabilities](./kibana-plugin-server.capabilities.md) that will be used by the application.Plugins relying on capabilities to toggle some of their features should register them during the setup phase using the registerProvider method.Plugins having the responsibility to restrict capabilities depending on a given context should register their capabilities switcher using the registerSwitcher method.Refers to the methods documentation for complete description and examples. | -| [CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) | APIs to access the application [Capabilities](./kibana-plugin-server.capabilities.md). | -| [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) | Provides helpers to generates the most commonly used [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) when invoking a [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md).See methods documentation for more detailed examples. | -| [ContextSetup](./kibana-plugin-server.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | -| [CoreSetup](./kibana-plugin-server.coresetup.md) | Context passed to the plugins setup method. | -| [CoreStart](./kibana-plugin-server.corestart.md) | Context passed to the plugins start method. | -| [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) | HTTP response parameters for a response with adjustable status code. | -| [DeprecationAPIClientParams](./kibana-plugin-server.deprecationapiclientparams.md) | | -| [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) | | -| [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) | | -| [DeprecationSettings](./kibana-plugin-server.deprecationsettings.md) | UiSettings deprecation field options. | -| [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | -| [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) | | -| [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | | -| [EnvironmentMode](./kibana-plugin-server.environmentmode.md) | | -| [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) | HTTP response parameters | -| [FakeRequest](./kibana-plugin-server.fakerequest.md) | Fake request object created manually by Kibana plugins. | -| [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) | HTTP response parameters | -| [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | Kibana HTTP Service provides own abstraction for work with HTTP stack. Plugins don't have direct access to hapi server and its primitives anymore. Moreover, plugins shouldn't rely on the fact that HTTP Service uses one or another library under the hood. This gives the platform flexibility to upgrade or changing our internal HTTP stack without breaking plugins. If the HTTP Service lacks functionality you need, we are happy to discuss and support your needs. | -| [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) | | -| [IContextContainer](./kibana-plugin-server.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | -| [ICspConfig](./kibana-plugin-server.icspconfig.md) | CSP configuration for use in Kibana. | -| [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) | A response data object, expected to returned as a result of [RequestHandler](./kibana-plugin-server.requesthandler.md) execution | -| [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) | A tiny abstraction for TCP socket. | -| [ImageValidation](./kibana-plugin-server.imagevalidation.md) | | -| [IndexSettingsDeprecationInfo](./kibana-plugin-server.indexsettingsdeprecationinfo.md) | | -| [IRenderOptions](./kibana-plugin-server.irenderoptions.md) | | -| [IRouter](./kibana-plugin-server.irouter.md) | Registers route handlers for specified resource path and method. See [RouteConfig](./kibana-plugin-server.routeconfig.md) and [RequestHandler](./kibana-plugin-server.requesthandler.md) for more information about arguments to route registrations. | -| [IScopedRenderingClient](./kibana-plugin-server.iscopedrenderingclient.md) | | -| [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) | Server-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. | -| [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) | Request specific route information exposed to a handler. | -| [LegacyRequest](./kibana-plugin-server.legacyrequest.md) | | -| [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) | | -| [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) | | -| [Logger](./kibana-plugin-server.logger.md) | Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. | -| [LoggerFactory](./kibana-plugin-server.loggerfactory.md) | The single purpose of LoggerFactory interface is to define a way to retrieve a context-based logger instance. | -| [LogMeta](./kibana-plugin-server.logmeta.md) | Contextual metadata | -| [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) | A tool set defining an outcome of OnPostAuth interceptor for incoming request. | -| [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | -| [OnPreResponseExtensions](./kibana-plugin-server.onpreresponseextensions.md) | Additional data to extend a response. | -| [OnPreResponseInfo](./kibana-plugin-server.onpreresponseinfo.md) | Response status code. | -| [OnPreResponseToolkit](./kibana-plugin-server.onpreresponsetoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | -| [PackageInfo](./kibana-plugin-server.packageinfo.md) | | -| [Plugin](./kibana-plugin-server.plugin.md) | The interface that should be returned by a PluginInitializer. | -| [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) | Describes a plugin configuration properties. | -| [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | -| [PluginManifest](./kibana-plugin-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | -| [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) | | -| [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) | | -| [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.Provides the following clients: - [rendering](./kibana-plugin-server.iscopedrenderingclient.md) - Rendering client which uses the data of the incoming request - [savedObjects.client](./kibana-plugin-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [elasticsearch.dataClient](./kibana-plugin-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [elasticsearch.adminClient](./kibana-plugin-server.scopedclusterclient.md) - Elasticsearch admin client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | -| [RouteConfig](./kibana-plugin-server.routeconfig.md) | Route specific configuration. | -| [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) | Additional route options. | -| [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) | Additional body options for a route | -| [RouteValidationResultFactory](./kibana-plugin-server.routevalidationresultfactory.md) | Validation result factory to be used in the custom validation function to return the valid data or validation errorsSee [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md). | -| [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) | The configuration object to the RouteValidator class. Set params, query and/or body to specify the validation logic to follow for that property. | -| [RouteValidatorOptions](./kibana-plugin-server.routevalidatoroptions.md) | Additional options for the RouteValidator class to modify its default behaviour. | -| [SavedObject](./kibana-plugin-server.savedobject.md) | | -| [SavedObjectAttributes](./kibana-plugin-server.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | -| [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) | A reference to another saved object. | -| [SavedObjectsBaseOptions](./kibana-plugin-server.savedobjectsbaseoptions.md) | | -| [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) | | -| [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) | | -| [SavedObjectsBulkResponse](./kibana-plugin-server.savedobjectsbulkresponse.md) | | -| [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) | | -| [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) | | -| [SavedObjectsBulkUpdateResponse](./kibana-plugin-server.savedobjectsbulkupdateresponse.md) | | -| [SavedObjectsClientProviderOptions](./kibana-plugin-server.savedobjectsclientprovideroptions.md) | Options to control the creation of the Saved Objects Client. | -| [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) | Options passed to each SavedObjectsClientWrapperFactory to aid in creating the wrapper instance. | -| [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) | | -| [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md) | | -| [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) | | -| [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) | Options controlling the export operation. | -| [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | -| [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) | | -| [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. | -| [SavedObjectsImportConflictError](./kibana-plugin-server.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. | -| [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) | Represents a failure to import. | -| [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. | -| [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) | Options to control the import operation. | -| [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) | The response describing the result of an import. | -| [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. | -| [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) | Represents a failure to import due to an unknown reason. | -| [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md) | Represents a failure to import due to having an unsupported saved object type. | -| [SavedObjectsIncrementCounterOptions](./kibana-plugin-server.savedobjectsincrementcounteroptions.md) | | -| [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) | | -| [SavedObjectsMigrationVersion](./kibana-plugin-server.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | -| [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) | A raw document as represented directly in the saved object index. | -| [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) | Options to control the "resolve import" operation. | -| [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for creating and registering Saved Object client wrappers. | -| [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceStart API provides a scoped Saved Objects client for interacting with Saved Objects. | -| [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) | | -| [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) | | -| [SessionCookieValidationResult](./kibana-plugin-server.sessioncookievalidationresult.md) | Return type from a function to validate cookie contents. | -| [SessionStorage](./kibana-plugin-server.sessionstorage.md) | Provides an interface to store and retrieve data across requests. | -| [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) | Configuration used to create HTTP session storage based on top of cookie mechanism. | -| [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) | SessionStorage factory to bind one to an incoming request | -| [StringValidation](./kibana-plugin-server.stringvalidation.md) | | -| [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) | UiSettings parameters defined by the plugins. | -| [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) | | -| [UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) | | -| [UserProvidedValues](./kibana-plugin-server.userprovidedvalues.md) | Describes the values explicitly set by user. | -| [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) | APIs to access the application's instance uuid. | - -## Variables - -| Variable | Description | -| --- | --- | -| [kibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Set of helpers used to create KibanaResponse to form HTTP response on an incoming request. Should be returned as a result of [RequestHandler](./kibana-plugin-server.requesthandler.md) execution. | -| [validBodyOutput](./kibana-plugin-server.validbodyoutput.md) | The set of valid body.output | - -## Type Aliases - -| Type Alias | Description | -| --- | --- | -| [AuthenticationHandler](./kibana-plugin-server.authenticationhandler.md) | See [AuthToolkit](./kibana-plugin-server.authtoolkit.md). | -| [AuthHeaders](./kibana-plugin-server.authheaders.md) | Auth Headers map | -| [AuthResult](./kibana-plugin-server.authresult.md) | | -| [CapabilitiesProvider](./kibana-plugin-server.capabilitiesprovider.md) | See [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) | -| [CapabilitiesSwitcher](./kibana-plugin-server.capabilitiesswitcher.md) | See [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) | -| [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) | Configuration deprecation returned from [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md) that handles a single deprecation from the configuration. | -| [ConfigDeprecationLogger](./kibana-plugin-server.configdeprecationlogger.md) | Logger interface used when invoking a [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) | -| [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md) | A provider that should returns a list of [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md).See [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) for more usage examples. | -| [ConfigPath](./kibana-plugin-server.configpath.md) | | -| [ElasticsearchClientConfig](./kibana-plugin-server.elasticsearchclientconfig.md) | | -| [GetAuthHeaders](./kibana-plugin-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | -| [GetAuthState](./kibana-plugin-server.getauthstate.md) | Get authentication state for a request. Returned by auth interceptor. | -| [HandlerContextType](./kibana-plugin-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md) to represent the type of the context. | -| [HandlerFunction](./kibana-plugin-server.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-server.icontextcontainer.md) | -| [HandlerParameters](./kibana-plugin-server.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-server.handlercontexttype.md). | -| [Headers](./kibana-plugin-server.headers.md) | Http request headers to read. | -| [HttpResponsePayload](./kibana-plugin-server.httpresponsepayload.md) | Data send to the client as a response payload. | -| [IBasePath](./kibana-plugin-server.ibasepath.md) | Access or manipulate the Kibana base path[BasePath](./kibana-plugin-server.basepath.md) | -| [IClusterClient](./kibana-plugin-server.iclusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). | -| [IContextProvider](./kibana-plugin-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | -| [ICustomClusterClient](./kibana-plugin-server.icustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). | -| [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) | Return authentication status for a request. | -| [ISavedObjectsRepository](./kibana-plugin-server.isavedobjectsrepository.md) | See [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) | -| [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). | -| [KibanaRequestRouteOptions](./kibana-plugin-server.kibanarequestrouteoptions.md) | Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. | -| [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. | -| [KnownHeaders](./kibana-plugin-server.knownheaders.md) | Set of well-known HTTP headers. | -| [LifecycleResponseFactory](./kibana-plugin-server.lifecycleresponsefactory.md) | Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. | -| [MIGRATION\_ASSISTANCE\_INDEX\_ACTION](./kibana-plugin-server.migration_assistance_index_action.md) | | -| [MIGRATION\_DEPRECATION\_LEVEL](./kibana-plugin-server.migration_deprecation_level.md) | | -| [MutatingOperationRefreshSetting](./kibana-plugin-server.mutatingoperationrefreshsetting.md) | Elasticsearch Refresh setting for mutating operation | -| [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md) | See [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md). | -| [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md) | See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). | -| [OnPreResponseHandler](./kibana-plugin-server.onpreresponsehandler.md) | See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). | -| [PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) | Dedicated type for plugin configuration schema. | -| [PluginInitializer](./kibana-plugin-server.plugininitializer.md) | The plugin export at the root of a plugin's server directory should conform to this interface. | -| [PluginName](./kibana-plugin-server.pluginname.md) | Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. | -| [PluginOpaqueId](./kibana-plugin-server.pluginopaqueid.md) | | -| [RecursiveReadonly](./kibana-plugin-server.recursivereadonly.md) | | -| [RedirectResponseOptions](./kibana-plugin-server.redirectresponseoptions.md) | HTTP response parameters for redirection response | -| [RequestHandler](./kibana-plugin-server.requesthandler.md) | A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) functions. | -| [RequestHandlerContextContainer](./kibana-plugin-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. | -| [RequestHandlerContextProvider](./kibana-plugin-server.requesthandlercontextprovider.md) | Context provider for request handler. Extends request context object with provided functionality or data. | -| [ResponseError](./kibana-plugin-server.responseerror.md) | Error message and optional data send to the client in case of error. | -| [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) | Additional data to provide error details. | -| [ResponseHeaders](./kibana-plugin-server.responseheaders.md) | Http response headers to set. | -| [RouteContentType](./kibana-plugin-server.routecontenttype.md) | The set of supported parseable Content-Types | -| [RouteMethod](./kibana-plugin-server.routemethod.md) | The set of common HTTP methods supported by Kibana routing. | -| [RouteRegistrar](./kibana-plugin-server.routeregistrar.md) | Route handler common definition | -| [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md) | The custom validation function if @kbn/config-schema is not a valid solution for your specific plugin requirements. | -| [RouteValidationSpec](./kibana-plugin-server.routevalidationspec.md) | Allowed property validation options: either @kbn/config-schema validations or custom validation functionsSee [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md) for custom validation. | -| [RouteValidatorFullConfig](./kibana-plugin-server.routevalidatorfullconfig.md) | Route validations config and options merged into one object | -| [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) | Type definition for a Saved Object attribute value | -| [SavedObjectAttributeSingle](./kibana-plugin-server.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) | -| [SavedObjectsClientContract](./kibana-plugin-server.savedobjectsclientcontract.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state.\#\# SavedObjectsClient errorsSince the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either:1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md)Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the isXYZError() helpers exposed at SavedObjectsErrorHelpers should be used to understand and manage error responses from the SavedObjectsClient.Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for error.body.error.type or doing substring checks on error.body.error.reason, just use the helpers to understand the meaning of the error:\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 }if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know }// always rethrow the error unless you handle it throw error; \`\`\`\#\#\# 404s from missing indexFrom the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing.At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages.From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing.\#\#\# 503s from missing indexUnlike all other methods, create requests are supposed to succeed even when the Kibana index does not exist because it will be automatically created by elasticsearch. When that is not the case it is because Elasticsearch's action.auto_create_index setting prevents it from being created automatically so we throw a special 503 with the intention of informing the user that their Elasticsearch settings need to be updated.See [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) See [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) | -| [SavedObjectsClientFactory](./kibana-plugin-server.savedobjectsclientfactory.md) | Describes the factory used to create instances of the Saved Objects Client. | -| [SavedObjectsClientWrapperFactory](./kibana-plugin-server.savedobjectsclientwrapperfactory.md) | Describes the factory used to create instances of Saved Objects Client Wrappers. | -| [ScopeableRequest](./kibana-plugin-server.scopeablerequest.md) | A user credentials container. It accommodates the necessary auth credentials to impersonate the current user.See [KibanaRequest](./kibana-plugin-server.kibanarequest.md). | -| [SharedGlobalConfig](./kibana-plugin-server.sharedglobalconfig.md) | | -| [UiSettingsType](./kibana-plugin-server.uisettingstype.md) | UI element type to represent the settings. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) + +## kibana-plugin-server package + +The Kibana Core APIs for server-side plugins. + +A plugin requires a `kibana.json` file at it's root directory that follows [the manfiest schema](./kibana-plugin-server.pluginmanifest.md) to define static plugin information required to load the plugin. + +A plugin's `server/index` file must contain a named import, `plugin`, that implements [PluginInitializer](./kibana-plugin-server.plugininitializer.md) which returns an object that implements [Plugin](./kibana-plugin-server.plugin.md). + +The plugin integrates with the core system via lifecycle events: `setup`, `start`, and `stop`. In each lifecycle method, the plugin will receive the corresponding core services available (either [CoreSetup](./kibana-plugin-server.coresetup.md) or [CoreStart](./kibana-plugin-server.corestart.md)) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. + +## Classes + +| Class | Description | +| --- | --- | +| [BasePath](./kibana-plugin-server.basepath.md) | Access or manipulate the Kibana base path | +| [ClusterClient](./kibana-plugin-server.clusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). | +| [CspConfig](./kibana-plugin-server.cspconfig.md) | CSP configuration for use in Kibana. | +| [ElasticsearchErrorHelpers](./kibana-plugin-server.elasticsearcherrorhelpers.md) | Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as body.error.header[WWW-Authenticate] | +| [KibanaRequest](./kibana-plugin-server.kibanarequest.md) | Kibana specific abstraction for an incoming request. | +| [RouteValidationError](./kibana-plugin-server.routevalidationerror.md) | Error to return when the validation is not successful. | +| [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) | | +| [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) | | +| [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) | | +| [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). | + +## Enumerations + +| Enumeration | Description | +| --- | --- | +| [AuthResultType](./kibana-plugin-server.authresulttype.md) | | +| [AuthStatus](./kibana-plugin-server.authstatus.md) | Status indicating an outcome of the authentication. | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [APICaller](./kibana-plugin-server.apicaller.md) | | +| [AssistanceAPIResponse](./kibana-plugin-server.assistanceapiresponse.md) | | +| [AssistantAPIClientParams](./kibana-plugin-server.assistantapiclientparams.md) | | +| [Authenticated](./kibana-plugin-server.authenticated.md) | | +| [AuthResultParams](./kibana-plugin-server.authresultparams.md) | Result of an incoming request authentication. | +| [AuthToolkit](./kibana-plugin-server.authtoolkit.md) | A tool set defining an outcome of Auth interceptor for incoming request. | +| [CallAPIOptions](./kibana-plugin-server.callapioptions.md) | The set of options that defines how API call should be made and result be processed. | +| [Capabilities](./kibana-plugin-server.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | +| [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) | APIs to manage the [Capabilities](./kibana-plugin-server.capabilities.md) that will be used by the application.Plugins relying on capabilities to toggle some of their features should register them during the setup phase using the registerProvider method.Plugins having the responsibility to restrict capabilities depending on a given context should register their capabilities switcher using the registerSwitcher method.Refers to the methods documentation for complete description and examples. | +| [CapabilitiesStart](./kibana-plugin-server.capabilitiesstart.md) | APIs to access the application [Capabilities](./kibana-plugin-server.capabilities.md). | +| [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) | Provides helpers to generates the most commonly used [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) when invoking a [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md).See methods documentation for more detailed examples. | +| [ContextSetup](./kibana-plugin-server.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | +| [CoreSetup](./kibana-plugin-server.coresetup.md) | Context passed to the plugins setup method. | +| [CoreStart](./kibana-plugin-server.corestart.md) | Context passed to the plugins start method. | +| [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) | HTTP response parameters for a response with adjustable status code. | +| [DeprecationAPIClientParams](./kibana-plugin-server.deprecationapiclientparams.md) | | +| [DeprecationAPIResponse](./kibana-plugin-server.deprecationapiresponse.md) | | +| [DeprecationInfo](./kibana-plugin-server.deprecationinfo.md) | | +| [DeprecationSettings](./kibana-plugin-server.deprecationsettings.md) | UiSettings deprecation field options. | +| [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | +| [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) | | +| [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | | +| [EnvironmentMode](./kibana-plugin-server.environmentmode.md) | | +| [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) | HTTP response parameters | +| [FakeRequest](./kibana-plugin-server.fakerequest.md) | Fake request object created manually by Kibana plugins. | +| [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) | HTTP response parameters | +| [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | Kibana HTTP Service provides own abstraction for work with HTTP stack. Plugins don't have direct access to hapi server and its primitives anymore. Moreover, plugins shouldn't rely on the fact that HTTP Service uses one or another library under the hood. This gives the platform flexibility to upgrade or changing our internal HTTP stack without breaking plugins. If the HTTP Service lacks functionality you need, we are happy to discuss and support your needs. | +| [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) | | +| [IContextContainer](./kibana-plugin-server.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | +| [ICspConfig](./kibana-plugin-server.icspconfig.md) | CSP configuration for use in Kibana. | +| [IKibanaResponse](./kibana-plugin-server.ikibanaresponse.md) | A response data object, expected to returned as a result of [RequestHandler](./kibana-plugin-server.requesthandler.md) execution | +| [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) | A tiny abstraction for TCP socket. | +| [ImageValidation](./kibana-plugin-server.imagevalidation.md) | | +| [IndexSettingsDeprecationInfo](./kibana-plugin-server.indexsettingsdeprecationinfo.md) | | +| [IRenderOptions](./kibana-plugin-server.irenderoptions.md) | | +| [IRouter](./kibana-plugin-server.irouter.md) | Registers route handlers for specified resource path and method. See [RouteConfig](./kibana-plugin-server.routeconfig.md) and [RequestHandler](./kibana-plugin-server.requesthandler.md) for more information about arguments to route registrations. | +| [IScopedRenderingClient](./kibana-plugin-server.iscopedrenderingclient.md) | | +| [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) | Server-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. | +| [KibanaRequestEvents](./kibana-plugin-server.kibanarequestevents.md) | Request events. | +| [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) | Request specific route information exposed to a handler. | +| [LegacyRequest](./kibana-plugin-server.legacyrequest.md) | | +| [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) | | +| [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) | | +| [Logger](./kibana-plugin-server.logger.md) | Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. | +| [LoggerFactory](./kibana-plugin-server.loggerfactory.md) | The single purpose of LoggerFactory interface is to define a way to retrieve a context-based logger instance. | +| [LogMeta](./kibana-plugin-server.logmeta.md) | Contextual metadata | +| [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) | A tool set defining an outcome of OnPostAuth interceptor for incoming request. | +| [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | +| [OnPreResponseExtensions](./kibana-plugin-server.onpreresponseextensions.md) | Additional data to extend a response. | +| [OnPreResponseInfo](./kibana-plugin-server.onpreresponseinfo.md) | Response status code. | +| [OnPreResponseToolkit](./kibana-plugin-server.onpreresponsetoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | +| [PackageInfo](./kibana-plugin-server.packageinfo.md) | | +| [Plugin](./kibana-plugin-server.plugin.md) | The interface that should be returned by a PluginInitializer. | +| [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) | Describes a plugin configuration properties. | +| [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | +| [PluginManifest](./kibana-plugin-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | +| [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) | | +| [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) | | +| [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.Provides the following clients: - [rendering](./kibana-plugin-server.iscopedrenderingclient.md) - Rendering client which uses the data of the incoming request - [savedObjects.client](./kibana-plugin-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [elasticsearch.dataClient](./kibana-plugin-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [elasticsearch.adminClient](./kibana-plugin-server.scopedclusterclient.md) - Elasticsearch admin client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | +| [RouteConfig](./kibana-plugin-server.routeconfig.md) | Route specific configuration. | +| [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) | Additional route options. | +| [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) | Additional body options for a route | +| [RouteValidationResultFactory](./kibana-plugin-server.routevalidationresultfactory.md) | Validation result factory to be used in the custom validation function to return the valid data or validation errorsSee [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md). | +| [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) | The configuration object to the RouteValidator class. Set params, query and/or body to specify the validation logic to follow for that property. | +| [RouteValidatorOptions](./kibana-plugin-server.routevalidatoroptions.md) | Additional options for the RouteValidator class to modify its default behaviour. | +| [SavedObject](./kibana-plugin-server.savedobject.md) | | +| [SavedObjectAttributes](./kibana-plugin-server.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | +| [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) | A reference to another saved object. | +| [SavedObjectsBaseOptions](./kibana-plugin-server.savedobjectsbaseoptions.md) | | +| [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) | | +| [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) | | +| [SavedObjectsBulkResponse](./kibana-plugin-server.savedobjectsbulkresponse.md) | | +| [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) | | +| [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) | | +| [SavedObjectsBulkUpdateResponse](./kibana-plugin-server.savedobjectsbulkupdateresponse.md) | | +| [SavedObjectsClientProviderOptions](./kibana-plugin-server.savedobjectsclientprovideroptions.md) | Options to control the creation of the Saved Objects Client. | +| [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) | Options passed to each SavedObjectsClientWrapperFactory to aid in creating the wrapper instance. | +| [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) | | +| [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md) | | +| [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) | | +| [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) | Options controlling the export operation. | +| [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | +| [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) | | +| [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. | +| [SavedObjectsImportConflictError](./kibana-plugin-server.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. | +| [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) | Represents a failure to import. | +| [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. | +| [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) | Options to control the import operation. | +| [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) | The response describing the result of an import. | +| [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. | +| [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) | Represents a failure to import due to an unknown reason. | +| [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md) | Represents a failure to import due to having an unsupported saved object type. | +| [SavedObjectsIncrementCounterOptions](./kibana-plugin-server.savedobjectsincrementcounteroptions.md) | | +| [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) | | +| [SavedObjectsMigrationVersion](./kibana-plugin-server.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) | A raw document as represented directly in the saved object index. | +| [SavedObjectsRepositoryFactory](./kibana-plugin-server.savedobjectsrepositoryfactory.md) | Factory provided when invoking a [client factory provider](./kibana-plugin-server.savedobjectsclientfactoryprovider.md) See [SavedObjectsServiceSetup.setClientFactoryProvider](./kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md) | +| [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) | Options to control the "resolve import" operation. | +| [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) | Saved Objects is Kibana's data persistence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for creating and registering Saved Object client wrappers. | +| [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceStart API provides a scoped Saved Objects client for interacting with Saved Objects. | +| [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) | | +| [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) | | +| [SessionCookieValidationResult](./kibana-plugin-server.sessioncookievalidationresult.md) | Return type from a function to validate cookie contents. | +| [SessionStorage](./kibana-plugin-server.sessionstorage.md) | Provides an interface to store and retrieve data across requests. | +| [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) | Configuration used to create HTTP session storage based on top of cookie mechanism. | +| [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) | SessionStorage factory to bind one to an incoming request | +| [StringValidationRegex](./kibana-plugin-server.stringvalidationregex.md) | StringValidation with regex object | +| [StringValidationRegexString](./kibana-plugin-server.stringvalidationregexstring.md) | StringValidation as regex string | +| [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) | UiSettings parameters defined by the plugins. | +| [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) | | +| [UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) | | +| [UserProvidedValues](./kibana-plugin-server.userprovidedvalues.md) | Describes the values explicitly set by user. | +| [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) | APIs to access the application's instance uuid. | + +## Variables + +| Variable | Description | +| --- | --- | +| [kibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Set of helpers used to create KibanaResponse to form HTTP response on an incoming request. Should be returned as a result of [RequestHandler](./kibana-plugin-server.requesthandler.md) execution. | +| [validBodyOutput](./kibana-plugin-server.validbodyoutput.md) | The set of valid body.output | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [AuthenticationHandler](./kibana-plugin-server.authenticationhandler.md) | See [AuthToolkit](./kibana-plugin-server.authtoolkit.md). | +| [AuthHeaders](./kibana-plugin-server.authheaders.md) | Auth Headers map | +| [AuthResult](./kibana-plugin-server.authresult.md) | | +| [CapabilitiesProvider](./kibana-plugin-server.capabilitiesprovider.md) | See [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) | +| [CapabilitiesSwitcher](./kibana-plugin-server.capabilitiesswitcher.md) | See [CapabilitiesSetup](./kibana-plugin-server.capabilitiessetup.md) | +| [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) | Configuration deprecation returned from [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md) that handles a single deprecation from the configuration. | +| [ConfigDeprecationLogger](./kibana-plugin-server.configdeprecationlogger.md) | Logger interface used when invoking a [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) | +| [ConfigDeprecationProvider](./kibana-plugin-server.configdeprecationprovider.md) | A provider that should returns a list of [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md).See [ConfigDeprecationFactory](./kibana-plugin-server.configdeprecationfactory.md) for more usage examples. | +| [ConfigPath](./kibana-plugin-server.configpath.md) | | +| [ElasticsearchClientConfig](./kibana-plugin-server.elasticsearchclientconfig.md) | | +| [GetAuthHeaders](./kibana-plugin-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | +| [GetAuthState](./kibana-plugin-server.getauthstate.md) | Gets authentication state for a request. Returned by auth interceptor. | +| [HandlerContextType](./kibana-plugin-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md) to represent the type of the context. | +| [HandlerFunction](./kibana-plugin-server.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-server.icontextcontainer.md) | +| [HandlerParameters](./kibana-plugin-server.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-server.handlercontexttype.md). | +| [Headers](./kibana-plugin-server.headers.md) | Http request headers to read. | +| [HttpResponsePayload](./kibana-plugin-server.httpresponsepayload.md) | Data send to the client as a response payload. | +| [IBasePath](./kibana-plugin-server.ibasepath.md) | Access or manipulate the Kibana base path[BasePath](./kibana-plugin-server.basepath.md) | +| [IClusterClient](./kibana-plugin-server.iclusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). | +| [IContextProvider](./kibana-plugin-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | +| [ICustomClusterClient](./kibana-plugin-server.icustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). | +| [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) | Returns authentication status for a request. | +| [ISavedObjectsRepository](./kibana-plugin-server.isavedobjectsrepository.md) | See [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) | +| [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). | +| [KibanaRequestRouteOptions](./kibana-plugin-server.kibanarequestrouteoptions.md) | Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. | +| [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. | +| [KnownHeaders](./kibana-plugin-server.knownheaders.md) | Set of well-known HTTP headers. | +| [LifecycleResponseFactory](./kibana-plugin-server.lifecycleresponsefactory.md) | Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. | +| [MIGRATION\_ASSISTANCE\_INDEX\_ACTION](./kibana-plugin-server.migration_assistance_index_action.md) | | +| [MIGRATION\_DEPRECATION\_LEVEL](./kibana-plugin-server.migration_deprecation_level.md) | | +| [MutatingOperationRefreshSetting](./kibana-plugin-server.mutatingoperationrefreshsetting.md) | Elasticsearch Refresh setting for mutating operation | +| [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md) | See [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md). | +| [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md) | See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). | +| [OnPreResponseHandler](./kibana-plugin-server.onpreresponsehandler.md) | See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). | +| [PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) | Dedicated type for plugin configuration schema. | +| [PluginInitializer](./kibana-plugin-server.plugininitializer.md) | The plugin export at the root of a plugin's server directory should conform to this interface. | +| [PluginName](./kibana-plugin-server.pluginname.md) | Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. | +| [PluginOpaqueId](./kibana-plugin-server.pluginopaqueid.md) | | +| [RecursiveReadonly](./kibana-plugin-server.recursivereadonly.md) | | +| [RedirectResponseOptions](./kibana-plugin-server.redirectresponseoptions.md) | HTTP response parameters for redirection response | +| [RequestHandler](./kibana-plugin-server.requesthandler.md) | A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) functions. | +| [RequestHandlerContextContainer](./kibana-plugin-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. | +| [RequestHandlerContextProvider](./kibana-plugin-server.requesthandlercontextprovider.md) | Context provider for request handler. Extends request context object with provided functionality or data. | +| [ResponseError](./kibana-plugin-server.responseerror.md) | Error message and optional data send to the client in case of error. | +| [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) | Additional data to provide error details. | +| [ResponseHeaders](./kibana-plugin-server.responseheaders.md) | Http response headers to set. | +| [RouteContentType](./kibana-plugin-server.routecontenttype.md) | The set of supported parseable Content-Types | +| [RouteMethod](./kibana-plugin-server.routemethod.md) | The set of common HTTP methods supported by Kibana routing. | +| [RouteRegistrar](./kibana-plugin-server.routeregistrar.md) | Route handler common definition | +| [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md) | The custom validation function if @kbn/config-schema is not a valid solution for your specific plugin requirements. | +| [RouteValidationSpec](./kibana-plugin-server.routevalidationspec.md) | Allowed property validation options: either @kbn/config-schema validations or custom validation functionsSee [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md) for custom validation. | +| [RouteValidatorFullConfig](./kibana-plugin-server.routevalidatorfullconfig.md) | Route validations config and options merged into one object | +| [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) | Type definition for a Saved Object attribute value | +| [SavedObjectAttributeSingle](./kibana-plugin-server.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) | +| [SavedObjectsClientContract](./kibana-plugin-server.savedobjectsclientcontract.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state.\#\# SavedObjectsClient errorsSince the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either:1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md)Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the isXYZError() helpers exposed at SavedObjectsErrorHelpers should be used to understand and manage error responses from the SavedObjectsClient.Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for error.body.error.type or doing substring checks on error.body.error.reason, just use the helpers to understand the meaning of the error:\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 }if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know }// always rethrow the error unless you handle it throw error; \`\`\`\#\#\# 404s from missing indexFrom the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing.At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages.From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing.\#\#\# 503s from missing indexUnlike all other methods, create requests are supposed to succeed even when the Kibana index does not exist because it will be automatically created by elasticsearch. When that is not the case it is because Elasticsearch's action.auto_create_index setting prevents it from being created automatically so we throw a special 503 with the intention of informing the user that their Elasticsearch settings need to be updated.See [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) See [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) | +| [SavedObjectsClientFactory](./kibana-plugin-server.savedobjectsclientfactory.md) | Describes the factory used to create instances of the Saved Objects Client. | +| [SavedObjectsClientFactoryProvider](./kibana-plugin-server.savedobjectsclientfactoryprovider.md) | Provider to invoke to retrieve a [SavedObjectsClientFactory](./kibana-plugin-server.savedobjectsclientfactory.md). | +| [SavedObjectsClientWrapperFactory](./kibana-plugin-server.savedobjectsclientwrapperfactory.md) | Describes the factory used to create instances of Saved Objects Client Wrappers. | +| [ScopeableRequest](./kibana-plugin-server.scopeablerequest.md) | A user credentials container. It accommodates the necessary auth credentials to impersonate the current user.See [KibanaRequest](./kibana-plugin-server.kibanarequest.md). | +| [SharedGlobalConfig](./kibana-plugin-server.sharedglobalconfig.md) | | +| [StringValidation](./kibana-plugin-server.stringvalidation.md) | Allows regex objects or a regex string | +| [UiSettingsType](./kibana-plugin-server.uisettingstype.md) | UI element type to represent the settings. | + diff --git a/docs/development/core/server/kibana-plugin-server.migration_assistance_index_action.md b/docs/development/core/server/kibana-plugin-server.migration_assistance_index_action.md index e5ecc6779b2822..879412e3a8ca89 100644 --- a/docs/development/core/server/kibana-plugin-server.migration_assistance_index_action.md +++ b/docs/development/core/server/kibana-plugin-server.migration_assistance_index_action.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [MIGRATION\_ASSISTANCE\_INDEX\_ACTION](./kibana-plugin-server.migration_assistance_index_action.md) - -## MIGRATION\_ASSISTANCE\_INDEX\_ACTION type - - -Signature: - -```typescript -export declare type MIGRATION_ASSISTANCE_INDEX_ACTION = 'upgrade' | 'reindex'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [MIGRATION\_ASSISTANCE\_INDEX\_ACTION](./kibana-plugin-server.migration_assistance_index_action.md) + +## MIGRATION\_ASSISTANCE\_INDEX\_ACTION type + + +Signature: + +```typescript +export declare type MIGRATION_ASSISTANCE_INDEX_ACTION = 'upgrade' | 'reindex'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.migration_deprecation_level.md b/docs/development/core/server/kibana-plugin-server.migration_deprecation_level.md index 33e02a1b2bce00..00f018da02d18c 100644 --- a/docs/development/core/server/kibana-plugin-server.migration_deprecation_level.md +++ b/docs/development/core/server/kibana-plugin-server.migration_deprecation_level.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [MIGRATION\_DEPRECATION\_LEVEL](./kibana-plugin-server.migration_deprecation_level.md) - -## MIGRATION\_DEPRECATION\_LEVEL type - - -Signature: - -```typescript -export declare type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [MIGRATION\_DEPRECATION\_LEVEL](./kibana-plugin-server.migration_deprecation_level.md) + +## MIGRATION\_DEPRECATION\_LEVEL type + + +Signature: + +```typescript +export declare type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.mutatingoperationrefreshsetting.md b/docs/development/core/server/kibana-plugin-server.mutatingoperationrefreshsetting.md index 94c8fa8c22ef62..7d2187bec6c256 100644 --- a/docs/development/core/server/kibana-plugin-server.mutatingoperationrefreshsetting.md +++ b/docs/development/core/server/kibana-plugin-server.mutatingoperationrefreshsetting.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [MutatingOperationRefreshSetting](./kibana-plugin-server.mutatingoperationrefreshsetting.md) - -## MutatingOperationRefreshSetting type - -Elasticsearch Refresh setting for mutating operation - -Signature: - -```typescript -export declare type MutatingOperationRefreshSetting = boolean | 'wait_for'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [MutatingOperationRefreshSetting](./kibana-plugin-server.mutatingoperationrefreshsetting.md) + +## MutatingOperationRefreshSetting type + +Elasticsearch Refresh setting for mutating operation + +Signature: + +```typescript +export declare type MutatingOperationRefreshSetting = boolean | 'wait_for'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpostauthhandler.md b/docs/development/core/server/kibana-plugin-server.onpostauthhandler.md index a887dea26e3bc0..3191ca0f38002a 100644 --- a/docs/development/core/server/kibana-plugin-server.onpostauthhandler.md +++ b/docs/development/core/server/kibana-plugin-server.onpostauthhandler.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md) - -## OnPostAuthHandler type - -See [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md). - -Signature: - -```typescript -export declare type OnPostAuthHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: OnPostAuthToolkit) => OnPostAuthResult | KibanaResponse | Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md) + +## OnPostAuthHandler type + +See [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md). + +Signature: + +```typescript +export declare type OnPostAuthHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: OnPostAuthToolkit) => OnPostAuthResult | KibanaResponse | Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpostauthtoolkit.md b/docs/development/core/server/kibana-plugin-server.onpostauthtoolkit.md index 001c14c53fecb3..9e73a77fc4b0c8 100644 --- a/docs/development/core/server/kibana-plugin-server.onpostauthtoolkit.md +++ b/docs/development/core/server/kibana-plugin-server.onpostauthtoolkit.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) - -## OnPostAuthToolkit interface - -A tool set defining an outcome of OnPostAuth interceptor for incoming request. - -Signature: - -```typescript -export interface OnPostAuthToolkit -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [next](./kibana-plugin-server.onpostauthtoolkit.next.md) | () => OnPostAuthResult | To pass request to the next handler | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) + +## OnPostAuthToolkit interface + +A tool set defining an outcome of OnPostAuth interceptor for incoming request. + +Signature: + +```typescript +export interface OnPostAuthToolkit +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [next](./kibana-plugin-server.onpostauthtoolkit.next.md) | () => OnPostAuthResult | To pass request to the next handler | + diff --git a/docs/development/core/server/kibana-plugin-server.onpostauthtoolkit.next.md b/docs/development/core/server/kibana-plugin-server.onpostauthtoolkit.next.md index cc9120defa442a..877f41e49c4933 100644 --- a/docs/development/core/server/kibana-plugin-server.onpostauthtoolkit.next.md +++ b/docs/development/core/server/kibana-plugin-server.onpostauthtoolkit.next.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) > [next](./kibana-plugin-server.onpostauthtoolkit.next.md) - -## OnPostAuthToolkit.next property - -To pass request to the next handler - -Signature: - -```typescript -next: () => OnPostAuthResult; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) > [next](./kibana-plugin-server.onpostauthtoolkit.next.md) + +## OnPostAuthToolkit.next property + +To pass request to the next handler + +Signature: + +```typescript +next: () => OnPostAuthResult; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpreauthhandler.md b/docs/development/core/server/kibana-plugin-server.onpreauthhandler.md index 003bd4b19eadfc..dee943f6ee3b51 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreauthhandler.md +++ b/docs/development/core/server/kibana-plugin-server.onpreauthhandler.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md) - -## OnPreAuthHandler type - -See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). - -Signature: - -```typescript -export declare type OnPreAuthHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: OnPreAuthToolkit) => OnPreAuthResult | KibanaResponse | Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md) + +## OnPreAuthHandler type + +See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). + +Signature: + +```typescript +export declare type OnPreAuthHandler = (request: KibanaRequest, response: LifecycleResponseFactory, toolkit: OnPreAuthToolkit) => OnPreAuthResult | KibanaResponse | Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.md b/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.md index 174f377eec292f..166eee8759df47 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.md +++ b/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) - -## OnPreAuthToolkit interface - -A tool set defining an outcome of OnPreAuth interceptor for incoming request. - -Signature: - -```typescript -export interface OnPreAuthToolkit -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [next](./kibana-plugin-server.onpreauthtoolkit.next.md) | () => OnPreAuthResult | To pass request to the next handler | -| [rewriteUrl](./kibana-plugin-server.onpreauthtoolkit.rewriteurl.md) | (url: string) => OnPreAuthResult | Rewrite requested resources url before is was authenticated and routed to a handler | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) + +## OnPreAuthToolkit interface + +A tool set defining an outcome of OnPreAuth interceptor for incoming request. + +Signature: + +```typescript +export interface OnPreAuthToolkit +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [next](./kibana-plugin-server.onpreauthtoolkit.next.md) | () => OnPreAuthResult | To pass request to the next handler | +| [rewriteUrl](./kibana-plugin-server.onpreauthtoolkit.rewriteurl.md) | (url: string) => OnPreAuthResult | Rewrite requested resources url before is was authenticated and routed to a handler | + diff --git a/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.next.md b/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.next.md index 9281e5879ce9ba..37909cbd8b24b2 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.next.md +++ b/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.next.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) > [next](./kibana-plugin-server.onpreauthtoolkit.next.md) - -## OnPreAuthToolkit.next property - -To pass request to the next handler - -Signature: - -```typescript -next: () => OnPreAuthResult; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) > [next](./kibana-plugin-server.onpreauthtoolkit.next.md) + +## OnPreAuthToolkit.next property + +To pass request to the next handler + +Signature: + +```typescript +next: () => OnPreAuthResult; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.rewriteurl.md b/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.rewriteurl.md index 0f401379c20fdf..c7d97b31c364cc 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.rewriteurl.md +++ b/docs/development/core/server/kibana-plugin-server.onpreauthtoolkit.rewriteurl.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) > [rewriteUrl](./kibana-plugin-server.onpreauthtoolkit.rewriteurl.md) - -## OnPreAuthToolkit.rewriteUrl property - -Rewrite requested resources url before is was authenticated and routed to a handler - -Signature: - -```typescript -rewriteUrl: (url: string) => OnPreAuthResult; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) > [rewriteUrl](./kibana-plugin-server.onpreauthtoolkit.rewriteurl.md) + +## OnPreAuthToolkit.rewriteUrl property + +Rewrite requested resources url before is was authenticated and routed to a handler + +Signature: + +```typescript +rewriteUrl: (url: string) => OnPreAuthResult; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpreresponseextensions.headers.md b/docs/development/core/server/kibana-plugin-server.onpreresponseextensions.headers.md index 8736020daf0638..28fa2fd4a3035b 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreresponseextensions.headers.md +++ b/docs/development/core/server/kibana-plugin-server.onpreresponseextensions.headers.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseExtensions](./kibana-plugin-server.onpreresponseextensions.md) > [headers](./kibana-plugin-server.onpreresponseextensions.headers.md) - -## OnPreResponseExtensions.headers property - -additional headers to attach to the response - -Signature: - -```typescript -headers?: ResponseHeaders; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseExtensions](./kibana-plugin-server.onpreresponseextensions.md) > [headers](./kibana-plugin-server.onpreresponseextensions.headers.md) + +## OnPreResponseExtensions.headers property + +additional headers to attach to the response + +Signature: + +```typescript +headers?: ResponseHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpreresponseextensions.md b/docs/development/core/server/kibana-plugin-server.onpreresponseextensions.md index e5aa624c39909a..7fd85e2371e0f1 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreresponseextensions.md +++ b/docs/development/core/server/kibana-plugin-server.onpreresponseextensions.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseExtensions](./kibana-plugin-server.onpreresponseextensions.md) - -## OnPreResponseExtensions interface - -Additional data to extend a response. - -Signature: - -```typescript -export interface OnPreResponseExtensions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [headers](./kibana-plugin-server.onpreresponseextensions.headers.md) | ResponseHeaders | additional headers to attach to the response | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseExtensions](./kibana-plugin-server.onpreresponseextensions.md) + +## OnPreResponseExtensions interface + +Additional data to extend a response. + +Signature: + +```typescript +export interface OnPreResponseExtensions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [headers](./kibana-plugin-server.onpreresponseextensions.headers.md) | ResponseHeaders | additional headers to attach to the response | + diff --git a/docs/development/core/server/kibana-plugin-server.onpreresponsehandler.md b/docs/development/core/server/kibana-plugin-server.onpreresponsehandler.md index 082de0a9b4aebf..9390686280a787 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreresponsehandler.md +++ b/docs/development/core/server/kibana-plugin-server.onpreresponsehandler.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseHandler](./kibana-plugin-server.onpreresponsehandler.md) - -## OnPreResponseHandler type - -See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). - -Signature: - -```typescript -export declare type OnPreResponseHandler = (request: KibanaRequest, preResponse: OnPreResponseInfo, toolkit: OnPreResponseToolkit) => OnPreResponseResult | Promise; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseHandler](./kibana-plugin-server.onpreresponsehandler.md) + +## OnPreResponseHandler type + +See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). + +Signature: + +```typescript +export declare type OnPreResponseHandler = (request: KibanaRequest, preResponse: OnPreResponseInfo, toolkit: OnPreResponseToolkit) => OnPreResponseResult | Promise; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpreresponseinfo.md b/docs/development/core/server/kibana-plugin-server.onpreresponseinfo.md index 736b4298037cf3..934b1d517ac468 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreresponseinfo.md +++ b/docs/development/core/server/kibana-plugin-server.onpreresponseinfo.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseInfo](./kibana-plugin-server.onpreresponseinfo.md) - -## OnPreResponseInfo interface - -Response status code. - -Signature: - -```typescript -export interface OnPreResponseInfo -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [statusCode](./kibana-plugin-server.onpreresponseinfo.statuscode.md) | number | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseInfo](./kibana-plugin-server.onpreresponseinfo.md) + +## OnPreResponseInfo interface + +Response status code. + +Signature: + +```typescript +export interface OnPreResponseInfo +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [statusCode](./kibana-plugin-server.onpreresponseinfo.statuscode.md) | number | | + diff --git a/docs/development/core/server/kibana-plugin-server.onpreresponseinfo.statuscode.md b/docs/development/core/server/kibana-plugin-server.onpreresponseinfo.statuscode.md index 4fd4529dc400fe..ffe04f2583a9b5 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreresponseinfo.statuscode.md +++ b/docs/development/core/server/kibana-plugin-server.onpreresponseinfo.statuscode.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseInfo](./kibana-plugin-server.onpreresponseinfo.md) > [statusCode](./kibana-plugin-server.onpreresponseinfo.statuscode.md) - -## OnPreResponseInfo.statusCode property - -Signature: - -```typescript -statusCode: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseInfo](./kibana-plugin-server.onpreresponseinfo.md) > [statusCode](./kibana-plugin-server.onpreresponseinfo.statuscode.md) + +## OnPreResponseInfo.statusCode property + +Signature: + +```typescript +statusCode: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.onpreresponsetoolkit.md b/docs/development/core/server/kibana-plugin-server.onpreresponsetoolkit.md index 5525f5bf60284c..93557318174092 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreresponsetoolkit.md +++ b/docs/development/core/server/kibana-plugin-server.onpreresponsetoolkit.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseToolkit](./kibana-plugin-server.onpreresponsetoolkit.md) - -## OnPreResponseToolkit interface - -A tool set defining an outcome of OnPreAuth interceptor for incoming request. - -Signature: - -```typescript -export interface OnPreResponseToolkit -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [next](./kibana-plugin-server.onpreresponsetoolkit.next.md) | (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult | To pass request to the next handler | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseToolkit](./kibana-plugin-server.onpreresponsetoolkit.md) + +## OnPreResponseToolkit interface + +A tool set defining an outcome of OnPreAuth interceptor for incoming request. + +Signature: + +```typescript +export interface OnPreResponseToolkit +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [next](./kibana-plugin-server.onpreresponsetoolkit.next.md) | (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult | To pass request to the next handler | + diff --git a/docs/development/core/server/kibana-plugin-server.onpreresponsetoolkit.next.md b/docs/development/core/server/kibana-plugin-server.onpreresponsetoolkit.next.md index bfb5827b16b2fb..cb4d67646a604f 100644 --- a/docs/development/core/server/kibana-plugin-server.onpreresponsetoolkit.next.md +++ b/docs/development/core/server/kibana-plugin-server.onpreresponsetoolkit.next.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseToolkit](./kibana-plugin-server.onpreresponsetoolkit.md) > [next](./kibana-plugin-server.onpreresponsetoolkit.next.md) - -## OnPreResponseToolkit.next property - -To pass request to the next handler - -Signature: - -```typescript -next: (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [OnPreResponseToolkit](./kibana-plugin-server.onpreresponsetoolkit.md) > [next](./kibana-plugin-server.onpreresponsetoolkit.next.md) + +## OnPreResponseToolkit.next property + +To pass request to the next handler + +Signature: + +```typescript +next: (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult; +``` diff --git a/docs/development/core/server/kibana-plugin-server.packageinfo.branch.md b/docs/development/core/server/kibana-plugin-server.packageinfo.branch.md index 36f187180d31b1..b9e086c38a22f7 100644 --- a/docs/development/core/server/kibana-plugin-server.packageinfo.branch.md +++ b/docs/development/core/server/kibana-plugin-server.packageinfo.branch.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [branch](./kibana-plugin-server.packageinfo.branch.md) - -## PackageInfo.branch property - -Signature: - -```typescript -branch: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [branch](./kibana-plugin-server.packageinfo.branch.md) + +## PackageInfo.branch property + +Signature: + +```typescript +branch: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.packageinfo.buildnum.md b/docs/development/core/server/kibana-plugin-server.packageinfo.buildnum.md index c0a231ee27ab00..2575d3d4170fbe 100644 --- a/docs/development/core/server/kibana-plugin-server.packageinfo.buildnum.md +++ b/docs/development/core/server/kibana-plugin-server.packageinfo.buildnum.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [buildNum](./kibana-plugin-server.packageinfo.buildnum.md) - -## PackageInfo.buildNum property - -Signature: - -```typescript -buildNum: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [buildNum](./kibana-plugin-server.packageinfo.buildnum.md) + +## PackageInfo.buildNum property + +Signature: + +```typescript +buildNum: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.packageinfo.buildsha.md b/docs/development/core/server/kibana-plugin-server.packageinfo.buildsha.md index 5e8de48067dd08..ae0cc4c7db0b78 100644 --- a/docs/development/core/server/kibana-plugin-server.packageinfo.buildsha.md +++ b/docs/development/core/server/kibana-plugin-server.packageinfo.buildsha.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [buildSha](./kibana-plugin-server.packageinfo.buildsha.md) - -## PackageInfo.buildSha property - -Signature: - -```typescript -buildSha: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [buildSha](./kibana-plugin-server.packageinfo.buildsha.md) + +## PackageInfo.buildSha property + +Signature: + +```typescript +buildSha: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.packageinfo.dist.md b/docs/development/core/server/kibana-plugin-server.packageinfo.dist.md index e45970780d522d..16d2b68a266231 100644 --- a/docs/development/core/server/kibana-plugin-server.packageinfo.dist.md +++ b/docs/development/core/server/kibana-plugin-server.packageinfo.dist.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [dist](./kibana-plugin-server.packageinfo.dist.md) - -## PackageInfo.dist property - -Signature: - -```typescript -dist: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [dist](./kibana-plugin-server.packageinfo.dist.md) + +## PackageInfo.dist property + +Signature: + +```typescript +dist: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.packageinfo.md b/docs/development/core/server/kibana-plugin-server.packageinfo.md index 3ff02c9cda85d9..c0c7e103a6077b 100644 --- a/docs/development/core/server/kibana-plugin-server.packageinfo.md +++ b/docs/development/core/server/kibana-plugin-server.packageinfo.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) - -## PackageInfo interface - - -Signature: - -```typescript -export interface PackageInfo -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [branch](./kibana-plugin-server.packageinfo.branch.md) | string | | -| [buildNum](./kibana-plugin-server.packageinfo.buildnum.md) | number | | -| [buildSha](./kibana-plugin-server.packageinfo.buildsha.md) | string | | -| [dist](./kibana-plugin-server.packageinfo.dist.md) | boolean | | -| [version](./kibana-plugin-server.packageinfo.version.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) + +## PackageInfo interface + + +Signature: + +```typescript +export interface PackageInfo +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [branch](./kibana-plugin-server.packageinfo.branch.md) | string | | +| [buildNum](./kibana-plugin-server.packageinfo.buildnum.md) | number | | +| [buildSha](./kibana-plugin-server.packageinfo.buildsha.md) | string | | +| [dist](./kibana-plugin-server.packageinfo.dist.md) | boolean | | +| [version](./kibana-plugin-server.packageinfo.version.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.packageinfo.version.md b/docs/development/core/server/kibana-plugin-server.packageinfo.version.md index e99e3c48d70416..f17ee6ee34199d 100644 --- a/docs/development/core/server/kibana-plugin-server.packageinfo.version.md +++ b/docs/development/core/server/kibana-plugin-server.packageinfo.version.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [version](./kibana-plugin-server.packageinfo.version.md) - -## PackageInfo.version property - -Signature: - -```typescript -version: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PackageInfo](./kibana-plugin-server.packageinfo.md) > [version](./kibana-plugin-server.packageinfo.version.md) + +## PackageInfo.version property + +Signature: + +```typescript +version: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.plugin.md b/docs/development/core/server/kibana-plugin-server.plugin.md index 73faf020a4a16c..5b2c206e71e63d 100644 --- a/docs/development/core/server/kibana-plugin-server.plugin.md +++ b/docs/development/core/server/kibana-plugin-server.plugin.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Plugin](./kibana-plugin-server.plugin.md) - -## Plugin interface - -The interface that should be returned by a `PluginInitializer`. - -Signature: - -```typescript -export interface Plugin -``` - -## Methods - -| Method | Description | -| --- | --- | -| [setup(core, plugins)](./kibana-plugin-server.plugin.setup.md) | | -| [start(core, plugins)](./kibana-plugin-server.plugin.start.md) | | -| [stop()](./kibana-plugin-server.plugin.stop.md) | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Plugin](./kibana-plugin-server.plugin.md) + +## Plugin interface + +The interface that should be returned by a `PluginInitializer`. + +Signature: + +```typescript +export interface Plugin +``` + +## Methods + +| Method | Description | +| --- | --- | +| [setup(core, plugins)](./kibana-plugin-server.plugin.setup.md) | | +| [start(core, plugins)](./kibana-plugin-server.plugin.start.md) | | +| [stop()](./kibana-plugin-server.plugin.stop.md) | | + diff --git a/docs/development/core/server/kibana-plugin-server.plugin.setup.md b/docs/development/core/server/kibana-plugin-server.plugin.setup.md index 5ceb504f796f18..66b669b28675df 100644 --- a/docs/development/core/server/kibana-plugin-server.plugin.setup.md +++ b/docs/development/core/server/kibana-plugin-server.plugin.setup.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Plugin](./kibana-plugin-server.plugin.md) > [setup](./kibana-plugin-server.plugin.setup.md) - -## Plugin.setup() method - -Signature: - -```typescript -setup(core: CoreSetup, plugins: TPluginsSetup): TSetup | Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| core | CoreSetup | | -| plugins | TPluginsSetup | | - -Returns: - -`TSetup | Promise` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Plugin](./kibana-plugin-server.plugin.md) > [setup](./kibana-plugin-server.plugin.setup.md) + +## Plugin.setup() method + +Signature: + +```typescript +setup(core: CoreSetup, plugins: TPluginsSetup): TSetup | Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreSetup | | +| plugins | TPluginsSetup | | + +Returns: + +`TSetup | Promise` + diff --git a/docs/development/core/server/kibana-plugin-server.plugin.start.md b/docs/development/core/server/kibana-plugin-server.plugin.start.md index 6ce9f05de77311..cfa692e7041175 100644 --- a/docs/development/core/server/kibana-plugin-server.plugin.start.md +++ b/docs/development/core/server/kibana-plugin-server.plugin.start.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Plugin](./kibana-plugin-server.plugin.md) > [start](./kibana-plugin-server.plugin.start.md) - -## Plugin.start() method - -Signature: - -```typescript -start(core: CoreStart, plugins: TPluginsStart): TStart | Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| core | CoreStart | | -| plugins | TPluginsStart | | - -Returns: - -`TStart | Promise` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Plugin](./kibana-plugin-server.plugin.md) > [start](./kibana-plugin-server.plugin.start.md) + +## Plugin.start() method + +Signature: + +```typescript +start(core: CoreStart, plugins: TPluginsStart): TStart | Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreStart | | +| plugins | TPluginsStart | | + +Returns: + +`TStart | Promise` + diff --git a/docs/development/core/server/kibana-plugin-server.plugin.stop.md b/docs/development/core/server/kibana-plugin-server.plugin.stop.md index 1c51727c1d1660..f46d170e774185 100644 --- a/docs/development/core/server/kibana-plugin-server.plugin.stop.md +++ b/docs/development/core/server/kibana-plugin-server.plugin.stop.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Plugin](./kibana-plugin-server.plugin.md) > [stop](./kibana-plugin-server.plugin.stop.md) - -## Plugin.stop() method - -Signature: - -```typescript -stop?(): void; -``` -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [Plugin](./kibana-plugin-server.plugin.md) > [stop](./kibana-plugin-server.plugin.stop.md) + +## Plugin.stop() method + +Signature: + +```typescript +stop?(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.deprecations.md b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.deprecations.md index 00574101838f29..74cce604023380 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.deprecations.md +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.deprecations.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) > [deprecations](./kibana-plugin-server.pluginconfigdescriptor.deprecations.md) - -## PluginConfigDescriptor.deprecations property - -Provider for the [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) to apply to the plugin configuration. - -Signature: - -```typescript -deprecations?: ConfigDeprecationProvider; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) > [deprecations](./kibana-plugin-server.pluginconfigdescriptor.deprecations.md) + +## PluginConfigDescriptor.deprecations property + +Provider for the [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) to apply to the plugin configuration. + +Signature: + +```typescript +deprecations?: ConfigDeprecationProvider; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md index d62b2457e9d9ac..23e8ca5f9dec3e 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) > [exposeToBrowser](./kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md) - -## PluginConfigDescriptor.exposeToBrowser property - -List of configuration properties that will be available on the client-side plugin. - -Signature: - -```typescript -exposeToBrowser?: { - [P in keyof T]?: boolean; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) > [exposeToBrowser](./kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md) + +## PluginConfigDescriptor.exposeToBrowser property + +List of configuration properties that will be available on the client-side plugin. + +Signature: + +```typescript +exposeToBrowser?: { + [P in keyof T]?: boolean; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md index 3d661ac66d2b70..731572d2167e9d 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md @@ -1,50 +1,50 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) - -## PluginConfigDescriptor interface - -Describes a plugin configuration properties. - -Signature: - -```typescript -export interface PluginConfigDescriptor -``` - -## Example - - -```typescript -// my_plugin/server/index.ts -import { schema, TypeOf } from '@kbn/config-schema'; -import { PluginConfigDescriptor } from 'kibana/server'; - -const configSchema = schema.object({ - secret: schema.string({ defaultValue: 'Only on server' }), - uiProp: schema.string({ defaultValue: 'Accessible from client' }), -}); - -type ConfigType = TypeOf; - -export const config: PluginConfigDescriptor = { - exposeToBrowser: { - uiProp: true, - }, - schema: configSchema, - deprecations: ({ rename, unused }) => [ - rename('securityKey', 'secret'), - unused('deprecatedProperty'), - ], -}; - -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [deprecations](./kibana-plugin-server.pluginconfigdescriptor.deprecations.md) | ConfigDeprecationProvider | Provider for the [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) to apply to the plugin configuration. | -| [exposeToBrowser](./kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md) | {
[P in keyof T]?: boolean;
} | List of configuration properties that will be available on the client-side plugin. | -| [schema](./kibana-plugin-server.pluginconfigdescriptor.schema.md) | PluginConfigSchema<T> | Schema to use to validate the plugin configuration.[PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) + +## PluginConfigDescriptor interface + +Describes a plugin configuration properties. + +Signature: + +```typescript +export interface PluginConfigDescriptor +``` + +## Example + + +```typescript +// my_plugin/server/index.ts +import { schema, TypeOf } from '@kbn/config-schema'; +import { PluginConfigDescriptor } from 'kibana/server'; + +const configSchema = schema.object({ + secret: schema.string({ defaultValue: 'Only on server' }), + uiProp: schema.string({ defaultValue: 'Accessible from client' }), +}); + +type ConfigType = TypeOf; + +export const config: PluginConfigDescriptor = { + exposeToBrowser: { + uiProp: true, + }, + schema: configSchema, + deprecations: ({ rename, unused }) => [ + rename('securityKey', 'secret'), + unused('deprecatedProperty'), + ], +}; + +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [deprecations](./kibana-plugin-server.pluginconfigdescriptor.deprecations.md) | ConfigDeprecationProvider | Provider for the [ConfigDeprecation](./kibana-plugin-server.configdeprecation.md) to apply to the plugin configuration. | +| [exposeToBrowser](./kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md) | {
[P in keyof T]?: boolean;
} | List of configuration properties that will be available on the client-side plugin. | +| [schema](./kibana-plugin-server.pluginconfigdescriptor.schema.md) | PluginConfigSchema<T> | Schema to use to validate the plugin configuration.[PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) | + diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.schema.md b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.schema.md index c4845d52ff2122..eae10cae3cc981 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.schema.md +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.schema.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) > [schema](./kibana-plugin-server.pluginconfigdescriptor.schema.md) - -## PluginConfigDescriptor.schema property - -Schema to use to validate the plugin configuration. - -[PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) - -Signature: - -```typescript -schema: PluginConfigSchema; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) > [schema](./kibana-plugin-server.pluginconfigdescriptor.schema.md) + +## PluginConfigDescriptor.schema property + +Schema to use to validate the plugin configuration. + +[PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) + +Signature: + +```typescript +schema: PluginConfigSchema; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigschema.md b/docs/development/core/server/kibana-plugin-server.pluginconfigschema.md index 6528798ec8e01f..fcc65e431337e9 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginconfigschema.md +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigschema.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) - -## PluginConfigSchema type - -Dedicated type for plugin configuration schema. - -Signature: - -```typescript -export declare type PluginConfigSchema = Type; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) + +## PluginConfigSchema type + +Dedicated type for plugin configuration schema. + +Signature: + +```typescript +export declare type PluginConfigSchema = Type; +``` diff --git a/docs/development/core/server/kibana-plugin-server.plugininitializer.md b/docs/development/core/server/kibana-plugin-server.plugininitializer.md index 1254ed2c88da35..3412f4da7f09db 100644 --- a/docs/development/core/server/kibana-plugin-server.plugininitializer.md +++ b/docs/development/core/server/kibana-plugin-server.plugininitializer.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializer](./kibana-plugin-server.plugininitializer.md) - -## PluginInitializer type - -The `plugin` export at the root of a plugin's `server` directory should conform to this interface. - -Signature: - -```typescript -export declare type PluginInitializer = (core: PluginInitializerContext) => Plugin; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializer](./kibana-plugin-server.plugininitializer.md) + +## PluginInitializer type + +The `plugin` export at the root of a plugin's `server` directory should conform to this interface. + +Signature: + +```typescript +export declare type PluginInitializer = (core: PluginInitializerContext) => Plugin; +``` diff --git a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.config.md b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.config.md index 56d064dcb290e4..b555d5c889cb94 100644 --- a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.config.md +++ b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.config.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) > [config](./kibana-plugin-server.plugininitializercontext.config.md) - -## PluginInitializerContext.config property - -Signature: - -```typescript -config: { - legacy: { - globalConfig$: Observable; - }; - create: () => Observable; - createIfExists: () => Observable; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) > [config](./kibana-plugin-server.plugininitializercontext.config.md) + +## PluginInitializerContext.config property + +Signature: + +```typescript +config: { + legacy: { + globalConfig$: Observable; + }; + create: () => Observable; + createIfExists: () => Observable; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.env.md b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.env.md index fd4caa605c0e59..91bbc7839e495b 100644 --- a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.env.md +++ b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.env.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) > [env](./kibana-plugin-server.plugininitializercontext.env.md) - -## PluginInitializerContext.env property - -Signature: - -```typescript -env: { - mode: EnvironmentMode; - packageInfo: Readonly; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) > [env](./kibana-plugin-server.plugininitializercontext.env.md) + +## PluginInitializerContext.env property + +Signature: + +```typescript +env: { + mode: EnvironmentMode; + packageInfo: Readonly; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.logger.md b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.logger.md index 688560f324d17c..d50e9df486be79 100644 --- a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.logger.md +++ b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.logger.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) > [logger](./kibana-plugin-server.plugininitializercontext.logger.md) - -## PluginInitializerContext.logger property - -Signature: - -```typescript -logger: LoggerFactory; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) > [logger](./kibana-plugin-server.plugininitializercontext.logger.md) + +## PluginInitializerContext.logger property + +Signature: + +```typescript +logger: LoggerFactory; +``` diff --git a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.md b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.md index c2fadfb779fc97..6adf7f277f6322 100644 --- a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.md +++ b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) - -## PluginInitializerContext interface - -Context that's available to plugins during initialization stage. - -Signature: - -```typescript -export interface PluginInitializerContext -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [config](./kibana-plugin-server.plugininitializercontext.config.md) | {
legacy: {
globalConfig$: Observable<SharedGlobalConfig>;
};
create: <T = ConfigSchema>() => Observable<T>;
createIfExists: <T = ConfigSchema>() => Observable<T | undefined>;
} | | -| [env](./kibana-plugin-server.plugininitializercontext.env.md) | {
mode: EnvironmentMode;
packageInfo: Readonly<PackageInfo>;
} | | -| [logger](./kibana-plugin-server.plugininitializercontext.logger.md) | LoggerFactory | | -| [opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) | PluginOpaqueId | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) + +## PluginInitializerContext interface + +Context that's available to plugins during initialization stage. + +Signature: + +```typescript +export interface PluginInitializerContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [config](./kibana-plugin-server.plugininitializercontext.config.md) | {
legacy: {
globalConfig$: Observable<SharedGlobalConfig>;
};
create: <T = ConfigSchema>() => Observable<T>;
createIfExists: <T = ConfigSchema>() => Observable<T | undefined>;
} | | +| [env](./kibana-plugin-server.plugininitializercontext.env.md) | {
mode: EnvironmentMode;
packageInfo: Readonly<PackageInfo>;
} | | +| [logger](./kibana-plugin-server.plugininitializercontext.logger.md) | LoggerFactory | | +| [opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) | PluginOpaqueId | | + diff --git a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.opaqueid.md b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.opaqueid.md index 7ac177f039c91f..e3149f8249892d 100644 --- a/docs/development/core/server/kibana-plugin-server.plugininitializercontext.opaqueid.md +++ b/docs/development/core/server/kibana-plugin-server.plugininitializercontext.opaqueid.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) > [opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) - -## PluginInitializerContext.opaqueId property - -Signature: - -```typescript -opaqueId: PluginOpaqueId; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) > [opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) + +## PluginInitializerContext.opaqueId property + +Signature: + +```typescript +opaqueId: PluginOpaqueId; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.configpath.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.configpath.md index 6ffe396aa2ed1d..24b83cb22b535d 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.configpath.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.configpath.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [configPath](./kibana-plugin-server.pluginmanifest.configpath.md) - -## PluginManifest.configPath property - -Root [configuration path](./kibana-plugin-server.configpath.md) used by the plugin, defaults to "id" in snake\_case format. - -Signature: - -```typescript -readonly configPath: ConfigPath; -``` - -## Example - -id: myPlugin configPath: my\_plugin - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [configPath](./kibana-plugin-server.pluginmanifest.configpath.md) + +## PluginManifest.configPath property + +Root [configuration path](./kibana-plugin-server.configpath.md) used by the plugin, defaults to "id" in snake\_case format. + +Signature: + +```typescript +readonly configPath: ConfigPath; +``` + +## Example + +id: myPlugin configPath: my\_plugin + diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.id.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.id.md index 104046f3ce7d0c..34b0f3afc3f77e 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.id.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [id](./kibana-plugin-server.pluginmanifest.id.md) - -## PluginManifest.id property - -Identifier of the plugin. Must be a string in camelCase. Part of a plugin public contract. Other plugins leverage it to access plugin API, navigate to the plugin, etc. - -Signature: - -```typescript -readonly id: PluginName; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [id](./kibana-plugin-server.pluginmanifest.id.md) + +## PluginManifest.id property + +Identifier of the plugin. Must be a string in camelCase. Part of a plugin public contract. Other plugins leverage it to access plugin API, navigate to the plugin, etc. + +Signature: + +```typescript +readonly id: PluginName; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.kibanaversion.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.kibanaversion.md index f568dce9a8a9e3..4f2e13ad448dc4 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.kibanaversion.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.kibanaversion.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [kibanaVersion](./kibana-plugin-server.pluginmanifest.kibanaversion.md) - -## PluginManifest.kibanaVersion property - -The version of Kibana the plugin is compatible with, defaults to "version". - -Signature: - -```typescript -readonly kibanaVersion: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [kibanaVersion](./kibana-plugin-server.pluginmanifest.kibanaversion.md) + +## PluginManifest.kibanaVersion property + +The version of Kibana the plugin is compatible with, defaults to "version". + +Signature: + +```typescript +readonly kibanaVersion: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.md index c39a702389fb3f..10ce3a921875f3 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.md @@ -1,31 +1,31 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) - -## PluginManifest interface - -Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. - -Signature: - -```typescript -export interface PluginManifest -``` - -## Remarks - -Should never be used in code outside of Core but is exported for documentation purposes. - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [configPath](./kibana-plugin-server.pluginmanifest.configpath.md) | ConfigPath | Root [configuration path](./kibana-plugin-server.configpath.md) used by the plugin, defaults to "id" in snake\_case format. | -| [id](./kibana-plugin-server.pluginmanifest.id.md) | PluginName | Identifier of the plugin. Must be a string in camelCase. Part of a plugin public contract. Other plugins leverage it to access plugin API, navigate to the plugin, etc. | -| [kibanaVersion](./kibana-plugin-server.pluginmanifest.kibanaversion.md) | string | The version of Kibana the plugin is compatible with, defaults to "version". | -| [optionalPlugins](./kibana-plugin-server.pluginmanifest.optionalplugins.md) | readonly PluginName[] | An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. | -| [requiredPlugins](./kibana-plugin-server.pluginmanifest.requiredplugins.md) | readonly PluginName[] | An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. | -| [server](./kibana-plugin-server.pluginmanifest.server.md) | boolean | Specifies whether plugin includes some server-side specific functionality. | -| [ui](./kibana-plugin-server.pluginmanifest.ui.md) | boolean | Specifies whether plugin includes some client/browser specific functionality that should be included into client bundle via public/ui_plugin.js file. | -| [version](./kibana-plugin-server.pluginmanifest.version.md) | string | Version of the plugin. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) + +## PluginManifest interface + +Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. + +Signature: + +```typescript +export interface PluginManifest +``` + +## Remarks + +Should never be used in code outside of Core but is exported for documentation purposes. + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [configPath](./kibana-plugin-server.pluginmanifest.configpath.md) | ConfigPath | Root [configuration path](./kibana-plugin-server.configpath.md) used by the plugin, defaults to "id" in snake\_case format. | +| [id](./kibana-plugin-server.pluginmanifest.id.md) | PluginName | Identifier of the plugin. Must be a string in camelCase. Part of a plugin public contract. Other plugins leverage it to access plugin API, navigate to the plugin, etc. | +| [kibanaVersion](./kibana-plugin-server.pluginmanifest.kibanaversion.md) | string | The version of Kibana the plugin is compatible with, defaults to "version". | +| [optionalPlugins](./kibana-plugin-server.pluginmanifest.optionalplugins.md) | readonly PluginName[] | An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. | +| [requiredPlugins](./kibana-plugin-server.pluginmanifest.requiredplugins.md) | readonly PluginName[] | An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. | +| [server](./kibana-plugin-server.pluginmanifest.server.md) | boolean | Specifies whether plugin includes some server-side specific functionality. | +| [ui](./kibana-plugin-server.pluginmanifest.ui.md) | boolean | Specifies whether plugin includes some client/browser specific functionality that should be included into client bundle via public/ui_plugin.js file. | +| [version](./kibana-plugin-server.pluginmanifest.version.md) | string | Version of the plugin. | + diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.optionalplugins.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.optionalplugins.md index 692785a705d409..c8abb389fc92aa 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.optionalplugins.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.optionalplugins.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [optionalPlugins](./kibana-plugin-server.pluginmanifest.optionalplugins.md) - -## PluginManifest.optionalPlugins property - -An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. - -Signature: - -```typescript -readonly optionalPlugins: readonly PluginName[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [optionalPlugins](./kibana-plugin-server.pluginmanifest.optionalplugins.md) + +## PluginManifest.optionalPlugins property + +An optional list of the other plugins that if installed and enabled \*\*may be\*\* leveraged by this plugin for some additional functionality but otherwise are not required for this plugin to work properly. + +Signature: + +```typescript +readonly optionalPlugins: readonly PluginName[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.requiredplugins.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.requiredplugins.md index 0ea7c872dfa07a..1a9753e889ae97 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.requiredplugins.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.requiredplugins.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [requiredPlugins](./kibana-plugin-server.pluginmanifest.requiredplugins.md) - -## PluginManifest.requiredPlugins property - -An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. - -Signature: - -```typescript -readonly requiredPlugins: readonly PluginName[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [requiredPlugins](./kibana-plugin-server.pluginmanifest.requiredplugins.md) + +## PluginManifest.requiredPlugins property + +An optional list of the other plugins that \*\*must be\*\* installed and enabled for this plugin to function properly. + +Signature: + +```typescript +readonly requiredPlugins: readonly PluginName[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.server.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.server.md index 676ad721edf7c7..06f8a907876d02 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.server.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.server.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [server](./kibana-plugin-server.pluginmanifest.server.md) - -## PluginManifest.server property - -Specifies whether plugin includes some server-side specific functionality. - -Signature: - -```typescript -readonly server: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [server](./kibana-plugin-server.pluginmanifest.server.md) + +## PluginManifest.server property + +Specifies whether plugin includes some server-side specific functionality. + +Signature: + +```typescript +readonly server: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.ui.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.ui.md index ad5ce2237c580f..3526f631662604 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.ui.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.ui.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [ui](./kibana-plugin-server.pluginmanifest.ui.md) - -## PluginManifest.ui property - -Specifies whether plugin includes some client/browser specific functionality that should be included into client bundle via `public/ui_plugin.js` file. - -Signature: - -```typescript -readonly ui: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [ui](./kibana-plugin-server.pluginmanifest.ui.md) + +## PluginManifest.ui property + +Specifies whether plugin includes some client/browser specific functionality that should be included into client bundle via `public/ui_plugin.js` file. + +Signature: + +```typescript +readonly ui: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginmanifest.version.md b/docs/development/core/server/kibana-plugin-server.pluginmanifest.version.md index 75255096408f36..1e58e03a743a57 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginmanifest.version.md +++ b/docs/development/core/server/kibana-plugin-server.pluginmanifest.version.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [version](./kibana-plugin-server.pluginmanifest.version.md) - -## PluginManifest.version property - -Version of the plugin. - -Signature: - -```typescript -readonly version: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginManifest](./kibana-plugin-server.pluginmanifest.md) > [version](./kibana-plugin-server.pluginmanifest.version.md) + +## PluginManifest.version property + +Version of the plugin. + +Signature: + +```typescript +readonly version: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginname.md b/docs/development/core/server/kibana-plugin-server.pluginname.md index 02121c10d6b1d6..365a4720ba5142 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginname.md +++ b/docs/development/core/server/kibana-plugin-server.pluginname.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginName](./kibana-plugin-server.pluginname.md) - -## PluginName type - -Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. - -Signature: - -```typescript -export declare type PluginName = string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginName](./kibana-plugin-server.pluginname.md) + +## PluginName type + +Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. + +Signature: + +```typescript +export declare type PluginName = string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginopaqueid.md b/docs/development/core/server/kibana-plugin-server.pluginopaqueid.md index 3b2399d95137d0..11bec2b2de2096 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginopaqueid.md +++ b/docs/development/core/server/kibana-plugin-server.pluginopaqueid.md @@ -1,12 +1,12 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginOpaqueId](./kibana-plugin-server.pluginopaqueid.md) - -## PluginOpaqueId type - - -Signature: - -```typescript -export declare type PluginOpaqueId = symbol; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginOpaqueId](./kibana-plugin-server.pluginopaqueid.md) + +## PluginOpaqueId type + + +Signature: + +```typescript +export declare type PluginOpaqueId = symbol; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.contracts.md b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.contracts.md index 90eb5daade31f6..174dabe63005e8 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.contracts.md +++ b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.contracts.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) > [contracts](./kibana-plugin-server.pluginsservicesetup.contracts.md) - -## PluginsServiceSetup.contracts property - -Signature: - -```typescript -contracts: Map; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) > [contracts](./kibana-plugin-server.pluginsservicesetup.contracts.md) + +## PluginsServiceSetup.contracts property + +Signature: + +```typescript +contracts: Map; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.md b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.md index 248726e26f3935..e24c428eecec86 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) - -## PluginsServiceSetup interface - - -Signature: - -```typescript -export interface PluginsServiceSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [contracts](./kibana-plugin-server.pluginsservicesetup.contracts.md) | Map<PluginName, unknown> | | -| [uiPlugins](./kibana-plugin-server.pluginsservicesetup.uiplugins.md) | {
internal: Map<PluginName, InternalPluginInfo>;
public: Map<PluginName, DiscoveredPlugin>;
browserConfigs: Map<PluginName, Observable<unknown>>;
} | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) + +## PluginsServiceSetup interface + + +Signature: + +```typescript +export interface PluginsServiceSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [contracts](./kibana-plugin-server.pluginsservicesetup.contracts.md) | Map<PluginName, unknown> | | +| [uiPlugins](./kibana-plugin-server.pluginsservicesetup.uiplugins.md) | {
internal: Map<PluginName, InternalPluginInfo>;
public: Map<PluginName, DiscoveredPlugin>;
browserConfigs: Map<PluginName, Observable<unknown>>;
} | | + diff --git a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.uiplugins.md b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.uiplugins.md index 7c47304cb9bf6f..5f9dcd15a9deec 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.uiplugins.md +++ b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.uiplugins.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) > [uiPlugins](./kibana-plugin-server.pluginsservicesetup.uiplugins.md) - -## PluginsServiceSetup.uiPlugins property - -Signature: - -```typescript -uiPlugins: { - internal: Map; - public: Map; - browserConfigs: Map>; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) > [uiPlugins](./kibana-plugin-server.pluginsservicesetup.uiplugins.md) + +## PluginsServiceSetup.uiPlugins property + +Signature: + +```typescript +uiPlugins: { + internal: Map; + public: Map; + browserConfigs: Map>; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginsservicestart.contracts.md b/docs/development/core/server/kibana-plugin-server.pluginsservicestart.contracts.md index 694ca647883bd3..23e4691ae72666 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginsservicestart.contracts.md +++ b/docs/development/core/server/kibana-plugin-server.pluginsservicestart.contracts.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) > [contracts](./kibana-plugin-server.pluginsservicestart.contracts.md) - -## PluginsServiceStart.contracts property - -Signature: - -```typescript -contracts: Map; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) > [contracts](./kibana-plugin-server.pluginsservicestart.contracts.md) + +## PluginsServiceStart.contracts property + +Signature: + +```typescript +contracts: Map; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginsservicestart.md b/docs/development/core/server/kibana-plugin-server.pluginsservicestart.md index 4ac66afbd7a3e7..9d8e7ee3ef7444 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginsservicestart.md +++ b/docs/development/core/server/kibana-plugin-server.pluginsservicestart.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) - -## PluginsServiceStart interface - - -Signature: - -```typescript -export interface PluginsServiceStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [contracts](./kibana-plugin-server.pluginsservicestart.contracts.md) | Map<PluginName, unknown> | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) + +## PluginsServiceStart interface + + +Signature: + +```typescript +export interface PluginsServiceStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [contracts](./kibana-plugin-server.pluginsservicestart.contracts.md) | Map<PluginName, unknown> | | + diff --git a/docs/development/core/server/kibana-plugin-server.recursivereadonly.md b/docs/development/core/server/kibana-plugin-server.recursivereadonly.md index 562fb9131c7bbf..9a0edaff6bcad9 100644 --- a/docs/development/core/server/kibana-plugin-server.recursivereadonly.md +++ b/docs/development/core/server/kibana-plugin-server.recursivereadonly.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RecursiveReadonly](./kibana-plugin-server.recursivereadonly.md) - -## RecursiveReadonly type - - -Signature: - -```typescript -export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RecursiveReadonly](./kibana-plugin-server.recursivereadonly.md) + +## RecursiveReadonly type + + +Signature: + +```typescript +export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ + [K in keyof T]: RecursiveReadonly; +}> : T; +``` diff --git a/docs/development/core/server/kibana-plugin-server.redirectresponseoptions.md b/docs/development/core/server/kibana-plugin-server.redirectresponseoptions.md index 6fb0a5add2fb65..3d63865ce0f3ee 100644 --- a/docs/development/core/server/kibana-plugin-server.redirectresponseoptions.md +++ b/docs/development/core/server/kibana-plugin-server.redirectresponseoptions.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RedirectResponseOptions](./kibana-plugin-server.redirectresponseoptions.md) - -## RedirectResponseOptions type - -HTTP response parameters for redirection response - -Signature: - -```typescript -export declare type RedirectResponseOptions = HttpResponseOptions & { - headers: { - location: string; - }; -}; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RedirectResponseOptions](./kibana-plugin-server.redirectresponseoptions.md) + +## RedirectResponseOptions type + +HTTP response parameters for redirection response + +Signature: + +```typescript +export declare type RedirectResponseOptions = HttpResponseOptions & { + headers: { + location: string; + }; +}; +``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandler.md b/docs/development/core/server/kibana-plugin-server.requesthandler.md index 9fc183ffc334b1..d9b6fc4a008e50 100644 --- a/docs/development/core/server/kibana-plugin-server.requesthandler.md +++ b/docs/development/core/server/kibana-plugin-server.requesthandler.md @@ -1,42 +1,42 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandler](./kibana-plugin-server.requesthandler.md) - -## RequestHandler type - -A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) functions. - -Signature: - -```typescript -export declare type RequestHandler

= (context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) => IKibanaResponse | Promise>; -``` - -## Example - - -```ts -const router = httpSetup.createRouter(); -// creates a route handler for GET request on 'my-app/path/{id}' path -router.get( - { - path: 'path/{id}', - // defines a validation schema for a named segment of the route path - validate: { - params: schema.object({ - id: schema.string(), - }), - }, - }, - // function to execute to create a responses - async (context, request, response) => { - const data = await context.findObject(request.params.id); - // creates a command to respond with 'not found' error - if (!data) return response.notFound(); - // creates a command to send found data to the client - return response.ok(data); - } -); - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandler](./kibana-plugin-server.requesthandler.md) + +## RequestHandler type + +A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) functions. + +Signature: + +```typescript +export declare type RequestHandler

= (context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) => IKibanaResponse | Promise>; +``` + +## Example + + +```ts +const router = httpSetup.createRouter(); +// creates a route handler for GET request on 'my-app/path/{id}' path +router.get( + { + path: 'path/{id}', + // defines a validation schema for a named segment of the route path + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + // function to execute to create a responses + async (context, request, response) => { + const data = await context.findObject(request.params.id); + // creates a command to respond with 'not found' error + if (!data) return response.notFound(); + // creates a command to send found data to the client + return response.ok(data); + } +); + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md index d1760dafd5bb63..77bfd85e6e54bb 100644 --- a/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) > [core](./kibana-plugin-server.requesthandlercontext.core.md) - -## RequestHandlerContext.core property - -Signature: - -```typescript -core: { - rendering: IScopedRenderingClient; - savedObjects: { - client: SavedObjectsClientContract; - }; - elasticsearch: { - dataClient: IScopedClusterClient; - adminClient: IScopedClusterClient; - }; - uiSettings: { - client: IUiSettingsClient; - }; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) > [core](./kibana-plugin-server.requesthandlercontext.core.md) + +## RequestHandlerContext.core property + +Signature: + +```typescript +core: { + rendering: IScopedRenderingClient; + savedObjects: { + client: SavedObjectsClientContract; + }; + elasticsearch: { + dataClient: IScopedClusterClient; + adminClient: IScopedClusterClient; + }; + uiSettings: { + client: IUiSettingsClient; + }; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md index 7c8625a5824ee8..4d14d890f51a2e 100644 --- a/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) - -## RequestHandlerContext interface - -Plugin specific context passed to a route handler. - -Provides the following clients: - [rendering](./kibana-plugin-server.iscopedrenderingclient.md) - Rendering client which uses the data of the incoming request - [savedObjects.client](./kibana-plugin-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [elasticsearch.dataClient](./kibana-plugin-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [elasticsearch.adminClient](./kibana-plugin-server.scopedclusterclient.md) - Elasticsearch admin client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request - -Signature: - -```typescript -export interface RequestHandlerContext -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [core](./kibana-plugin-server.requesthandlercontext.core.md) | {
rendering: IScopedRenderingClient;
savedObjects: {
client: SavedObjectsClientContract;
};
elasticsearch: {
dataClient: IScopedClusterClient;
adminClient: IScopedClusterClient;
};
uiSettings: {
client: IUiSettingsClient;
};
} | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) + +## RequestHandlerContext interface + +Plugin specific context passed to a route handler. + +Provides the following clients: - [rendering](./kibana-plugin-server.iscopedrenderingclient.md) - Rendering client which uses the data of the incoming request - [savedObjects.client](./kibana-plugin-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [elasticsearch.dataClient](./kibana-plugin-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [elasticsearch.adminClient](./kibana-plugin-server.scopedclusterclient.md) - Elasticsearch admin client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request + +Signature: + +```typescript +export interface RequestHandlerContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [core](./kibana-plugin-server.requesthandlercontext.core.md) | {
rendering: IScopedRenderingClient;
savedObjects: {
client: SavedObjectsClientContract;
};
elasticsearch: {
dataClient: IScopedClusterClient;
adminClient: IScopedClusterClient;
};
uiSettings: {
client: IUiSettingsClient;
};
} | | + diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md index b76a9ce7d235ca..90bb49b292a708 100644 --- a/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContextContainer](./kibana-plugin-server.requesthandlercontextcontainer.md) - -## RequestHandlerContextContainer type - -An object that handles registration of http request context providers. - -Signature: - -```typescript -export declare type RequestHandlerContextContainer = IContextContainer>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContextContainer](./kibana-plugin-server.requesthandlercontextcontainer.md) + +## RequestHandlerContextContainer type + +An object that handles registration of http request context providers. + +Signature: + +```typescript +export declare type RequestHandlerContextContainer = IContextContainer>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md index ea7294b721aabd..f75462f8d1218d 100644 --- a/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContextProvider](./kibana-plugin-server.requesthandlercontextprovider.md) - -## RequestHandlerContextProvider type - -Context provider for request handler. Extends request context object with provided functionality or data. - -Signature: - -```typescript -export declare type RequestHandlerContextProvider = IContextProvider, TContextName>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContextProvider](./kibana-plugin-server.requesthandlercontextprovider.md) + +## RequestHandlerContextProvider type + +Context provider for request handler. Extends request context object with provided functionality or data. + +Signature: + +```typescript +export declare type RequestHandlerContextProvider = IContextProvider, TContextName>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.responseerror.md b/docs/development/core/server/kibana-plugin-server.responseerror.md index 11d5e786d66e84..a623ddf8f33957 100644 --- a/docs/development/core/server/kibana-plugin-server.responseerror.md +++ b/docs/development/core/server/kibana-plugin-server.responseerror.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseError](./kibana-plugin-server.responseerror.md) - -## ResponseError type - -Error message and optional data send to the client in case of error. - -Signature: - -```typescript -export declare type ResponseError = string | Error | { - message: string | Error; - attributes?: ResponseErrorAttributes; -}; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseError](./kibana-plugin-server.responseerror.md) + +## ResponseError type + +Error message and optional data send to the client in case of error. + +Signature: + +```typescript +export declare type ResponseError = string | Error | { + message: string | Error; + attributes?: ResponseErrorAttributes; +}; +``` diff --git a/docs/development/core/server/kibana-plugin-server.responseerrorattributes.md b/docs/development/core/server/kibana-plugin-server.responseerrorattributes.md index 32cc72e9a0d52e..75db8594e636c1 100644 --- a/docs/development/core/server/kibana-plugin-server.responseerrorattributes.md +++ b/docs/development/core/server/kibana-plugin-server.responseerrorattributes.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) - -## ResponseErrorAttributes type - -Additional data to provide error details. - -Signature: - -```typescript -export declare type ResponseErrorAttributes = Record; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) + +## ResponseErrorAttributes type + +Additional data to provide error details. + +Signature: + +```typescript +export declare type ResponseErrorAttributes = Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.responseheaders.md b/docs/development/core/server/kibana-plugin-server.responseheaders.md index c6ba852b9a6244..606c880360edc9 100644 --- a/docs/development/core/server/kibana-plugin-server.responseheaders.md +++ b/docs/development/core/server/kibana-plugin-server.responseheaders.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseHeaders](./kibana-plugin-server.responseheaders.md) - -## ResponseHeaders type - -Http response headers to set. - -Signature: - -```typescript -export declare type ResponseHeaders = { - [header in KnownHeaders]?: string | string[]; -} & { - [header: string]: string | string[]; -}; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseHeaders](./kibana-plugin-server.responseheaders.md) + +## ResponseHeaders type + +Http response headers to set. + +Signature: + +```typescript +export declare type ResponseHeaders = { + [header in KnownHeaders]?: string | string[]; +} & { + [header: string]: string | string[]; +}; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeconfig.md b/docs/development/core/server/kibana-plugin-server.routeconfig.md index 4beb12f0d056e5..78c18afc3ca8c3 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfig.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfig.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfig](./kibana-plugin-server.routeconfig.md) - -## RouteConfig interface - -Route specific configuration. - -Signature: - -```typescript -export interface RouteConfig -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [options](./kibana-plugin-server.routeconfig.options.md) | RouteConfigOptions<Method> | Additional route options [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md). | -| [path](./kibana-plugin-server.routeconfig.path.md) | string | The endpoint \_within\_ the router path to register the route. | -| [validate](./kibana-plugin-server.routeconfig.validate.md) | RouteValidatorFullConfig<P, Q, B> | false | A schema created with @kbn/config-schema that every request will be validated against. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfig](./kibana-plugin-server.routeconfig.md) + +## RouteConfig interface + +Route specific configuration. + +Signature: + +```typescript +export interface RouteConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [options](./kibana-plugin-server.routeconfig.options.md) | RouteConfigOptions<Method> | Additional route options [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md). | +| [path](./kibana-plugin-server.routeconfig.path.md) | string | The endpoint \_within\_ the router path to register the route. | +| [validate](./kibana-plugin-server.routeconfig.validate.md) | RouteValidatorFullConfig<P, Q, B> | false | A schema created with @kbn/config-schema that every request will be validated against. | + diff --git a/docs/development/core/server/kibana-plugin-server.routeconfig.options.md b/docs/development/core/server/kibana-plugin-server.routeconfig.options.md index 90ad294457101f..5423b3c1979733 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfig.options.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfig.options.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfig](./kibana-plugin-server.routeconfig.md) > [options](./kibana-plugin-server.routeconfig.options.md) - -## RouteConfig.options property - -Additional route options [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md). - -Signature: - -```typescript -options?: RouteConfigOptions; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfig](./kibana-plugin-server.routeconfig.md) > [options](./kibana-plugin-server.routeconfig.options.md) + +## RouteConfig.options property + +Additional route options [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md). + +Signature: + +```typescript +options?: RouteConfigOptions; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeconfig.path.md b/docs/development/core/server/kibana-plugin-server.routeconfig.path.md index 0e6fa19f98ace2..1e1e01a74de310 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfig.path.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfig.path.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfig](./kibana-plugin-server.routeconfig.md) > [path](./kibana-plugin-server.routeconfig.path.md) - -## RouteConfig.path property - -The endpoint \_within\_ the router path to register the route. - -Signature: - -```typescript -path: string; -``` - -## Remarks - -E.g. if the router is registered at `/elasticsearch` and the route path is `/search`, the full path for the route is `/elasticsearch/search`. Supports: - named path segments `path/{name}`. - optional path segments `path/{position?}`. - multi-segments `path/{coordinates*2}`. Segments are accessible within a handler function as `params` property of [KibanaRequest](./kibana-plugin-server.kibanarequest.md) object. To have read access to `params` you \*must\* specify validation schema with [RouteConfig.validate](./kibana-plugin-server.routeconfig.validate.md). - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfig](./kibana-plugin-server.routeconfig.md) > [path](./kibana-plugin-server.routeconfig.path.md) + +## RouteConfig.path property + +The endpoint \_within\_ the router path to register the route. + +Signature: + +```typescript +path: string; +``` + +## Remarks + +E.g. if the router is registered at `/elasticsearch` and the route path is `/search`, the full path for the route is `/elasticsearch/search`. Supports: - named path segments `path/{name}`. - optional path segments `path/{position?}`. - multi-segments `path/{coordinates*2}`. Segments are accessible within a handler function as `params` property of [KibanaRequest](./kibana-plugin-server.kibanarequest.md) object. To have read access to `params` you \*must\* specify validation schema with [RouteConfig.validate](./kibana-plugin-server.routeconfig.validate.md). + diff --git a/docs/development/core/server/kibana-plugin-server.routeconfig.validate.md b/docs/development/core/server/kibana-plugin-server.routeconfig.validate.md index 23a72fc3c68b3a..c69ff4cbb5af2a 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfig.validate.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfig.validate.md @@ -1,62 +1,62 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfig](./kibana-plugin-server.routeconfig.md) > [validate](./kibana-plugin-server.routeconfig.validate.md) - -## RouteConfig.validate property - -A schema created with `@kbn/config-schema` that every request will be validated against. - -Signature: - -```typescript -validate: RouteValidatorFullConfig | false; -``` - -## Remarks - -You \*must\* specify a validation schema to be able to read: - url path segments - request query - request body To opt out of validating the request, specify `validate: false`. In this case request params, query, and body will be \*\*empty\*\* objects and have no access to raw values. In some cases you may want to use another validation library. To do this, you need to instruct the `@kbn/config-schema` library to output \*\*non-validated values\*\* with setting schema as `schema.object({}, { allowUnknowns: true })`; - -## Example - - -```ts - import { schema } from '@kbn/config-schema'; - router.get({ - path: 'path/{id}', - validate: { - params: schema.object({ - id: schema.string(), - }), - query: schema.object({...}), - body: schema.object({...}), - }, -}, -(context, req, res,) { - req.params; // type Readonly<{id: string}> - console.log(req.params.id); // value -}); - -router.get({ - path: 'path/{id}', - validate: false, // handler has no access to params, query, body values. -}, -(context, req, res,) { - req.params; // type Readonly<{}>; - console.log(req.params.id); // undefined -}); - -router.get({ - path: 'path/{id}', - validate: { - // handler has access to raw non-validated params in runtime - params: schema.object({}, { allowUnknowns: true }) - }, -}, -(context, req, res,) { - req.params; // type Readonly<{}>; - console.log(req.params.id); // value - myValidationLibrary.validate({ params: req.params }); -}); - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfig](./kibana-plugin-server.routeconfig.md) > [validate](./kibana-plugin-server.routeconfig.validate.md) + +## RouteConfig.validate property + +A schema created with `@kbn/config-schema` that every request will be validated against. + +Signature: + +```typescript +validate: RouteValidatorFullConfig | false; +``` + +## Remarks + +You \*must\* specify a validation schema to be able to read: - url path segments - request query - request body To opt out of validating the request, specify `validate: false`. In this case request params, query, and body will be \*\*empty\*\* objects and have no access to raw values. In some cases you may want to use another validation library. To do this, you need to instruct the `@kbn/config-schema` library to output \*\*non-validated values\*\* with setting schema as `schema.object({}, { allowUnknowns: true })`; + +## Example + + +```ts + import { schema } from '@kbn/config-schema'; + router.get({ + path: 'path/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + query: schema.object({...}), + body: schema.object({...}), + }, +}, +(context, req, res,) { + req.params; // type Readonly<{id: string}> + console.log(req.params.id); // value +}); + +router.get({ + path: 'path/{id}', + validate: false, // handler has no access to params, query, body values. +}, +(context, req, res,) { + req.params; // type Readonly<{}>; + console.log(req.params.id); // undefined +}); + +router.get({ + path: 'path/{id}', + validate: { + // handler has access to raw non-validated params in runtime + params: schema.object({}, { allowUnknowns: true }) + }, +}, +(context, req, res,) { + req.params; // type Readonly<{}>; + console.log(req.params.id); // value + myValidationLibrary.validate({ params: req.params }); +}); + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptions.authrequired.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptions.authrequired.md index 2bb2491cae5dfc..e4cbca9c978108 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptions.authrequired.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptions.authrequired.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) > [authRequired](./kibana-plugin-server.routeconfigoptions.authrequired.md) - -## RouteConfigOptions.authRequired property - -A flag shows that authentication for a route: `enabled` when true `disabled` when false - -Enabled by default. - -Signature: - -```typescript -authRequired?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) > [authRequired](./kibana-plugin-server.routeconfigoptions.authrequired.md) + +## RouteConfigOptions.authRequired property + +A flag shows that authentication for a route: `enabled` when true `disabled` when false + +Enabled by default. + +Signature: + +```typescript +authRequired?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptions.body.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptions.body.md index fee5528ce3378e..8b7cc6ab06f7fb 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptions.body.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptions.body.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) > [body](./kibana-plugin-server.routeconfigoptions.body.md) - -## RouteConfigOptions.body property - -Additional body options [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md). - -Signature: - -```typescript -body?: Method extends 'get' | 'options' ? undefined : RouteConfigOptionsBody; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) > [body](./kibana-plugin-server.routeconfigoptions.body.md) + +## RouteConfigOptions.body property + +Additional body options [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md). + +Signature: + +```typescript +body?: Method extends 'get' | 'options' ? undefined : RouteConfigOptionsBody; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptions.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptions.md index 99339db81065c1..0929e15b6228b7 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptions.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptions.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) - -## RouteConfigOptions interface - -Additional route options. - -Signature: - -```typescript -export interface RouteConfigOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [authRequired](./kibana-plugin-server.routeconfigoptions.authrequired.md) | boolean | A flag shows that authentication for a route: enabled when true disabled when falseEnabled by default. | -| [body](./kibana-plugin-server.routeconfigoptions.body.md) | Method extends 'get' | 'options' ? undefined : RouteConfigOptionsBody | Additional body options [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md). | -| [tags](./kibana-plugin-server.routeconfigoptions.tags.md) | readonly string[] | Additional metadata tag strings to attach to the route. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) + +## RouteConfigOptions interface + +Additional route options. + +Signature: + +```typescript +export interface RouteConfigOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [authRequired](./kibana-plugin-server.routeconfigoptions.authrequired.md) | boolean | A flag shows that authentication for a route: enabled when true disabled when falseEnabled by default. | +| [body](./kibana-plugin-server.routeconfigoptions.body.md) | Method extends 'get' | 'options' ? undefined : RouteConfigOptionsBody | Additional body options [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md). | +| [tags](./kibana-plugin-server.routeconfigoptions.tags.md) | readonly string[] | Additional metadata tag strings to attach to the route. | + diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptions.tags.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptions.tags.md index e13ef883cc0537..adcce0caa750f1 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptions.tags.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptions.tags.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) > [tags](./kibana-plugin-server.routeconfigoptions.tags.md) - -## RouteConfigOptions.tags property - -Additional metadata tag strings to attach to the route. - -Signature: - -```typescript -tags?: readonly string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) > [tags](./kibana-plugin-server.routeconfigoptions.tags.md) + +## RouteConfigOptions.tags property + +Additional metadata tag strings to attach to the route. + +Signature: + +```typescript +tags?: readonly string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.accepts.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.accepts.md index f48c9a1d73b11e..f71388c2bbf4b9 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.accepts.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.accepts.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) > [accepts](./kibana-plugin-server.routeconfigoptionsbody.accepts.md) - -## RouteConfigOptionsBody.accepts property - -A string or an array of strings with the allowed mime types for the endpoint. Use this settings to limit the set of allowed mime types. Note that allowing additional mime types not listed above will not enable them to be parsed, and if parse is true, the request will result in an error response. - -Default value: allows parsing of the following mime types: \* application/json \* application/\*+json \* application/octet-stream \* application/x-www-form-urlencoded \* multipart/form-data \* text/\* - -Signature: - -```typescript -accepts?: RouteContentType | RouteContentType[] | string | string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) > [accepts](./kibana-plugin-server.routeconfigoptionsbody.accepts.md) + +## RouteConfigOptionsBody.accepts property + +A string or an array of strings with the allowed mime types for the endpoint. Use this settings to limit the set of allowed mime types. Note that allowing additional mime types not listed above will not enable them to be parsed, and if parse is true, the request will result in an error response. + +Default value: allows parsing of the following mime types: \* application/json \* application/\*+json \* application/octet-stream \* application/x-www-form-urlencoded \* multipart/form-data \* text/\* + +Signature: + +```typescript +accepts?: RouteContentType | RouteContentType[] | string | string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.maxbytes.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.maxbytes.md index 3d22dc07d5bae0..1bf02285b4304e 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.maxbytes.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.maxbytes.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) > [maxBytes](./kibana-plugin-server.routeconfigoptionsbody.maxbytes.md) - -## RouteConfigOptionsBody.maxBytes property - -Limits the size of incoming payloads to the specified byte count. Allowing very large payloads may cause the server to run out of memory. - -Default value: The one set in the kibana.yml config file under the parameter `server.maxPayloadBytes`. - -Signature: - -```typescript -maxBytes?: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) > [maxBytes](./kibana-plugin-server.routeconfigoptionsbody.maxbytes.md) + +## RouteConfigOptionsBody.maxBytes property + +Limits the size of incoming payloads to the specified byte count. Allowing very large payloads may cause the server to run out of memory. + +Default value: The one set in the kibana.yml config file under the parameter `server.maxPayloadBytes`. + +Signature: + +```typescript +maxBytes?: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.md index 6ef04de459fcf2..77bccd33cb52e7 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) - -## RouteConfigOptionsBody interface - -Additional body options for a route - -Signature: - -```typescript -export interface RouteConfigOptionsBody -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [accepts](./kibana-plugin-server.routeconfigoptionsbody.accepts.md) | RouteContentType | RouteContentType[] | string | string[] | A string or an array of strings with the allowed mime types for the endpoint. Use this settings to limit the set of allowed mime types. Note that allowing additional mime types not listed above will not enable them to be parsed, and if parse is true, the request will result in an error response.Default value: allows parsing of the following mime types: \* application/json \* application/\*+json \* application/octet-stream \* application/x-www-form-urlencoded \* multipart/form-data \* text/\* | -| [maxBytes](./kibana-plugin-server.routeconfigoptionsbody.maxbytes.md) | number | Limits the size of incoming payloads to the specified byte count. Allowing very large payloads may cause the server to run out of memory.Default value: The one set in the kibana.yml config file under the parameter server.maxPayloadBytes. | -| [output](./kibana-plugin-server.routeconfigoptionsbody.output.md) | typeof validBodyOutput[number] | The processed payload format. The value must be one of: \* 'data' - the incoming payload is read fully into memory. If parse is true, the payload is parsed (JSON, form-decoded, multipart) based on the 'Content-Type' header. If parse is false, a raw Buffer is returned. \* 'stream' - the incoming payload is made available via a Stream.Readable interface. If the payload is 'multipart/form-data' and parse is true, field values are presented as text while files are provided as streams. File streams from a 'multipart/form-data' upload will also have a hapi property containing the filename and headers properties. Note that payload streams for multipart payloads are a synthetic interface created on top of the entire multipart content loaded into memory. To avoid loading large multipart payloads into memory, set parse to false and handle the multipart payload in the handler using a streaming parser (e.g. pez).Default value: 'data', unless no validation.body is provided in the route definition. In that case the default is 'stream' to alleviate memory pressure. | -| [parse](./kibana-plugin-server.routeconfigoptionsbody.parse.md) | boolean | 'gunzip' | Determines if the incoming payload is processed or presented raw. Available values: \* true - if the request 'Content-Type' matches the allowed mime types set by allow (for the whole payload as well as parts), the payload is converted into an object when possible. If the format is unknown, a Bad Request (400) error response is sent. Any known content encoding is decoded. \* false - the raw payload is returned unmodified. \* 'gunzip' - the raw payload is returned unmodified after any known content encoding is decoded.Default value: true, unless no validation.body is provided in the route definition. In that case the default is false to alleviate memory pressure. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) + +## RouteConfigOptionsBody interface + +Additional body options for a route + +Signature: + +```typescript +export interface RouteConfigOptionsBody +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [accepts](./kibana-plugin-server.routeconfigoptionsbody.accepts.md) | RouteContentType | RouteContentType[] | string | string[] | A string or an array of strings with the allowed mime types for the endpoint. Use this settings to limit the set of allowed mime types. Note that allowing additional mime types not listed above will not enable them to be parsed, and if parse is true, the request will result in an error response.Default value: allows parsing of the following mime types: \* application/json \* application/\*+json \* application/octet-stream \* application/x-www-form-urlencoded \* multipart/form-data \* text/\* | +| [maxBytes](./kibana-plugin-server.routeconfigoptionsbody.maxbytes.md) | number | Limits the size of incoming payloads to the specified byte count. Allowing very large payloads may cause the server to run out of memory.Default value: The one set in the kibana.yml config file under the parameter server.maxPayloadBytes. | +| [output](./kibana-plugin-server.routeconfigoptionsbody.output.md) | typeof validBodyOutput[number] | The processed payload format. The value must be one of: \* 'data' - the incoming payload is read fully into memory. If parse is true, the payload is parsed (JSON, form-decoded, multipart) based on the 'Content-Type' header. If parse is false, a raw Buffer is returned. \* 'stream' - the incoming payload is made available via a Stream.Readable interface. If the payload is 'multipart/form-data' and parse is true, field values are presented as text while files are provided as streams. File streams from a 'multipart/form-data' upload will also have a hapi property containing the filename and headers properties. Note that payload streams for multipart payloads are a synthetic interface created on top of the entire multipart content loaded into memory. To avoid loading large multipart payloads into memory, set parse to false and handle the multipart payload in the handler using a streaming parser (e.g. pez).Default value: 'data', unless no validation.body is provided in the route definition. In that case the default is 'stream' to alleviate memory pressure. | +| [parse](./kibana-plugin-server.routeconfigoptionsbody.parse.md) | boolean | 'gunzip' | Determines if the incoming payload is processed or presented raw. Available values: \* true - if the request 'Content-Type' matches the allowed mime types set by allow (for the whole payload as well as parts), the payload is converted into an object when possible. If the format is unknown, a Bad Request (400) error response is sent. Any known content encoding is decoded. \* false - the raw payload is returned unmodified. \* 'gunzip' - the raw payload is returned unmodified after any known content encoding is decoded.Default value: true, unless no validation.body is provided in the route definition. In that case the default is false to alleviate memory pressure. | + diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.output.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.output.md index b84bc709df3eca..1c66589df9e803 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.output.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.output.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) > [output](./kibana-plugin-server.routeconfigoptionsbody.output.md) - -## RouteConfigOptionsBody.output property - -The processed payload format. The value must be one of: \* 'data' - the incoming payload is read fully into memory. If parse is true, the payload is parsed (JSON, form-decoded, multipart) based on the 'Content-Type' header. If parse is false, a raw Buffer is returned. \* 'stream' - the incoming payload is made available via a Stream.Readable interface. If the payload is 'multipart/form-data' and parse is true, field values are presented as text while files are provided as streams. File streams from a 'multipart/form-data' upload will also have a hapi property containing the filename and headers properties. Note that payload streams for multipart payloads are a synthetic interface created on top of the entire multipart content loaded into memory. To avoid loading large multipart payloads into memory, set parse to false and handle the multipart payload in the handler using a streaming parser (e.g. pez). - -Default value: 'data', unless no validation.body is provided in the route definition. In that case the default is 'stream' to alleviate memory pressure. - -Signature: - -```typescript -output?: typeof validBodyOutput[number]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) > [output](./kibana-plugin-server.routeconfigoptionsbody.output.md) + +## RouteConfigOptionsBody.output property + +The processed payload format. The value must be one of: \* 'data' - the incoming payload is read fully into memory. If parse is true, the payload is parsed (JSON, form-decoded, multipart) based on the 'Content-Type' header. If parse is false, a raw Buffer is returned. \* 'stream' - the incoming payload is made available via a Stream.Readable interface. If the payload is 'multipart/form-data' and parse is true, field values are presented as text while files are provided as streams. File streams from a 'multipart/form-data' upload will also have a hapi property containing the filename and headers properties. Note that payload streams for multipart payloads are a synthetic interface created on top of the entire multipart content loaded into memory. To avoid loading large multipart payloads into memory, set parse to false and handle the multipart payload in the handler using a streaming parser (e.g. pez). + +Default value: 'data', unless no validation.body is provided in the route definition. In that case the default is 'stream' to alleviate memory pressure. + +Signature: + +```typescript +output?: typeof validBodyOutput[number]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.parse.md b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.parse.md index d395f67c696690..b030c9de302afb 100644 --- a/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.parse.md +++ b/docs/development/core/server/kibana-plugin-server.routeconfigoptionsbody.parse.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) > [parse](./kibana-plugin-server.routeconfigoptionsbody.parse.md) - -## RouteConfigOptionsBody.parse property - -Determines if the incoming payload is processed or presented raw. Available values: \* true - if the request 'Content-Type' matches the allowed mime types set by allow (for the whole payload as well as parts), the payload is converted into an object when possible. If the format is unknown, a Bad Request (400) error response is sent. Any known content encoding is decoded. \* false - the raw payload is returned unmodified. \* 'gunzip' - the raw payload is returned unmodified after any known content encoding is decoded. - -Default value: true, unless no validation.body is provided in the route definition. In that case the default is false to alleviate memory pressure. - -Signature: - -```typescript -parse?: boolean | 'gunzip'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteConfigOptionsBody](./kibana-plugin-server.routeconfigoptionsbody.md) > [parse](./kibana-plugin-server.routeconfigoptionsbody.parse.md) + +## RouteConfigOptionsBody.parse property + +Determines if the incoming payload is processed or presented raw. Available values: \* true - if the request 'Content-Type' matches the allowed mime types set by allow (for the whole payload as well as parts), the payload is converted into an object when possible. If the format is unknown, a Bad Request (400) error response is sent. Any known content encoding is decoded. \* false - the raw payload is returned unmodified. \* 'gunzip' - the raw payload is returned unmodified after any known content encoding is decoded. + +Default value: true, unless no validation.body is provided in the route definition. In that case the default is false to alleviate memory pressure. + +Signature: + +```typescript +parse?: boolean | 'gunzip'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routecontenttype.md b/docs/development/core/server/kibana-plugin-server.routecontenttype.md index 010388c7b8f177..3c9b88938d1311 100644 --- a/docs/development/core/server/kibana-plugin-server.routecontenttype.md +++ b/docs/development/core/server/kibana-plugin-server.routecontenttype.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteContentType](./kibana-plugin-server.routecontenttype.md) - -## RouteContentType type - -The set of supported parseable Content-Types - -Signature: - -```typescript -export declare type RouteContentType = 'application/json' | 'application/*+json' | 'application/octet-stream' | 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'text/*'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteContentType](./kibana-plugin-server.routecontenttype.md) + +## RouteContentType type + +The set of supported parseable Content-Types + +Signature: + +```typescript +export declare type RouteContentType = 'application/json' | 'application/*+json' | 'application/octet-stream' | 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'text/*'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routemethod.md b/docs/development/core/server/kibana-plugin-server.routemethod.md index 4f83344f842b3c..939ae94b85691b 100644 --- a/docs/development/core/server/kibana-plugin-server.routemethod.md +++ b/docs/development/core/server/kibana-plugin-server.routemethod.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteMethod](./kibana-plugin-server.routemethod.md) - -## RouteMethod type - -The set of common HTTP methods supported by Kibana routing. - -Signature: - -```typescript -export declare type RouteMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteMethod](./kibana-plugin-server.routemethod.md) + +## RouteMethod type + +The set of common HTTP methods supported by Kibana routing. + +Signature: + +```typescript +export declare type RouteMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routeregistrar.md b/docs/development/core/server/kibana-plugin-server.routeregistrar.md index 901d260fee21da..b886305731c3c3 100644 --- a/docs/development/core/server/kibana-plugin-server.routeregistrar.md +++ b/docs/development/core/server/kibana-plugin-server.routeregistrar.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteRegistrar](./kibana-plugin-server.routeregistrar.md) - -## RouteRegistrar type - -Route handler common definition - -Signature: - -```typescript -export declare type RouteRegistrar = (route: RouteConfig, handler: RequestHandler) => void; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteRegistrar](./kibana-plugin-server.routeregistrar.md) + +## RouteRegistrar type + +Route handler common definition + +Signature: + +```typescript +export declare type RouteRegistrar = (route: RouteConfig, handler: RequestHandler) => void; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routevalidationerror._constructor_.md b/docs/development/core/server/kibana-plugin-server.routevalidationerror._constructor_.md index 551e13faaf1542..d643cc31f50cfd 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidationerror._constructor_.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidationerror._constructor_.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationError](./kibana-plugin-server.routevalidationerror.md) > [(constructor)](./kibana-plugin-server.routevalidationerror._constructor_.md) - -## RouteValidationError.(constructor) - -Constructs a new instance of the `RouteValidationError` class - -Signature: - -```typescript -constructor(error: Error | string, path?: string[]); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | string | | -| path | string[] | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationError](./kibana-plugin-server.routevalidationerror.md) > [(constructor)](./kibana-plugin-server.routevalidationerror._constructor_.md) + +## RouteValidationError.(constructor) + +Constructs a new instance of the `RouteValidationError` class + +Signature: + +```typescript +constructor(error: Error | string, path?: string[]); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | string | | +| path | string[] | | + diff --git a/docs/development/core/server/kibana-plugin-server.routevalidationerror.md b/docs/development/core/server/kibana-plugin-server.routevalidationerror.md index 71bd72dca2eaba..7c84b26e9291e0 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidationerror.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidationerror.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationError](./kibana-plugin-server.routevalidationerror.md) - -## RouteValidationError class - -Error to return when the validation is not successful. - -Signature: - -```typescript -export declare class RouteValidationError extends SchemaTypeError -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(error, path)](./kibana-plugin-server.routevalidationerror._constructor_.md) | | Constructs a new instance of the RouteValidationError class | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationError](./kibana-plugin-server.routevalidationerror.md) + +## RouteValidationError class + +Error to return when the validation is not successful. + +Signature: + +```typescript +export declare class RouteValidationError extends SchemaTypeError +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(error, path)](./kibana-plugin-server.routevalidationerror._constructor_.md) | | Constructs a new instance of the RouteValidationError class | + diff --git a/docs/development/core/server/kibana-plugin-server.routevalidationfunction.md b/docs/development/core/server/kibana-plugin-server.routevalidationfunction.md index 34fa096aaae785..e64f6ae0178bcd 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidationfunction.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidationfunction.md @@ -1,42 +1,42 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md) - -## RouteValidationFunction type - -The custom validation function if @kbn/config-schema is not a valid solution for your specific plugin requirements. - -Signature: - -```typescript -export declare type RouteValidationFunction = (data: any, validationResult: RouteValidationResultFactory) => { - value: T; - error?: never; -} | { - value?: never; - error: RouteValidationError; -}; -``` - -## Example - -The validation should look something like: - -```typescript -interface MyExpectedBody { - bar: string; - baz: number; -} - -const myBodyValidation: RouteValidationFunction = (data, validationResult) => { - const { ok, badRequest } = validationResult; - const { bar, baz } = data || {}; - if (typeof bar === 'string' && typeof baz === 'number') { - return ok({ bar, baz }); - } else { - return badRequest('Wrong payload', ['body']); - } -} - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md) + +## RouteValidationFunction type + +The custom validation function if @kbn/config-schema is not a valid solution for your specific plugin requirements. + +Signature: + +```typescript +export declare type RouteValidationFunction = (data: any, validationResult: RouteValidationResultFactory) => { + value: T; + error?: never; +} | { + value?: never; + error: RouteValidationError; +}; +``` + +## Example + +The validation should look something like: + +```typescript +interface MyExpectedBody { + bar: string; + baz: number; +} + +const myBodyValidation: RouteValidationFunction = (data, validationResult) => { + const { ok, badRequest } = validationResult; + const { bar, baz } = data || {}; + if (typeof bar === 'string' && typeof baz === 'number') { + return ok({ bar, baz }); + } else { + return badRequest('Wrong payload', ['body']); + } +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.badrequest.md b/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.badrequest.md index 36ea6103fb352d..29406a2d9866a6 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.badrequest.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.badrequest.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationResultFactory](./kibana-plugin-server.routevalidationresultfactory.md) > [badRequest](./kibana-plugin-server.routevalidationresultfactory.badrequest.md) - -## RouteValidationResultFactory.badRequest property - -Signature: - -```typescript -badRequest: (error: Error | string, path?: string[]) => { - error: RouteValidationError; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationResultFactory](./kibana-plugin-server.routevalidationresultfactory.md) > [badRequest](./kibana-plugin-server.routevalidationresultfactory.badrequest.md) + +## RouteValidationResultFactory.badRequest property + +Signature: + +```typescript +badRequest: (error: Error | string, path?: string[]) => { + error: RouteValidationError; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.md b/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.md index 5f44b490e9a17a..eac2e0e6c4c1a8 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationResultFactory](./kibana-plugin-server.routevalidationresultfactory.md) - -## RouteValidationResultFactory interface - -Validation result factory to be used in the custom validation function to return the valid data or validation errors - -See [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md). - -Signature: - -```typescript -export interface RouteValidationResultFactory -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [badRequest](./kibana-plugin-server.routevalidationresultfactory.badrequest.md) | (error: Error | string, path?: string[]) => {
error: RouteValidationError;
} | | -| [ok](./kibana-plugin-server.routevalidationresultfactory.ok.md) | <T>(value: T) => {
value: T;
} | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationResultFactory](./kibana-plugin-server.routevalidationresultfactory.md) + +## RouteValidationResultFactory interface + +Validation result factory to be used in the custom validation function to return the valid data or validation errors + +See [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md). + +Signature: + +```typescript +export interface RouteValidationResultFactory +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [badRequest](./kibana-plugin-server.routevalidationresultfactory.badrequest.md) | (error: Error | string, path?: string[]) => {
error: RouteValidationError;
} | | +| [ok](./kibana-plugin-server.routevalidationresultfactory.ok.md) | <T>(value: T) => {
value: T;
} | | + diff --git a/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.ok.md b/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.ok.md index eca6a31bd547f5..5ba36a4b5bc3bf 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.ok.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidationresultfactory.ok.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationResultFactory](./kibana-plugin-server.routevalidationresultfactory.md) > [ok](./kibana-plugin-server.routevalidationresultfactory.ok.md) - -## RouteValidationResultFactory.ok property - -Signature: - -```typescript -ok: (value: T) => { - value: T; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationResultFactory](./kibana-plugin-server.routevalidationresultfactory.md) > [ok](./kibana-plugin-server.routevalidationresultfactory.ok.md) + +## RouteValidationResultFactory.ok property + +Signature: + +```typescript +ok: (value: T) => { + value: T; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routevalidationspec.md b/docs/development/core/server/kibana-plugin-server.routevalidationspec.md index f5fc06544043f2..67b9bd9b8daa87 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidationspec.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidationspec.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationSpec](./kibana-plugin-server.routevalidationspec.md) - -## RouteValidationSpec type - -Allowed property validation options: either @kbn/config-schema validations or custom validation functions - -See [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md) for custom validation. - -Signature: - -```typescript -export declare type RouteValidationSpec = ObjectType | Type | RouteValidationFunction; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidationSpec](./kibana-plugin-server.routevalidationspec.md) + +## RouteValidationSpec type + +Allowed property validation options: either @kbn/config-schema validations or custom validation functions + +See [RouteValidationFunction](./kibana-plugin-server.routevalidationfunction.md) for custom validation. + +Signature: + +```typescript +export declare type RouteValidationSpec = ObjectType | Type | RouteValidationFunction; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.body.md b/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.body.md index 8b5d2c04130871..56b7552f615f03 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.body.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.body.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) > [body](./kibana-plugin-server.routevalidatorconfig.body.md) - -## RouteValidatorConfig.body property - -Validation logic for the body payload - -Signature: - -```typescript -body?: RouteValidationSpec; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) > [body](./kibana-plugin-server.routevalidatorconfig.body.md) + +## RouteValidatorConfig.body property + +Validation logic for the body payload + +Signature: + +```typescript +body?: RouteValidationSpec; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.md b/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.md index 4637da7741d806..6bdba920702d72 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) - -## RouteValidatorConfig interface - -The configuration object to the RouteValidator class. Set `params`, `query` and/or `body` to specify the validation logic to follow for that property. - -Signature: - -```typescript -export interface RouteValidatorConfig -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [body](./kibana-plugin-server.routevalidatorconfig.body.md) | RouteValidationSpec<B> | Validation logic for the body payload | -| [params](./kibana-plugin-server.routevalidatorconfig.params.md) | RouteValidationSpec<P> | Validation logic for the URL params | -| [query](./kibana-plugin-server.routevalidatorconfig.query.md) | RouteValidationSpec<Q> | Validation logic for the Query params | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) + +## RouteValidatorConfig interface + +The configuration object to the RouteValidator class. Set `params`, `query` and/or `body` to specify the validation logic to follow for that property. + +Signature: + +```typescript +export interface RouteValidatorConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-server.routevalidatorconfig.body.md) | RouteValidationSpec<B> | Validation logic for the body payload | +| [params](./kibana-plugin-server.routevalidatorconfig.params.md) | RouteValidationSpec<P> | Validation logic for the URL params | +| [query](./kibana-plugin-server.routevalidatorconfig.query.md) | RouteValidationSpec<Q> | Validation logic for the Query params | + diff --git a/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.params.md b/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.params.md index 11de25ff3b19f6..33ad91bf6badfc 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.params.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.params.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) > [params](./kibana-plugin-server.routevalidatorconfig.params.md) - -## RouteValidatorConfig.params property - -Validation logic for the URL params - -Signature: - -```typescript -params?: RouteValidationSpec

; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) > [params](./kibana-plugin-server.routevalidatorconfig.params.md) + +## RouteValidatorConfig.params property + +Validation logic for the URL params + +Signature: + +```typescript +params?: RouteValidationSpec

; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.query.md b/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.query.md index 510325c2dfff76..272c696c595935 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.query.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidatorconfig.query.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) > [query](./kibana-plugin-server.routevalidatorconfig.query.md) - -## RouteValidatorConfig.query property - -Validation logic for the Query params - -Signature: - -```typescript -query?: RouteValidationSpec; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorConfig](./kibana-plugin-server.routevalidatorconfig.md) > [query](./kibana-plugin-server.routevalidatorconfig.query.md) + +## RouteValidatorConfig.query property + +Validation logic for the Query params + +Signature: + +```typescript +query?: RouteValidationSpec; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routevalidatorfullconfig.md b/docs/development/core/server/kibana-plugin-server.routevalidatorfullconfig.md index 0f3785b954a3a9..90d7501c4af175 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidatorfullconfig.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidatorfullconfig.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorFullConfig](./kibana-plugin-server.routevalidatorfullconfig.md) - -## RouteValidatorFullConfig type - -Route validations config and options merged into one object - -Signature: - -```typescript -export declare type RouteValidatorFullConfig = RouteValidatorConfig & RouteValidatorOptions; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorFullConfig](./kibana-plugin-server.routevalidatorfullconfig.md) + +## RouteValidatorFullConfig type + +Route validations config and options merged into one object + +Signature: + +```typescript +export declare type RouteValidatorFullConfig = RouteValidatorConfig & RouteValidatorOptions; +``` diff --git a/docs/development/core/server/kibana-plugin-server.routevalidatoroptions.md b/docs/development/core/server/kibana-plugin-server.routevalidatoroptions.md index 00b029d9928e3c..ddbc9d28c3b063 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidatoroptions.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidatoroptions.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorOptions](./kibana-plugin-server.routevalidatoroptions.md) - -## RouteValidatorOptions interface - -Additional options for the RouteValidator class to modify its default behaviour. - -Signature: - -```typescript -export interface RouteValidatorOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [unsafe](./kibana-plugin-server.routevalidatoroptions.unsafe.md) | {
params?: boolean;
query?: boolean;
body?: boolean;
} | Set the unsafe config to avoid running some additional internal \*safe\* validations on top of your custom validation | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorOptions](./kibana-plugin-server.routevalidatoroptions.md) + +## RouteValidatorOptions interface + +Additional options for the RouteValidator class to modify its default behaviour. + +Signature: + +```typescript +export interface RouteValidatorOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [unsafe](./kibana-plugin-server.routevalidatoroptions.unsafe.md) | {
params?: boolean;
query?: boolean;
body?: boolean;
} | Set the unsafe config to avoid running some additional internal \*safe\* validations on top of your custom validation | + diff --git a/docs/development/core/server/kibana-plugin-server.routevalidatoroptions.unsafe.md b/docs/development/core/server/kibana-plugin-server.routevalidatoroptions.unsafe.md index 0406a372c4e9d7..60f868aedfc058 100644 --- a/docs/development/core/server/kibana-plugin-server.routevalidatoroptions.unsafe.md +++ b/docs/development/core/server/kibana-plugin-server.routevalidatoroptions.unsafe.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorOptions](./kibana-plugin-server.routevalidatoroptions.md) > [unsafe](./kibana-plugin-server.routevalidatoroptions.unsafe.md) - -## RouteValidatorOptions.unsafe property - -Set the `unsafe` config to avoid running some additional internal \*safe\* validations on top of your custom validation - -Signature: - -```typescript -unsafe?: { - params?: boolean; - query?: boolean; - body?: boolean; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RouteValidatorOptions](./kibana-plugin-server.routevalidatoroptions.md) > [unsafe](./kibana-plugin-server.routevalidatoroptions.unsafe.md) + +## RouteValidatorOptions.unsafe property + +Set the `unsafe` config to avoid running some additional internal \*safe\* validations on top of your custom validation + +Signature: + +```typescript +unsafe?: { + params?: boolean; + query?: boolean; + body?: boolean; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.attributes.md b/docs/development/core/server/kibana-plugin-server.savedobject.attributes.md index 7049ca65e96d37..8284548d9d94cd 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.attributes.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.attributes.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [attributes](./kibana-plugin-server.savedobject.attributes.md) - -## SavedObject.attributes property - -The data for a Saved Object is stored as an object in the `attributes` property. - -Signature: - -```typescript -attributes: T; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [attributes](./kibana-plugin-server.savedobject.attributes.md) + +## SavedObject.attributes property + +The data for a Saved Object is stored as an object in the `attributes` property. + +Signature: + +```typescript +attributes: T; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.error.md b/docs/development/core/server/kibana-plugin-server.savedobject.error.md index 910f1fa32d5df5..4baea1599eae8b 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.error.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.error.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [error](./kibana-plugin-server.savedobject.error.md) - -## SavedObject.error property - -Signature: - -```typescript -error?: { - message: string; - statusCode: number; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [error](./kibana-plugin-server.savedobject.error.md) + +## SavedObject.error property + +Signature: + +```typescript +error?: { + message: string; + statusCode: number; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.id.md b/docs/development/core/server/kibana-plugin-server.savedobject.id.md index cc0127eb6ab04b..7048d103652994 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [id](./kibana-plugin-server.savedobject.id.md) - -## SavedObject.id property - -The ID of this Saved Object, guaranteed to be unique for all objects of the same `type` - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [id](./kibana-plugin-server.savedobject.id.md) + +## SavedObject.id property + +The ID of this Saved Object, guaranteed to be unique for all objects of the same `type` + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.md b/docs/development/core/server/kibana-plugin-server.savedobject.md index c7099cdce7ecd1..b3184fd38ad93c 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) - -## SavedObject interface - - -Signature: - -```typescript -export interface SavedObject -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [attributes](./kibana-plugin-server.savedobject.attributes.md) | T | The data for a Saved Object is stored as an object in the attributes property. | -| [error](./kibana-plugin-server.savedobject.error.md) | {
message: string;
statusCode: number;
} | | -| [id](./kibana-plugin-server.savedobject.id.md) | string | The ID of this Saved Object, guaranteed to be unique for all objects of the same type | -| [migrationVersion](./kibana-plugin-server.savedobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | -| [references](./kibana-plugin-server.savedobject.references.md) | SavedObjectReference[] | A reference to another saved object. | -| [type](./kibana-plugin-server.savedobject.type.md) | string | The type of Saved Object. Each plugin can define it's own custom Saved Object types. | -| [updated\_at](./kibana-plugin-server.savedobject.updated_at.md) | string | Timestamp of the last time this document had been updated. | -| [version](./kibana-plugin-server.savedobject.version.md) | string | An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) + +## SavedObject interface + + +Signature: + +```typescript +export interface SavedObject +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [attributes](./kibana-plugin-server.savedobject.attributes.md) | T | The data for a Saved Object is stored as an object in the attributes property. | +| [error](./kibana-plugin-server.savedobject.error.md) | {
message: string;
statusCode: number;
} | | +| [id](./kibana-plugin-server.savedobject.id.md) | string | The ID of this Saved Object, guaranteed to be unique for all objects of the same type | +| [migrationVersion](./kibana-plugin-server.savedobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [references](./kibana-plugin-server.savedobject.references.md) | SavedObjectReference[] | A reference to another saved object. | +| [type](./kibana-plugin-server.savedobject.type.md) | string | The type of Saved Object. Each plugin can define it's own custom Saved Object types. | +| [updated\_at](./kibana-plugin-server.savedobject.updated_at.md) | string | Timestamp of the last time this document had been updated. | +| [version](./kibana-plugin-server.savedobject.version.md) | string | An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.migrationversion.md b/docs/development/core/server/kibana-plugin-server.savedobject.migrationversion.md index 63c353a8b2e75d..5e8486ebb8b088 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.migrationversion.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.migrationversion.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [migrationVersion](./kibana-plugin-server.savedobject.migrationversion.md) - -## SavedObject.migrationVersion property - -Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. - -Signature: - -```typescript -migrationVersion?: SavedObjectsMigrationVersion; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [migrationVersion](./kibana-plugin-server.savedobject.migrationversion.md) + +## SavedObject.migrationVersion property + +Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. + +Signature: + +```typescript +migrationVersion?: SavedObjectsMigrationVersion; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.references.md b/docs/development/core/server/kibana-plugin-server.savedobject.references.md index 22d4c84e9bcade..7381e0e814748a 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.references.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.references.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [references](./kibana-plugin-server.savedobject.references.md) - -## SavedObject.references property - -A reference to another saved object. - -Signature: - -```typescript -references: SavedObjectReference[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [references](./kibana-plugin-server.savedobject.references.md) + +## SavedObject.references property + +A reference to another saved object. + +Signature: + +```typescript +references: SavedObjectReference[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.type.md b/docs/development/core/server/kibana-plugin-server.savedobject.type.md index 0498b2d780484f..0e79e6ccb54cb7 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.type.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [type](./kibana-plugin-server.savedobject.type.md) - -## SavedObject.type property - -The type of Saved Object. Each plugin can define it's own custom Saved Object types. - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [type](./kibana-plugin-server.savedobject.type.md) + +## SavedObject.type property + +The type of Saved Object. Each plugin can define it's own custom Saved Object types. + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.updated_at.md b/docs/development/core/server/kibana-plugin-server.savedobject.updated_at.md index bf57cbc08dbb4c..38db2a5e96398d 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.updated_at.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.updated_at.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [updated\_at](./kibana-plugin-server.savedobject.updated_at.md) - -## SavedObject.updated\_at property - -Timestamp of the last time this document had been updated. - -Signature: - -```typescript -updated_at?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [updated\_at](./kibana-plugin-server.savedobject.updated_at.md) + +## SavedObject.updated\_at property + +Timestamp of the last time this document had been updated. + +Signature: + +```typescript +updated_at?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobject.version.md b/docs/development/core/server/kibana-plugin-server.savedobject.version.md index a1c2f2c6c3b44a..e81e37198226c6 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobject.version.md +++ b/docs/development/core/server/kibana-plugin-server.savedobject.version.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [version](./kibana-plugin-server.savedobject.version.md) - -## SavedObject.version property - -An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. - -Signature: - -```typescript -version?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObject](./kibana-plugin-server.savedobject.md) > [version](./kibana-plugin-server.savedobject.version.md) + +## SavedObject.version property + +An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. + +Signature: + +```typescript +version?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectattribute.md b/docs/development/core/server/kibana-plugin-server.savedobjectattribute.md index 6696d9c6ce96da..b25fc079a7d7bc 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectattribute.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectattribute.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) - -## SavedObjectAttribute type - -Type definition for a Saved Object attribute value - -Signature: - -```typescript -export declare type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttributeSingle[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) + +## SavedObjectAttribute type + +Type definition for a Saved Object attribute value + +Signature: + +```typescript +export declare type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttributeSingle[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectattributes.md b/docs/development/core/server/kibana-plugin-server.savedobjectattributes.md index 6d24eb02b4eaf0..7e80e757775bb0 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectattributes.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectattributes.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectAttributes](./kibana-plugin-server.savedobjectattributes.md) - -## SavedObjectAttributes interface - -The data for a Saved Object is stored as an object in the `attributes` property. - -Signature: - -```typescript -export interface SavedObjectAttributes -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectAttributes](./kibana-plugin-server.savedobjectattributes.md) + +## SavedObjectAttributes interface + +The data for a Saved Object is stored as an object in the `attributes` property. + +Signature: + +```typescript +export interface SavedObjectAttributes +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectattributesingle.md b/docs/development/core/server/kibana-plugin-server.savedobjectattributesingle.md index b2ddb59ddb2522..7928b594bf9dc9 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectattributesingle.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectattributesingle.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectAttributeSingle](./kibana-plugin-server.savedobjectattributesingle.md) - -## SavedObjectAttributeSingle type - -Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) - -Signature: - -```typescript -export declare type SavedObjectAttributeSingle = string | number | boolean | null | undefined | SavedObjectAttributes; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectAttributeSingle](./kibana-plugin-server.savedobjectattributesingle.md) + +## SavedObjectAttributeSingle type + +Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) + +Signature: + +```typescript +export declare type SavedObjectAttributeSingle = string | number | boolean | null | undefined | SavedObjectAttributes; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectreference.id.md b/docs/development/core/server/kibana-plugin-server.savedobjectreference.id.md index f6e11c0228743c..e4d7ff3e8e8314 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectreference.id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectreference.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) > [id](./kibana-plugin-server.savedobjectreference.id.md) - -## SavedObjectReference.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) > [id](./kibana-plugin-server.savedobjectreference.id.md) + +## SavedObjectReference.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectreference.md b/docs/development/core/server/kibana-plugin-server.savedobjectreference.md index 75cf59ea3b9254..3ceb1c3c949fe4 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectreference.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectreference.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) - -## SavedObjectReference interface - -A reference to another saved object. - -Signature: - -```typescript -export interface SavedObjectReference -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [id](./kibana-plugin-server.savedobjectreference.id.md) | string | | -| [name](./kibana-plugin-server.savedobjectreference.name.md) | string | | -| [type](./kibana-plugin-server.savedobjectreference.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) + +## SavedObjectReference interface + +A reference to another saved object. + +Signature: + +```typescript +export interface SavedObjectReference +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-server.savedobjectreference.id.md) | string | | +| [name](./kibana-plugin-server.savedobjectreference.name.md) | string | | +| [type](./kibana-plugin-server.savedobjectreference.type.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectreference.name.md b/docs/development/core/server/kibana-plugin-server.savedobjectreference.name.md index 8a88128c3fbc10..f22884367db27a 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectreference.name.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectreference.name.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) > [name](./kibana-plugin-server.savedobjectreference.name.md) - -## SavedObjectReference.name property - -Signature: - -```typescript -name: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) > [name](./kibana-plugin-server.savedobjectreference.name.md) + +## SavedObjectReference.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectreference.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectreference.type.md index 5347256dfa2dc1..2d34cec0bc3a5f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectreference.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectreference.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) > [type](./kibana-plugin-server.savedobjectreference.type.md) - -## SavedObjectReference.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectReference](./kibana-plugin-server.savedobjectreference.md) > [type](./kibana-plugin-server.savedobjectreference.type.md) + +## SavedObjectReference.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbaseoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbaseoptions.md index 6eace924490cc4..daf5a36ffc6903 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbaseoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbaseoptions.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBaseOptions](./kibana-plugin-server.savedobjectsbaseoptions.md) - -## SavedObjectsBaseOptions interface - - -Signature: - -```typescript -export interface SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [namespace](./kibana-plugin-server.savedobjectsbaseoptions.namespace.md) | string | Specify the namespace for this operation | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBaseOptions](./kibana-plugin-server.savedobjectsbaseoptions.md) + +## SavedObjectsBaseOptions interface + + +Signature: + +```typescript +export interface SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [namespace](./kibana-plugin-server.savedobjectsbaseoptions.namespace.md) | string | Specify the namespace for this operation | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbaseoptions.namespace.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbaseoptions.namespace.md index 6e921dc8ab60e7..97eb45d70cef2d 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbaseoptions.namespace.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbaseoptions.namespace.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBaseOptions](./kibana-plugin-server.savedobjectsbaseoptions.md) > [namespace](./kibana-plugin-server.savedobjectsbaseoptions.namespace.md) - -## SavedObjectsBaseOptions.namespace property - -Specify the namespace for this operation - -Signature: - -```typescript -namespace?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBaseOptions](./kibana-plugin-server.savedobjectsbaseoptions.md) > [namespace](./kibana-plugin-server.savedobjectsbaseoptions.namespace.md) + +## SavedObjectsBaseOptions.namespace property + +Specify the namespace for this operation + +Signature: + +```typescript +namespace?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.attributes.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.attributes.md index cfa19c5fb3fd81..ca45721381c3b0 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.attributes.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.attributes.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [attributes](./kibana-plugin-server.savedobjectsbulkcreateobject.attributes.md) - -## SavedObjectsBulkCreateObject.attributes property - -Signature: - -```typescript -attributes: T; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [attributes](./kibana-plugin-server.savedobjectsbulkcreateobject.attributes.md) + +## SavedObjectsBulkCreateObject.attributes property + +Signature: + +```typescript +attributes: T; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.id.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.id.md index 6b8b65339ffa39..3eceb5c782a818 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [id](./kibana-plugin-server.savedobjectsbulkcreateobject.id.md) - -## SavedObjectsBulkCreateObject.id property - -Signature: - -```typescript -id?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [id](./kibana-plugin-server.savedobjectsbulkcreateobject.id.md) + +## SavedObjectsBulkCreateObject.id property + +Signature: + +```typescript +id?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.md index bae275777310a6..87386b986009da 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) - -## SavedObjectsBulkCreateObject interface - - -Signature: - -```typescript -export interface SavedObjectsBulkCreateObject -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [attributes](./kibana-plugin-server.savedobjectsbulkcreateobject.attributes.md) | T | | -| [id](./kibana-plugin-server.savedobjectsbulkcreateobject.id.md) | string | | -| [migrationVersion](./kibana-plugin-server.savedobjectsbulkcreateobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | -| [references](./kibana-plugin-server.savedobjectsbulkcreateobject.references.md) | SavedObjectReference[] | | -| [type](./kibana-plugin-server.savedobjectsbulkcreateobject.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) + +## SavedObjectsBulkCreateObject interface + + +Signature: + +```typescript +export interface SavedObjectsBulkCreateObject +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [attributes](./kibana-plugin-server.savedobjectsbulkcreateobject.attributes.md) | T | | +| [id](./kibana-plugin-server.savedobjectsbulkcreateobject.id.md) | string | | +| [migrationVersion](./kibana-plugin-server.savedobjectsbulkcreateobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [references](./kibana-plugin-server.savedobjectsbulkcreateobject.references.md) | SavedObjectReference[] | | +| [type](./kibana-plugin-server.savedobjectsbulkcreateobject.type.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.migrationversion.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.migrationversion.md index 6065988a8d0fce..df76370da2426a 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.migrationversion.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.migrationversion.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [migrationVersion](./kibana-plugin-server.savedobjectsbulkcreateobject.migrationversion.md) - -## SavedObjectsBulkCreateObject.migrationVersion property - -Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. - -Signature: - -```typescript -migrationVersion?: SavedObjectsMigrationVersion; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [migrationVersion](./kibana-plugin-server.savedobjectsbulkcreateobject.migrationversion.md) + +## SavedObjectsBulkCreateObject.migrationVersion property + +Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. + +Signature: + +```typescript +migrationVersion?: SavedObjectsMigrationVersion; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.references.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.references.md index 0a96787de03a9d..9674dc69ef71e2 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.references.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.references.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [references](./kibana-plugin-server.savedobjectsbulkcreateobject.references.md) - -## SavedObjectsBulkCreateObject.references property - -Signature: - -```typescript -references?: SavedObjectReference[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [references](./kibana-plugin-server.savedobjectsbulkcreateobject.references.md) + +## SavedObjectsBulkCreateObject.references property + +Signature: + +```typescript +references?: SavedObjectReference[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.type.md index 8db44a46d7f3f9..a68f614f73eb79 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkcreateobject.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [type](./kibana-plugin-server.savedobjectsbulkcreateobject.type.md) - -## SavedObjectsBulkCreateObject.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-server.savedobjectsbulkcreateobject.md) > [type](./kibana-plugin-server.savedobjectsbulkcreateobject.type.md) + +## SavedObjectsBulkCreateObject.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.fields.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.fields.md index d67df82b123e79..fdea718e27a602 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.fields.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.fields.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) > [fields](./kibana-plugin-server.savedobjectsbulkgetobject.fields.md) - -## SavedObjectsBulkGetObject.fields property - -SavedObject fields to include in the response - -Signature: - -```typescript -fields?: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) > [fields](./kibana-plugin-server.savedobjectsbulkgetobject.fields.md) + +## SavedObjectsBulkGetObject.fields property + +SavedObject fields to include in the response + +Signature: + +```typescript +fields?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.id.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.id.md index 3476d3276181cd..78f37d8a62a00d 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) > [id](./kibana-plugin-server.savedobjectsbulkgetobject.id.md) - -## SavedObjectsBulkGetObject.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) > [id](./kibana-plugin-server.savedobjectsbulkgetobject.id.md) + +## SavedObjectsBulkGetObject.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.md index ae89f30b9f7544..ef8b76a4188488 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) - -## SavedObjectsBulkGetObject interface - - -Signature: - -```typescript -export interface SavedObjectsBulkGetObject -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [fields](./kibana-plugin-server.savedobjectsbulkgetobject.fields.md) | string[] | SavedObject fields to include in the response | -| [id](./kibana-plugin-server.savedobjectsbulkgetobject.id.md) | string | | -| [type](./kibana-plugin-server.savedobjectsbulkgetobject.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) + +## SavedObjectsBulkGetObject interface + + +Signature: + +```typescript +export interface SavedObjectsBulkGetObject +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [fields](./kibana-plugin-server.savedobjectsbulkgetobject.fields.md) | string[] | SavedObject fields to include in the response | +| [id](./kibana-plugin-server.savedobjectsbulkgetobject.id.md) | string | | +| [type](./kibana-plugin-server.savedobjectsbulkgetobject.type.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.type.md index c3fef3704faa7e..2317170fa04a2b 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkgetobject.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) > [type](./kibana-plugin-server.savedobjectsbulkgetobject.type.md) - -## SavedObjectsBulkGetObject.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) > [type](./kibana-plugin-server.savedobjectsbulkgetobject.type.md) + +## SavedObjectsBulkGetObject.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkresponse.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkresponse.md index 7ff4934a2af66a..20a1194c87eda4 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkresponse.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkresponse.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkResponse](./kibana-plugin-server.savedobjectsbulkresponse.md) - -## SavedObjectsBulkResponse interface - - -Signature: - -```typescript -export interface SavedObjectsBulkResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [saved\_objects](./kibana-plugin-server.savedobjectsbulkresponse.saved_objects.md) | Array<SavedObject<T>> | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkResponse](./kibana-plugin-server.savedobjectsbulkresponse.md) + +## SavedObjectsBulkResponse interface + + +Signature: + +```typescript +export interface SavedObjectsBulkResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [saved\_objects](./kibana-plugin-server.savedobjectsbulkresponse.saved_objects.md) | Array<SavedObject<T>> | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkresponse.saved_objects.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkresponse.saved_objects.md index 78f0fe36eaedcc..c6cfb230f75ebd 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkresponse.saved_objects.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkresponse.saved_objects.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkResponse](./kibana-plugin-server.savedobjectsbulkresponse.md) > [saved\_objects](./kibana-plugin-server.savedobjectsbulkresponse.saved_objects.md) - -## SavedObjectsBulkResponse.saved\_objects property - -Signature: - -```typescript -saved_objects: Array>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkResponse](./kibana-plugin-server.savedobjectsbulkresponse.md) > [saved\_objects](./kibana-plugin-server.savedobjectsbulkresponse.saved_objects.md) + +## SavedObjectsBulkResponse.saved\_objects property + +Signature: + +```typescript +saved_objects: Array>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.attributes.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.attributes.md index 3de73d133d7a78..bd80c8d093d0fa 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.attributes.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.attributes.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) > [attributes](./kibana-plugin-server.savedobjectsbulkupdateobject.attributes.md) - -## SavedObjectsBulkUpdateObject.attributes property - -The data for a Saved Object is stored as an object in the `attributes` property. - -Signature: - -```typescript -attributes: Partial; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) > [attributes](./kibana-plugin-server.savedobjectsbulkupdateobject.attributes.md) + +## SavedObjectsBulkUpdateObject.attributes property + +The data for a Saved Object is stored as an object in the `attributes` property. + +Signature: + +```typescript +attributes: Partial; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.id.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.id.md index 88bc9f306b26cd..1cdaf5288c0ca4 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) > [id](./kibana-plugin-server.savedobjectsbulkupdateobject.id.md) - -## SavedObjectsBulkUpdateObject.id property - -The ID of this Saved Object, guaranteed to be unique for all objects of the same `type` - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) > [id](./kibana-plugin-server.savedobjectsbulkupdateobject.id.md) + +## SavedObjectsBulkUpdateObject.id property + +The ID of this Saved Object, guaranteed to be unique for all objects of the same `type` + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.md index b84bbe0a17344b..8e4e3d761148e9 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) - -## SavedObjectsBulkUpdateObject interface - - -Signature: - -```typescript -export interface SavedObjectsBulkUpdateObject extends Pick -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [attributes](./kibana-plugin-server.savedobjectsbulkupdateobject.attributes.md) | Partial<T> | The data for a Saved Object is stored as an object in the attributes property. | -| [id](./kibana-plugin-server.savedobjectsbulkupdateobject.id.md) | string | The ID of this Saved Object, guaranteed to be unique for all objects of the same type | -| [type](./kibana-plugin-server.savedobjectsbulkupdateobject.type.md) | string | The type of this Saved Object. Each plugin can define it's own custom Saved Object types. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) + +## SavedObjectsBulkUpdateObject interface + + +Signature: + +```typescript +export interface SavedObjectsBulkUpdateObject extends Pick +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [attributes](./kibana-plugin-server.savedobjectsbulkupdateobject.attributes.md) | Partial<T> | The data for a Saved Object is stored as an object in the attributes property. | +| [id](./kibana-plugin-server.savedobjectsbulkupdateobject.id.md) | string | The ID of this Saved Object, guaranteed to be unique for all objects of the same type | +| [type](./kibana-plugin-server.savedobjectsbulkupdateobject.type.md) | string | The type of this Saved Object. Each plugin can define it's own custom Saved Object types. | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.type.md index d2d46b24ea8be7..c95faf80c84cba 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateobject.type.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) > [type](./kibana-plugin-server.savedobjectsbulkupdateobject.type.md) - -## SavedObjectsBulkUpdateObject.type property - -The type of this Saved Object. Each plugin can define it's own custom Saved Object types. - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) > [type](./kibana-plugin-server.savedobjectsbulkupdateobject.type.md) + +## SavedObjectsBulkUpdateObject.type property + +The type of this Saved Object. Each plugin can define it's own custom Saved Object types. + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.md index 920a6ca224df49..fb18d80fe3f09f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) - -## SavedObjectsBulkUpdateOptions interface - - -Signature: - -```typescript -export interface SavedObjectsBulkUpdateOptions extends SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [refresh](./kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) + +## SavedObjectsBulkUpdateOptions interface + + +Signature: + +```typescript +export interface SavedObjectsBulkUpdateOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [refresh](./kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md index 35e9e6483da10e..52913cd776ebbe 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) > [refresh](./kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md) - -## SavedObjectsBulkUpdateOptions.refresh property - -The Elasticsearch Refresh setting for this operation - -Signature: - -```typescript -refresh?: MutatingOperationRefreshSetting; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) > [refresh](./kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md) + +## SavedObjectsBulkUpdateOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateresponse.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateresponse.md index 03707bd14a3ebb..065b9df0823cd7 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateresponse.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateresponse.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateResponse](./kibana-plugin-server.savedobjectsbulkupdateresponse.md) - -## SavedObjectsBulkUpdateResponse interface - - -Signature: - -```typescript -export interface SavedObjectsBulkUpdateResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [saved\_objects](./kibana-plugin-server.savedobjectsbulkupdateresponse.saved_objects.md) | Array<SavedObjectsUpdateResponse<T>> | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateResponse](./kibana-plugin-server.savedobjectsbulkupdateresponse.md) + +## SavedObjectsBulkUpdateResponse interface + + +Signature: + +```typescript +export interface SavedObjectsBulkUpdateResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [saved\_objects](./kibana-plugin-server.savedobjectsbulkupdateresponse.saved_objects.md) | Array<SavedObjectsUpdateResponse<T>> | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateresponse.saved_objects.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateresponse.saved_objects.md index 0ca54ca1762923..b8fc07b819bed0 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateresponse.saved_objects.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateresponse.saved_objects.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateResponse](./kibana-plugin-server.savedobjectsbulkupdateresponse.md) > [saved\_objects](./kibana-plugin-server.savedobjectsbulkupdateresponse.saved_objects.md) - -## SavedObjectsBulkUpdateResponse.saved\_objects property - -Signature: - -```typescript -saved_objects: Array>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateResponse](./kibana-plugin-server.savedobjectsbulkupdateresponse.md) > [saved\_objects](./kibana-plugin-server.savedobjectsbulkupdateresponse.saved_objects.md) + +## SavedObjectsBulkUpdateResponse.saved\_objects property + +Signature: + +```typescript +saved_objects: Array>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkcreate.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkcreate.md index 1081a91f927624..40f947188de545 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkcreate.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkcreate.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [bulkCreate](./kibana-plugin-server.savedobjectsclient.bulkcreate.md) - -## SavedObjectsClient.bulkCreate() method - -Persists multiple documents batched together as a single request - -Signature: - -```typescript -bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| objects | Array<SavedObjectsBulkCreateObject<T>> | | -| options | SavedObjectsCreateOptions | | - -Returns: - -`Promise>` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [bulkCreate](./kibana-plugin-server.savedobjectsclient.bulkcreate.md) + +## SavedObjectsClient.bulkCreate() method + +Persists multiple documents batched together as a single request + +Signature: + +```typescript +bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | Array<SavedObjectsBulkCreateObject<T>> | | +| options | SavedObjectsCreateOptions | | + +Returns: + +`Promise>` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkget.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkget.md index 6fbeadd4ce67c4..c86c30d14db3b8 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkget.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkget.md @@ -1,29 +1,29 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [bulkGet](./kibana-plugin-server.savedobjectsclient.bulkget.md) - -## SavedObjectsClient.bulkGet() method - -Returns an array of objects by id - -Signature: - -```typescript -bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| objects | SavedObjectsBulkGetObject[] | an array of ids, or an array of objects containing id, type and optionally fields | -| options | SavedObjectsBaseOptions | | - -Returns: - -`Promise>` - -## Example - -bulkGet(\[ { id: 'one', type: 'config' }, { id: 'foo', type: 'index-pattern' } \]) - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [bulkGet](./kibana-plugin-server.savedobjectsclient.bulkget.md) + +## SavedObjectsClient.bulkGet() method + +Returns an array of objects by id + +Signature: + +```typescript +bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | SavedObjectsBulkGetObject[] | an array of ids, or an array of objects containing id, type and optionally fields | +| options | SavedObjectsBaseOptions | | + +Returns: + +`Promise>` + +## Example + +bulkGet(\[ { id: 'one', type: 'config' }, { id: 'foo', type: 'index-pattern' } \]) + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkupdate.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkupdate.md index 30db524ffa02c8..33958837ebca39 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkupdate.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkupdate.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [bulkUpdate](./kibana-plugin-server.savedobjectsclient.bulkupdate.md) - -## SavedObjectsClient.bulkUpdate() method - -Bulk Updates multiple SavedObject at once - -Signature: - -```typescript -bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| objects | Array<SavedObjectsBulkUpdateObject<T>> | | -| options | SavedObjectsBulkUpdateOptions | | - -Returns: - -`Promise>` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [bulkUpdate](./kibana-plugin-server.savedobjectsclient.bulkupdate.md) + +## SavedObjectsClient.bulkUpdate() method + +Bulk Updates multiple SavedObject at once + +Signature: + +```typescript +bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | Array<SavedObjectsBulkUpdateObject<T>> | | +| options | SavedObjectsBulkUpdateOptions | | + +Returns: + +`Promise>` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.create.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.create.md index 68b97ccdf2aef4..ddb78a57e71bc6 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.create.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.create.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [create](./kibana-plugin-server.savedobjectsclient.create.md) - -## SavedObjectsClient.create() method - -Persists a SavedObject - -Signature: - -```typescript -create(type: string, attributes: T, options?: SavedObjectsCreateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| attributes | T | | -| options | SavedObjectsCreateOptions | | - -Returns: - -`Promise>` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [create](./kibana-plugin-server.savedobjectsclient.create.md) + +## SavedObjectsClient.create() method + +Persists a SavedObject + +Signature: + +```typescript +create(type: string, attributes: T, options?: SavedObjectsCreateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| attributes | T | | +| options | SavedObjectsCreateOptions | | + +Returns: + +`Promise>` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.delete.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.delete.md index c20c7e886490a4..310ab0d78f7a6f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.delete.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.delete.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [delete](./kibana-plugin-server.savedobjectsclient.delete.md) - -## SavedObjectsClient.delete() method - -Deletes a SavedObject - -Signature: - -```typescript -delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| id | string | | -| options | SavedObjectsDeleteOptions | | - -Returns: - -`Promise<{}>` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [delete](./kibana-plugin-server.savedobjectsclient.delete.md) + +## SavedObjectsClient.delete() method + +Deletes a SavedObject + +Signature: + +```typescript +delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| options | SavedObjectsDeleteOptions | | + +Returns: + +`Promise<{}>` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.errors.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.errors.md index f08440485c63c5..9e6eb8d4140021 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.errors.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.errors.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [errors](./kibana-plugin-server.savedobjectsclient.errors.md) - -## SavedObjectsClient.errors property - -Signature: - -```typescript -static errors: typeof SavedObjectsErrorHelpers; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [errors](./kibana-plugin-server.savedobjectsclient.errors.md) + +## SavedObjectsClient.errors property + +Signature: + +```typescript +static errors: typeof SavedObjectsErrorHelpers; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.find.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.find.md index a590cc4c4b663d..f72691d3ce0c87 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.find.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.find.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [find](./kibana-plugin-server.savedobjectsclient.find.md) - -## SavedObjectsClient.find() method - -Find all SavedObjects matching the search query - -Signature: - -```typescript -find(options: SavedObjectsFindOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| options | SavedObjectsFindOptions | | - -Returns: - -`Promise>` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [find](./kibana-plugin-server.savedobjectsclient.find.md) + +## SavedObjectsClient.find() method + +Find all SavedObjects matching the search query + +Signature: + +```typescript +find(options: SavedObjectsFindOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | SavedObjectsFindOptions | | + +Returns: + +`Promise>` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.get.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.get.md index bde16a134f5b59..3906462184d4f9 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.get.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.get.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [get](./kibana-plugin-server.savedobjectsclient.get.md) - -## SavedObjectsClient.get() method - -Retrieves a single object - -Signature: - -```typescript -get(type: string, id: string, options?: SavedObjectsBaseOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | The type of SavedObject to retrieve | -| id | string | The ID of the SavedObject to retrieve | -| options | SavedObjectsBaseOptions | | - -Returns: - -`Promise>` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [get](./kibana-plugin-server.savedobjectsclient.get.md) + +## SavedObjectsClient.get() method + +Retrieves a single object + +Signature: + +```typescript +get(type: string, id: string, options?: SavedObjectsBaseOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | The type of SavedObject to retrieve | +| id | string | The ID of the SavedObject to retrieve | +| options | SavedObjectsBaseOptions | | + +Returns: + +`Promise>` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.md index e68486ecff874e..4a42c11e511dfd 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.md @@ -1,36 +1,36 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) - -## SavedObjectsClient class - -Signature: - -```typescript -export declare class SavedObjectsClient -``` - -## Remarks - -The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `SavedObjectsClient` class. - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [errors](./kibana-plugin-server.savedobjectsclient.errors.md) | | typeof SavedObjectsErrorHelpers | | -| [errors](./kibana-plugin-server.savedobjectsclient.errors.md) | static | typeof SavedObjectsErrorHelpers | | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [bulkCreate(objects, options)](./kibana-plugin-server.savedobjectsclient.bulkcreate.md) | | Persists multiple documents batched together as a single request | -| [bulkGet(objects, options)](./kibana-plugin-server.savedobjectsclient.bulkget.md) | | Returns an array of objects by id | -| [bulkUpdate(objects, options)](./kibana-plugin-server.savedobjectsclient.bulkupdate.md) | | Bulk Updates multiple SavedObject at once | -| [create(type, attributes, options)](./kibana-plugin-server.savedobjectsclient.create.md) | | Persists a SavedObject | -| [delete(type, id, options)](./kibana-plugin-server.savedobjectsclient.delete.md) | | Deletes a SavedObject | -| [find(options)](./kibana-plugin-server.savedobjectsclient.find.md) | | Find all SavedObjects matching the search query | -| [get(type, id, options)](./kibana-plugin-server.savedobjectsclient.get.md) | | Retrieves a single object | -| [update(type, id, attributes, options)](./kibana-plugin-server.savedobjectsclient.update.md) | | Updates an SavedObject | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) + +## SavedObjectsClient class + +Signature: + +```typescript +export declare class SavedObjectsClient +``` + +## Remarks + +The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `SavedObjectsClient` class. + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [errors](./kibana-plugin-server.savedobjectsclient.errors.md) | | typeof SavedObjectsErrorHelpers | | +| [errors](./kibana-plugin-server.savedobjectsclient.errors.md) | static | typeof SavedObjectsErrorHelpers | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [bulkCreate(objects, options)](./kibana-plugin-server.savedobjectsclient.bulkcreate.md) | | Persists multiple documents batched together as a single request | +| [bulkGet(objects, options)](./kibana-plugin-server.savedobjectsclient.bulkget.md) | | Returns an array of objects by id | +| [bulkUpdate(objects, options)](./kibana-plugin-server.savedobjectsclient.bulkupdate.md) | | Bulk Updates multiple SavedObject at once | +| [create(type, attributes, options)](./kibana-plugin-server.savedobjectsclient.create.md) | | Persists a SavedObject | +| [delete(type, id, options)](./kibana-plugin-server.savedobjectsclient.delete.md) | | Deletes a SavedObject | +| [find(options)](./kibana-plugin-server.savedobjectsclient.find.md) | | Find all SavedObjects matching the search query | +| [get(type, id, options)](./kibana-plugin-server.savedobjectsclient.get.md) | | Retrieves a single object | +| [update(type, id, attributes, options)](./kibana-plugin-server.savedobjectsclient.update.md) | | Updates an SavedObject | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.update.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.update.md index 16454c98bb55b3..2c71e518b7b05f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.update.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.update.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [update](./kibana-plugin-server.savedobjectsclient.update.md) - -## SavedObjectsClient.update() method - -Updates an SavedObject - -Signature: - -```typescript -update(type: string, id: string, attributes: Partial, options?: SavedObjectsUpdateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| id | string | | -| attributes | Partial<T> | | -| options | SavedObjectsUpdateOptions | | - -Returns: - -`Promise>` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) > [update](./kibana-plugin-server.savedobjectsclient.update.md) + +## SavedObjectsClient.update() method + +Updates an SavedObject + +Signature: + +```typescript +update(type: string, id: string, attributes: Partial, options?: SavedObjectsUpdateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| attributes | Partial<T> | | +| options | SavedObjectsUpdateOptions | | + +Returns: + +`Promise>` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientcontract.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientcontract.md index bc5b11dd21b785..c21c7bfe978ab3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientcontract.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientcontract.md @@ -1,43 +1,43 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientContract](./kibana-plugin-server.savedobjectsclientcontract.md) - -## SavedObjectsClientContract type - -Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. - -\#\# SavedObjectsClient errors - -Since the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either: - -1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) - -Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the `isXYZError()` helpers exposed at `SavedObjectsErrorHelpers` should be used to understand and manage error responses from the `SavedObjectsClient`. - -Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for `error.body.error.type` or doing substring checks on `error.body.error.reason`, just use the helpers to understand the meaning of the error: - -\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 } - -if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know } - -// always rethrow the error unless you handle it throw error; \`\`\` - -\#\#\# 404s from missing index - -From the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing. - -At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages. - -From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing. - -\#\#\# 503s from missing index - -Unlike all other methods, create requests are supposed to succeed even when the Kibana index does not exist because it will be automatically created by elasticsearch. When that is not the case it is because Elasticsearch's `action.auto_create_index` setting prevents it from being created automatically so we throw a special 503 with the intention of informing the user that their Elasticsearch settings need to be updated. - -See [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) See [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) - -Signature: - -```typescript -export declare type SavedObjectsClientContract = Pick; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientContract](./kibana-plugin-server.savedobjectsclientcontract.md) + +## SavedObjectsClientContract type + +Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. + +\#\# SavedObjectsClient errors + +Since the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either: + +1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) + +Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the `isXYZError()` helpers exposed at `SavedObjectsErrorHelpers` should be used to understand and manage error responses from the `SavedObjectsClient`. + +Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for `error.body.error.type` or doing substring checks on `error.body.error.reason`, just use the helpers to understand the meaning of the error: + +\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 } + +if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know } + +// always rethrow the error unless you handle it throw error; \`\`\` + +\#\#\# 404s from missing index + +From the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing. + +At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages. + +From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing. + +\#\#\# 503s from missing index + +Unlike all other methods, create requests are supposed to succeed even when the Kibana index does not exist because it will be automatically created by elasticsearch. When that is not the case it is because Elasticsearch's `action.auto_create_index` setting prevents it from being created automatically so we throw a special 503 with the intention of informing the user that their Elasticsearch settings need to be updated. + +See [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) See [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) + +Signature: + +```typescript +export declare type SavedObjectsClientContract = Pick; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientfactory.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientfactory.md index 9e307597206800..01c6c6a108b7b0 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientfactory.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientfactory.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientFactory](./kibana-plugin-server.savedobjectsclientfactory.md) - -## SavedObjectsClientFactory type - -Describes the factory used to create instances of the Saved Objects Client. - -Signature: - -```typescript -export declare type SavedObjectsClientFactory = ({ request, }: { - request: Request; -}) => SavedObjectsClientContract; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientFactory](./kibana-plugin-server.savedobjectsclientfactory.md) + +## SavedObjectsClientFactory type + +Describes the factory used to create instances of the Saved Objects Client. + +Signature: + +```typescript +export declare type SavedObjectsClientFactory = ({ request, }: { + request: KibanaRequest; +}) => SavedObjectsClientContract; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientfactoryprovider.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientfactoryprovider.md new file mode 100644 index 00000000000000..59617b6be443cd --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientfactoryprovider.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientFactoryProvider](./kibana-plugin-server.savedobjectsclientfactoryprovider.md) + +## SavedObjectsClientFactoryProvider type + +Provider to invoke to retrieve a [SavedObjectsClientFactory](./kibana-plugin-server.savedobjectsclientfactory.md). + +Signature: + +```typescript +export declare type SavedObjectsClientFactoryProvider = (repositoryFactory: SavedObjectsRepositoryFactory) => SavedObjectsClientFactory; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientprovideroptions.excludedwrappers.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientprovideroptions.excludedwrappers.md index 9eb036c01e26ed..344a1b5e153aa3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientprovideroptions.excludedwrappers.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientprovideroptions.excludedwrappers.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientProviderOptions](./kibana-plugin-server.savedobjectsclientprovideroptions.md) > [excludedWrappers](./kibana-plugin-server.savedobjectsclientprovideroptions.excludedwrappers.md) - -## SavedObjectsClientProviderOptions.excludedWrappers property - -Signature: - -```typescript -excludedWrappers?: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientProviderOptions](./kibana-plugin-server.savedobjectsclientprovideroptions.md) > [excludedWrappers](./kibana-plugin-server.savedobjectsclientprovideroptions.excludedwrappers.md) + +## SavedObjectsClientProviderOptions.excludedWrappers property + +Signature: + +```typescript +excludedWrappers?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientprovideroptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientprovideroptions.md index 29b872a30a3734..8027bf1c78c9f4 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientprovideroptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientprovideroptions.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientProviderOptions](./kibana-plugin-server.savedobjectsclientprovideroptions.md) - -## SavedObjectsClientProviderOptions interface - -Options to control the creation of the Saved Objects Client. - -Signature: - -```typescript -export interface SavedObjectsClientProviderOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [excludedWrappers](./kibana-plugin-server.savedobjectsclientprovideroptions.excludedwrappers.md) | string[] | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientProviderOptions](./kibana-plugin-server.savedobjectsclientprovideroptions.md) + +## SavedObjectsClientProviderOptions interface + +Options to control the creation of the Saved Objects Client. + +Signature: + +```typescript +export interface SavedObjectsClientProviderOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [excludedWrappers](./kibana-plugin-server.savedobjectsclientprovideroptions.excludedwrappers.md) | string[] | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperfactory.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperfactory.md index 3ef2fac727b018..f429c922099007 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperfactory.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperfactory.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperFactory](./kibana-plugin-server.savedobjectsclientwrapperfactory.md) - -## SavedObjectsClientWrapperFactory type - -Describes the factory used to create instances of Saved Objects Client Wrappers. - -Signature: - -```typescript -export declare type SavedObjectsClientWrapperFactory = (options: SavedObjectsClientWrapperOptions) => SavedObjectsClientContract; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperFactory](./kibana-plugin-server.savedobjectsclientwrapperfactory.md) + +## SavedObjectsClientWrapperFactory type + +Describes the factory used to create instances of Saved Objects Client Wrappers. + +Signature: + +```typescript +export declare type SavedObjectsClientWrapperFactory = (options: SavedObjectsClientWrapperOptions) => SavedObjectsClientContract; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.client.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.client.md index 0545901087bb4d..a154d55f04cc88 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.client.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.client.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) > [client](./kibana-plugin-server.savedobjectsclientwrapperoptions.client.md) - -## SavedObjectsClientWrapperOptions.client property - -Signature: - -```typescript -client: SavedObjectsClientContract; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) > [client](./kibana-plugin-server.savedobjectsclientwrapperoptions.client.md) + +## SavedObjectsClientWrapperOptions.client property + +Signature: + +```typescript +client: SavedObjectsClientContract; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.md index 65e7cfa64c2a66..dfff863898a2b3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) - -## SavedObjectsClientWrapperOptions interface - -Options passed to each SavedObjectsClientWrapperFactory to aid in creating the wrapper instance. - -Signature: - -```typescript -export interface SavedObjectsClientWrapperOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [client](./kibana-plugin-server.savedobjectsclientwrapperoptions.client.md) | SavedObjectsClientContract | | -| [request](./kibana-plugin-server.savedobjectsclientwrapperoptions.request.md) | Request | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) + +## SavedObjectsClientWrapperOptions interface + +Options passed to each SavedObjectsClientWrapperFactory to aid in creating the wrapper instance. + +Signature: + +```typescript +export interface SavedObjectsClientWrapperOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [client](./kibana-plugin-server.savedobjectsclientwrapperoptions.client.md) | SavedObjectsClientContract | | +| [request](./kibana-plugin-server.savedobjectsclientwrapperoptions.request.md) | KibanaRequest | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.request.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.request.md index 0ff75028612d03..89c7e0ed207ffb 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.request.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclientwrapperoptions.request.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) > [request](./kibana-plugin-server.savedobjectsclientwrapperoptions.request.md) - -## SavedObjectsClientWrapperOptions.request property - -Signature: - -```typescript -request: Request; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) > [request](./kibana-plugin-server.savedobjectsclientwrapperoptions.request.md) + +## SavedObjectsClientWrapperOptions.request property + +Signature: + +```typescript +request: KibanaRequest; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.id.md b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.id.md index 1c55342bb0430f..b63eade437ffff 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.id.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [id](./kibana-plugin-server.savedobjectscreateoptions.id.md) - -## SavedObjectsCreateOptions.id property - -(not recommended) Specify an id for the document - -Signature: - -```typescript -id?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [id](./kibana-plugin-server.savedobjectscreateoptions.id.md) + +## SavedObjectsCreateOptions.id property + +(not recommended) Specify an id for the document + +Signature: + +```typescript +id?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.md index e4ad6360569152..8bbafbdf5814be 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) - -## SavedObjectsCreateOptions interface - - -Signature: - -```typescript -export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [id](./kibana-plugin-server.savedobjectscreateoptions.id.md) | string | (not recommended) Specify an id for the document | -| [migrationVersion](./kibana-plugin-server.savedobjectscreateoptions.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | -| [overwrite](./kibana-plugin-server.savedobjectscreateoptions.overwrite.md) | boolean | Overwrite existing documents (defaults to false) | -| [references](./kibana-plugin-server.savedobjectscreateoptions.references.md) | SavedObjectReference[] | | -| [refresh](./kibana-plugin-server.savedobjectscreateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) + +## SavedObjectsCreateOptions interface + + +Signature: + +```typescript +export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-server.savedobjectscreateoptions.id.md) | string | (not recommended) Specify an id for the document | +| [migrationVersion](./kibana-plugin-server.savedobjectscreateoptions.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [overwrite](./kibana-plugin-server.savedobjectscreateoptions.overwrite.md) | boolean | Overwrite existing documents (defaults to false) | +| [references](./kibana-plugin-server.savedobjectscreateoptions.references.md) | SavedObjectReference[] | | +| [refresh](./kibana-plugin-server.savedobjectscreateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.migrationversion.md b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.migrationversion.md index 33432b1138d918..92b858f4464129 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.migrationversion.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.migrationversion.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [migrationVersion](./kibana-plugin-server.savedobjectscreateoptions.migrationversion.md) - -## SavedObjectsCreateOptions.migrationVersion property - -Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. - -Signature: - -```typescript -migrationVersion?: SavedObjectsMigrationVersion; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [migrationVersion](./kibana-plugin-server.savedobjectscreateoptions.migrationversion.md) + +## SavedObjectsCreateOptions.migrationVersion property + +Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. + +Signature: + +```typescript +migrationVersion?: SavedObjectsMigrationVersion; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.overwrite.md b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.overwrite.md index cb58e87795300a..039bf0be854597 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.overwrite.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.overwrite.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [overwrite](./kibana-plugin-server.savedobjectscreateoptions.overwrite.md) - -## SavedObjectsCreateOptions.overwrite property - -Overwrite existing documents (defaults to false) - -Signature: - -```typescript -overwrite?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [overwrite](./kibana-plugin-server.savedobjectscreateoptions.overwrite.md) + +## SavedObjectsCreateOptions.overwrite property + +Overwrite existing documents (defaults to false) + +Signature: + +```typescript +overwrite?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.references.md b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.references.md index bdf88b021c06c9..d168cd4a1adc95 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.references.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.references.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [references](./kibana-plugin-server.savedobjectscreateoptions.references.md) - -## SavedObjectsCreateOptions.references property - -Signature: - -```typescript -references?: SavedObjectReference[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [references](./kibana-plugin-server.savedobjectscreateoptions.references.md) + +## SavedObjectsCreateOptions.references property + +Signature: + +```typescript +references?: SavedObjectReference[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.refresh.md index 785874a12c8c45..2f67dff5d4a5d1 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.refresh.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.refresh.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [refresh](./kibana-plugin-server.savedobjectscreateoptions.refresh.md) - -## SavedObjectsCreateOptions.refresh property - -The Elasticsearch Refresh setting for this operation - -Signature: - -```typescript -refresh?: MutatingOperationRefreshSetting; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [refresh](./kibana-plugin-server.savedobjectscreateoptions.refresh.md) + +## SavedObjectsCreateOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md index df4ce1b4b84286..743bf8fee33ccb 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md) - -## SavedObjectsDeleteByNamespaceOptions interface - - -Signature: - -```typescript -export interface SavedObjectsDeleteByNamespaceOptions extends SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [refresh](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md) + +## SavedObjectsDeleteByNamespaceOptions interface + + +Signature: + +```typescript +export interface SavedObjectsDeleteByNamespaceOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [refresh](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsdeletebynamespaceoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectsdeletebynamespaceoptions.refresh.md index 2332520ac388fc..0c314b7b094dce 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsdeletebynamespaceoptions.refresh.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsdeletebynamespaceoptions.refresh.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md) > [refresh](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.refresh.md) - -## SavedObjectsDeleteByNamespaceOptions.refresh property - -The Elasticsearch Refresh setting for this operation - -Signature: - -```typescript -refresh?: MutatingOperationRefreshSetting; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.md) > [refresh](./kibana-plugin-server.savedobjectsdeletebynamespaceoptions.refresh.md) + +## SavedObjectsDeleteByNamespaceOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.md index 2c641ba5cc8d8e..c4c2e9f64a7be9 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) - -## SavedObjectsDeleteOptions interface - - -Signature: - -```typescript -export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [refresh](./kibana-plugin-server.savedobjectsdeleteoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) + +## SavedObjectsDeleteOptions interface + + +Signature: + +```typescript +export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [refresh](./kibana-plugin-server.savedobjectsdeleteoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.refresh.md index 782c52956f2976..476d982bed950f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.refresh.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.refresh.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) > [refresh](./kibana-plugin-server.savedobjectsdeleteoptions.refresh.md) - -## SavedObjectsDeleteOptions.refresh property - -The Elasticsearch Refresh setting for this operation - -Signature: - -```typescript -refresh?: MutatingOperationRefreshSetting; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) > [refresh](./kibana-plugin-server.savedobjectsdeleteoptions.refresh.md) + +## SavedObjectsDeleteOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createbadrequesterror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createbadrequesterror.md index 03ad9d29c1cc3a..38e133b40c8525 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createbadrequesterror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createbadrequesterror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createBadRequestError](./kibana-plugin-server.savedobjectserrorhelpers.createbadrequesterror.md) - -## SavedObjectsErrorHelpers.createBadRequestError() method - -Signature: - -```typescript -static createBadRequestError(reason?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| reason | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createBadRequestError](./kibana-plugin-server.savedobjectserrorhelpers.createbadrequesterror.md) + +## SavedObjectsErrorHelpers.createBadRequestError() method + +Signature: + +```typescript +static createBadRequestError(reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createesautocreateindexerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createesautocreateindexerror.md index 62cec4bfa38fc1..6a1d86dc6cd141 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createesautocreateindexerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createesautocreateindexerror.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createEsAutoCreateIndexError](./kibana-plugin-server.savedobjectserrorhelpers.createesautocreateindexerror.md) - -## SavedObjectsErrorHelpers.createEsAutoCreateIndexError() method - -Signature: - -```typescript -static createEsAutoCreateIndexError(): DecoratedError; -``` -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createEsAutoCreateIndexError](./kibana-plugin-server.savedobjectserrorhelpers.createesautocreateindexerror.md) + +## SavedObjectsErrorHelpers.createEsAutoCreateIndexError() method + +Signature: + +```typescript +static createEsAutoCreateIndexError(): DecoratedError; +``` +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.creategenericnotfounderror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.creategenericnotfounderror.md index 1abe1cf0067ec6..e608939af45cb4 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.creategenericnotfounderror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.creategenericnotfounderror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createGenericNotFoundError](./kibana-plugin-server.savedobjectserrorhelpers.creategenericnotfounderror.md) - -## SavedObjectsErrorHelpers.createGenericNotFoundError() method - -Signature: - -```typescript -static createGenericNotFoundError(type?: string | null, id?: string | null): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | null | | -| id | string | null | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createGenericNotFoundError](./kibana-plugin-server.savedobjectserrorhelpers.creategenericnotfounderror.md) + +## SavedObjectsErrorHelpers.createGenericNotFoundError() method + +Signature: + +```typescript +static createGenericNotFoundError(type?: string | null, id?: string | null): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | null | | +| id | string | null | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createinvalidversionerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createinvalidversionerror.md index fc65c93fde9466..15a25d90d8d82e 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createinvalidversionerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createinvalidversionerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createInvalidVersionError](./kibana-plugin-server.savedobjectserrorhelpers.createinvalidversionerror.md) - -## SavedObjectsErrorHelpers.createInvalidVersionError() method - -Signature: - -```typescript -static createInvalidVersionError(versionInput?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| versionInput | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createInvalidVersionError](./kibana-plugin-server.savedobjectserrorhelpers.createinvalidversionerror.md) + +## SavedObjectsErrorHelpers.createInvalidVersionError() method + +Signature: + +```typescript +static createInvalidVersionError(versionInput?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| versionInput | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createunsupportedtypeerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createunsupportedtypeerror.md index 1b22f86df67964..51d48c7083f2ec 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createunsupportedtypeerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.createunsupportedtypeerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createUnsupportedTypeError](./kibana-plugin-server.savedobjectserrorhelpers.createunsupportedtypeerror.md) - -## SavedObjectsErrorHelpers.createUnsupportedTypeError() method - -Signature: - -```typescript -static createUnsupportedTypeError(type: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [createUnsupportedTypeError](./kibana-plugin-server.savedobjectserrorhelpers.createunsupportedtypeerror.md) + +## SavedObjectsErrorHelpers.createUnsupportedTypeError() method + +Signature: + +```typescript +static createUnsupportedTypeError(type: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoratebadrequesterror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoratebadrequesterror.md index deccee473eaa4a..07da6c59591ec3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoratebadrequesterror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoratebadrequesterror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateBadRequestError](./kibana-plugin-server.savedobjectserrorhelpers.decoratebadrequesterror.md) - -## SavedObjectsErrorHelpers.decorateBadRequestError() method - -Signature: - -```typescript -static decorateBadRequestError(error: Error, reason?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | | -| reason | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateBadRequestError](./kibana-plugin-server.savedobjectserrorhelpers.decoratebadrequesterror.md) + +## SavedObjectsErrorHelpers.decorateBadRequestError() method + +Signature: + +```typescript +static decorateBadRequestError(error: Error, reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateconflicterror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateconflicterror.md index ac999903d3a211..10e974c22d9abc 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateconflicterror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateconflicterror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateConflictError](./kibana-plugin-server.savedobjectserrorhelpers.decorateconflicterror.md) - -## SavedObjectsErrorHelpers.decorateConflictError() method - -Signature: - -```typescript -static decorateConflictError(error: Error, reason?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | | -| reason | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateConflictError](./kibana-plugin-server.savedobjectserrorhelpers.decorateconflicterror.md) + +## SavedObjectsErrorHelpers.decorateConflictError() method + +Signature: + +```typescript +static decorateConflictError(error: Error, reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateesunavailableerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateesunavailableerror.md index 54a420913390be..8d0f498f5eb79f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateesunavailableerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateesunavailableerror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateEsUnavailableError](./kibana-plugin-server.savedobjectserrorhelpers.decorateesunavailableerror.md) - -## SavedObjectsErrorHelpers.decorateEsUnavailableError() method - -Signature: - -```typescript -static decorateEsUnavailableError(error: Error, reason?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | | -| reason | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateEsUnavailableError](./kibana-plugin-server.savedobjectserrorhelpers.decorateesunavailableerror.md) + +## SavedObjectsErrorHelpers.decorateEsUnavailableError() method + +Signature: + +```typescript +static decorateEsUnavailableError(error: Error, reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateforbiddenerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateforbiddenerror.md index c5130dfb124006..b95c207b691c58 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateforbiddenerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorateforbiddenerror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateForbiddenError](./kibana-plugin-server.savedobjectserrorhelpers.decorateforbiddenerror.md) - -## SavedObjectsErrorHelpers.decorateForbiddenError() method - -Signature: - -```typescript -static decorateForbiddenError(error: Error, reason?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | | -| reason | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateForbiddenError](./kibana-plugin-server.savedobjectserrorhelpers.decorateforbiddenerror.md) + +## SavedObjectsErrorHelpers.decorateForbiddenError() method + +Signature: + +```typescript +static decorateForbiddenError(error: Error, reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorategeneralerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorategeneralerror.md index 6086df058483f1..c08417ada54361 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorategeneralerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decorategeneralerror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateGeneralError](./kibana-plugin-server.savedobjectserrorhelpers.decorategeneralerror.md) - -## SavedObjectsErrorHelpers.decorateGeneralError() method - -Signature: - -```typescript -static decorateGeneralError(error: Error, reason?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | | -| reason | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateGeneralError](./kibana-plugin-server.savedobjectserrorhelpers.decorategeneralerror.md) + +## SavedObjectsErrorHelpers.decorateGeneralError() method + +Signature: + +```typescript +static decorateGeneralError(error: Error, reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoratenotauthorizederror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoratenotauthorizederror.md index 3977b58c945bc2..db412b869aeae7 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoratenotauthorizederror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoratenotauthorizederror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateNotAuthorizedError](./kibana-plugin-server.savedobjectserrorhelpers.decoratenotauthorizederror.md) - -## SavedObjectsErrorHelpers.decorateNotAuthorizedError() method - -Signature: - -```typescript -static decorateNotAuthorizedError(error: Error, reason?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | | -| reason | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateNotAuthorizedError](./kibana-plugin-server.savedobjectserrorhelpers.decoratenotauthorizederror.md) + +## SavedObjectsErrorHelpers.decorateNotAuthorizedError() method + +Signature: + +```typescript +static decorateNotAuthorizedError(error: Error, reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoraterequestentitytoolargeerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoraterequestentitytoolargeerror.md index 58cba64fd31398..e426192afe4ee2 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoraterequestentitytoolargeerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.decoraterequestentitytoolargeerror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateRequestEntityTooLargeError](./kibana-plugin-server.savedobjectserrorhelpers.decoraterequestentitytoolargeerror.md) - -## SavedObjectsErrorHelpers.decorateRequestEntityTooLargeError() method - -Signature: - -```typescript -static decorateRequestEntityTooLargeError(error: Error, reason?: string): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | | -| reason | string | | - -Returns: - -`DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [decorateRequestEntityTooLargeError](./kibana-plugin-server.savedobjectserrorhelpers.decoraterequestentitytoolargeerror.md) + +## SavedObjectsErrorHelpers.decorateRequestEntityTooLargeError() method + +Signature: + +```typescript +static decorateRequestEntityTooLargeError(error: Error, reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isbadrequesterror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isbadrequesterror.md index 79805e371884d9..b66faa0b794714 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isbadrequesterror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isbadrequesterror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isBadRequestError](./kibana-plugin-server.savedobjectserrorhelpers.isbadrequesterror.md) - -## SavedObjectsErrorHelpers.isBadRequestError() method - -Signature: - -```typescript -static isBadRequestError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isBadRequestError](./kibana-plugin-server.savedobjectserrorhelpers.isbadrequesterror.md) + +## SavedObjectsErrorHelpers.isBadRequestError() method + +Signature: + +```typescript +static isBadRequestError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isconflicterror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isconflicterror.md index 99e636bf006adf..e8652190e59b90 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isconflicterror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isconflicterror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isConflictError](./kibana-plugin-server.savedobjectserrorhelpers.isconflicterror.md) - -## SavedObjectsErrorHelpers.isConflictError() method - -Signature: - -```typescript -static isConflictError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isConflictError](./kibana-plugin-server.savedobjectserrorhelpers.isconflicterror.md) + +## SavedObjectsErrorHelpers.isConflictError() method + +Signature: + +```typescript +static isConflictError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isesautocreateindexerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isesautocreateindexerror.md index 37b845d3362038..df6129390b0c76 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isesautocreateindexerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isesautocreateindexerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isEsAutoCreateIndexError](./kibana-plugin-server.savedobjectserrorhelpers.isesautocreateindexerror.md) - -## SavedObjectsErrorHelpers.isEsAutoCreateIndexError() method - -Signature: - -```typescript -static isEsAutoCreateIndexError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isEsAutoCreateIndexError](./kibana-plugin-server.savedobjectserrorhelpers.isesautocreateindexerror.md) + +## SavedObjectsErrorHelpers.isEsAutoCreateIndexError() method + +Signature: + +```typescript +static isEsAutoCreateIndexError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isesunavailableerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isesunavailableerror.md index 0672c92a0c80f7..44b8afa6c649a3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isesunavailableerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isesunavailableerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isEsUnavailableError](./kibana-plugin-server.savedobjectserrorhelpers.isesunavailableerror.md) - -## SavedObjectsErrorHelpers.isEsUnavailableError() method - -Signature: - -```typescript -static isEsUnavailableError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isEsUnavailableError](./kibana-plugin-server.savedobjectserrorhelpers.isesunavailableerror.md) + +## SavedObjectsErrorHelpers.isEsUnavailableError() method + +Signature: + +```typescript +static isEsUnavailableError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isforbiddenerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isforbiddenerror.md index 6350de9b6403c3..7955f5f5dbf462 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isforbiddenerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isforbiddenerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isForbiddenError](./kibana-plugin-server.savedobjectserrorhelpers.isforbiddenerror.md) - -## SavedObjectsErrorHelpers.isForbiddenError() method - -Signature: - -```typescript -static isForbiddenError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isForbiddenError](./kibana-plugin-server.savedobjectserrorhelpers.isforbiddenerror.md) + +## SavedObjectsErrorHelpers.isForbiddenError() method + +Signature: + +```typescript +static isForbiddenError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isinvalidversionerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isinvalidversionerror.md index c91056b92e456f..7218e50d5f1571 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isinvalidversionerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isinvalidversionerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isInvalidVersionError](./kibana-plugin-server.savedobjectserrorhelpers.isinvalidversionerror.md) - -## SavedObjectsErrorHelpers.isInvalidVersionError() method - -Signature: - -```typescript -static isInvalidVersionError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isInvalidVersionError](./kibana-plugin-server.savedobjectserrorhelpers.isinvalidversionerror.md) + +## SavedObjectsErrorHelpers.isInvalidVersionError() method + +Signature: + +```typescript +static isInvalidVersionError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isnotauthorizederror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isnotauthorizederror.md index 6cedc87f52db98..fd28812b965278 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isnotauthorizederror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isnotauthorizederror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isNotAuthorizedError](./kibana-plugin-server.savedobjectserrorhelpers.isnotauthorizederror.md) - -## SavedObjectsErrorHelpers.isNotAuthorizedError() method - -Signature: - -```typescript -static isNotAuthorizedError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isNotAuthorizedError](./kibana-plugin-server.savedobjectserrorhelpers.isnotauthorizederror.md) + +## SavedObjectsErrorHelpers.isNotAuthorizedError() method + +Signature: + +```typescript +static isNotAuthorizedError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isnotfounderror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isnotfounderror.md index 125730454e4d08..3a1c8b3f3d3605 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isnotfounderror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isnotfounderror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isNotFoundError](./kibana-plugin-server.savedobjectserrorhelpers.isnotfounderror.md) - -## SavedObjectsErrorHelpers.isNotFoundError() method - -Signature: - -```typescript -static isNotFoundError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isNotFoundError](./kibana-plugin-server.savedobjectserrorhelpers.isnotfounderror.md) + +## SavedObjectsErrorHelpers.isNotFoundError() method + +Signature: + +```typescript +static isNotFoundError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isrequestentitytoolargeerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isrequestentitytoolargeerror.md index 63a8862a6d84ce..6b23d082455741 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isrequestentitytoolargeerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.isrequestentitytoolargeerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isRequestEntityTooLargeError](./kibana-plugin-server.savedobjectserrorhelpers.isrequestentitytoolargeerror.md) - -## SavedObjectsErrorHelpers.isRequestEntityTooLargeError() method - -Signature: - -```typescript -static isRequestEntityTooLargeError(error: Error | DecoratedError): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | Error | DecoratedError | | - -Returns: - -`boolean` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isRequestEntityTooLargeError](./kibana-plugin-server.savedobjectserrorhelpers.isrequestentitytoolargeerror.md) + +## SavedObjectsErrorHelpers.isRequestEntityTooLargeError() method + +Signature: + +```typescript +static isRequestEntityTooLargeError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.issavedobjectsclienterror.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.issavedobjectsclienterror.md index 8e22e2df805f8f..3e79e41dba53fd 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.issavedobjectsclienterror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.issavedobjectsclienterror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isSavedObjectsClientError](./kibana-plugin-server.savedobjectserrorhelpers.issavedobjectsclienterror.md) - -## SavedObjectsErrorHelpers.isSavedObjectsClientError() method - -Signature: - -```typescript -static isSavedObjectsClientError(error: any): error is DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | any | | - -Returns: - -`error is DecoratedError` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) > [isSavedObjectsClientError](./kibana-plugin-server.savedobjectserrorhelpers.issavedobjectsclienterror.md) + +## SavedObjectsErrorHelpers.isSavedObjectsClientError() method + +Signature: + +```typescript +static isSavedObjectsClientError(error: any): error is DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | any | | + +Returns: + +`error is DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.md b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.md index ffa4b06028c2a3..d7c39281fca33c 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectserrorhelpers.md @@ -1,40 +1,40 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) - -## SavedObjectsErrorHelpers class - - -Signature: - -```typescript -export declare class SavedObjectsErrorHelpers -``` - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [createBadRequestError(reason)](./kibana-plugin-server.savedobjectserrorhelpers.createbadrequesterror.md) | static | | -| [createEsAutoCreateIndexError()](./kibana-plugin-server.savedobjectserrorhelpers.createesautocreateindexerror.md) | static | | -| [createGenericNotFoundError(type, id)](./kibana-plugin-server.savedobjectserrorhelpers.creategenericnotfounderror.md) | static | | -| [createInvalidVersionError(versionInput)](./kibana-plugin-server.savedobjectserrorhelpers.createinvalidversionerror.md) | static | | -| [createUnsupportedTypeError(type)](./kibana-plugin-server.savedobjectserrorhelpers.createunsupportedtypeerror.md) | static | | -| [decorateBadRequestError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decoratebadrequesterror.md) | static | | -| [decorateConflictError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decorateconflicterror.md) | static | | -| [decorateEsUnavailableError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decorateesunavailableerror.md) | static | | -| [decorateForbiddenError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decorateforbiddenerror.md) | static | | -| [decorateGeneralError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decorategeneralerror.md) | static | | -| [decorateNotAuthorizedError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decoratenotauthorizederror.md) | static | | -| [decorateRequestEntityTooLargeError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decoraterequestentitytoolargeerror.md) | static | | -| [isBadRequestError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isbadrequesterror.md) | static | | -| [isConflictError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isconflicterror.md) | static | | -| [isEsAutoCreateIndexError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isesautocreateindexerror.md) | static | | -| [isEsUnavailableError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isesunavailableerror.md) | static | | -| [isForbiddenError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isforbiddenerror.md) | static | | -| [isInvalidVersionError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isinvalidversionerror.md) | static | | -| [isNotAuthorizedError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isnotauthorizederror.md) | static | | -| [isNotFoundError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isnotfounderror.md) | static | | -| [isRequestEntityTooLargeError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isrequestentitytoolargeerror.md) | static | | -| [isSavedObjectsClientError(error)](./kibana-plugin-server.savedobjectserrorhelpers.issavedobjectsclienterror.md) | static | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) + +## SavedObjectsErrorHelpers class + + +Signature: + +```typescript +export declare class SavedObjectsErrorHelpers +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [createBadRequestError(reason)](./kibana-plugin-server.savedobjectserrorhelpers.createbadrequesterror.md) | static | | +| [createEsAutoCreateIndexError()](./kibana-plugin-server.savedobjectserrorhelpers.createesautocreateindexerror.md) | static | | +| [createGenericNotFoundError(type, id)](./kibana-plugin-server.savedobjectserrorhelpers.creategenericnotfounderror.md) | static | | +| [createInvalidVersionError(versionInput)](./kibana-plugin-server.savedobjectserrorhelpers.createinvalidversionerror.md) | static | | +| [createUnsupportedTypeError(type)](./kibana-plugin-server.savedobjectserrorhelpers.createunsupportedtypeerror.md) | static | | +| [decorateBadRequestError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decoratebadrequesterror.md) | static | | +| [decorateConflictError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decorateconflicterror.md) | static | | +| [decorateEsUnavailableError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decorateesunavailableerror.md) | static | | +| [decorateForbiddenError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decorateforbiddenerror.md) | static | | +| [decorateGeneralError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decorategeneralerror.md) | static | | +| [decorateNotAuthorizedError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decoratenotauthorizederror.md) | static | | +| [decorateRequestEntityTooLargeError(error, reason)](./kibana-plugin-server.savedobjectserrorhelpers.decoraterequestentitytoolargeerror.md) | static | | +| [isBadRequestError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isbadrequesterror.md) | static | | +| [isConflictError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isconflicterror.md) | static | | +| [isEsAutoCreateIndexError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isesautocreateindexerror.md) | static | | +| [isEsUnavailableError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isesunavailableerror.md) | static | | +| [isForbiddenError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isforbiddenerror.md) | static | | +| [isInvalidVersionError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isinvalidversionerror.md) | static | | +| [isNotAuthorizedError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isnotauthorizederror.md) | static | | +| [isNotFoundError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isnotfounderror.md) | static | | +| [isRequestEntityTooLargeError(error)](./kibana-plugin-server.savedobjectserrorhelpers.isrequestentitytoolargeerror.md) | static | | +| [isSavedObjectsClientError(error)](./kibana-plugin-server.savedobjectserrorhelpers.issavedobjectsclienterror.md) | static | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.excludeexportdetails.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.excludeexportdetails.md index bffc8096898348..479fa0221e256f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.excludeexportdetails.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.excludeexportdetails.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [excludeExportDetails](./kibana-plugin-server.savedobjectsexportoptions.excludeexportdetails.md) - -## SavedObjectsExportOptions.excludeExportDetails property - -flag to not append [export details](./kibana-plugin-server.savedobjectsexportresultdetails.md) to the end of the export stream. - -Signature: - -```typescript -excludeExportDetails?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [excludeExportDetails](./kibana-plugin-server.savedobjectsexportoptions.excludeexportdetails.md) + +## SavedObjectsExportOptions.excludeExportDetails property + +flag to not append [export details](./kibana-plugin-server.savedobjectsexportresultdetails.md) to the end of the export stream. + +Signature: + +```typescript +excludeExportDetails?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.exportsizelimit.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.exportsizelimit.md index 36eba992739973..91a6e622969243 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.exportsizelimit.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.exportsizelimit.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [exportSizeLimit](./kibana-plugin-server.savedobjectsexportoptions.exportsizelimit.md) - -## SavedObjectsExportOptions.exportSizeLimit property - -the maximum number of objects to export. - -Signature: - -```typescript -exportSizeLimit: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [exportSizeLimit](./kibana-plugin-server.savedobjectsexportoptions.exportsizelimit.md) + +## SavedObjectsExportOptions.exportSizeLimit property + +the maximum number of objects to export. + +Signature: + +```typescript +exportSizeLimit: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.includereferencesdeep.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.includereferencesdeep.md index 0cd7688e04184d..44ac2761a19d22 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.includereferencesdeep.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.includereferencesdeep.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [includeReferencesDeep](./kibana-plugin-server.savedobjectsexportoptions.includereferencesdeep.md) - -## SavedObjectsExportOptions.includeReferencesDeep property - -flag to also include all related saved objects in the export stream. - -Signature: - -```typescript -includeReferencesDeep?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [includeReferencesDeep](./kibana-plugin-server.savedobjectsexportoptions.includereferencesdeep.md) + +## SavedObjectsExportOptions.includeReferencesDeep property + +flag to also include all related saved objects in the export stream. + +Signature: + +```typescript +includeReferencesDeep?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.md index d312d7d4b34997..2715d58ab30d72 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) - -## SavedObjectsExportOptions interface - -Options controlling the export operation. - -Signature: - -```typescript -export interface SavedObjectsExportOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [excludeExportDetails](./kibana-plugin-server.savedobjectsexportoptions.excludeexportdetails.md) | boolean | flag to not append [export details](./kibana-plugin-server.savedobjectsexportresultdetails.md) to the end of the export stream. | -| [exportSizeLimit](./kibana-plugin-server.savedobjectsexportoptions.exportsizelimit.md) | number | the maximum number of objects to export. | -| [includeReferencesDeep](./kibana-plugin-server.savedobjectsexportoptions.includereferencesdeep.md) | boolean | flag to also include all related saved objects in the export stream. | -| [namespace](./kibana-plugin-server.savedobjectsexportoptions.namespace.md) | string | optional namespace to override the namespace used by the savedObjectsClient. | -| [objects](./kibana-plugin-server.savedobjectsexportoptions.objects.md) | Array<{
id: string;
type: string;
}> | optional array of objects to export. | -| [savedObjectsClient](./kibana-plugin-server.savedobjectsexportoptions.savedobjectsclient.md) | SavedObjectsClientContract | an instance of the SavedObjectsClient. | -| [search](./kibana-plugin-server.savedobjectsexportoptions.search.md) | string | optional query string to filter exported objects. | -| [types](./kibana-plugin-server.savedobjectsexportoptions.types.md) | string[] | optional array of saved object types. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) + +## SavedObjectsExportOptions interface + +Options controlling the export operation. + +Signature: + +```typescript +export interface SavedObjectsExportOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [excludeExportDetails](./kibana-plugin-server.savedobjectsexportoptions.excludeexportdetails.md) | boolean | flag to not append [export details](./kibana-plugin-server.savedobjectsexportresultdetails.md) to the end of the export stream. | +| [exportSizeLimit](./kibana-plugin-server.savedobjectsexportoptions.exportsizelimit.md) | number | the maximum number of objects to export. | +| [includeReferencesDeep](./kibana-plugin-server.savedobjectsexportoptions.includereferencesdeep.md) | boolean | flag to also include all related saved objects in the export stream. | +| [namespace](./kibana-plugin-server.savedobjectsexportoptions.namespace.md) | string | optional namespace to override the namespace used by the savedObjectsClient. | +| [objects](./kibana-plugin-server.savedobjectsexportoptions.objects.md) | Array<{
id: string;
type: string;
}> | optional array of objects to export. | +| [savedObjectsClient](./kibana-plugin-server.savedobjectsexportoptions.savedobjectsclient.md) | SavedObjectsClientContract | an instance of the SavedObjectsClient. | +| [search](./kibana-plugin-server.savedobjectsexportoptions.search.md) | string | optional query string to filter exported objects. | +| [types](./kibana-plugin-server.savedobjectsexportoptions.types.md) | string[] | optional array of saved object types. | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.namespace.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.namespace.md index 1a28cc92e6e7e1..6dde67d8cac0d9 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.namespace.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.namespace.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [namespace](./kibana-plugin-server.savedobjectsexportoptions.namespace.md) - -## SavedObjectsExportOptions.namespace property - -optional namespace to override the namespace used by the savedObjectsClient. - -Signature: - -```typescript -namespace?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [namespace](./kibana-plugin-server.savedobjectsexportoptions.namespace.md) + +## SavedObjectsExportOptions.namespace property + +optional namespace to override the namespace used by the savedObjectsClient. + +Signature: + +```typescript +namespace?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.objects.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.objects.md index cd32f66c0f81e3..ab93ecc06a1375 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.objects.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.objects.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [objects](./kibana-plugin-server.savedobjectsexportoptions.objects.md) - -## SavedObjectsExportOptions.objects property - -optional array of objects to export. - -Signature: - -```typescript -objects?: Array<{ - id: string; - type: string; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [objects](./kibana-plugin-server.savedobjectsexportoptions.objects.md) + +## SavedObjectsExportOptions.objects property + +optional array of objects to export. + +Signature: + +```typescript +objects?: Array<{ + id: string; + type: string; + }>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.savedobjectsclient.md index 1e0dd6c6f164f7..851f0025b6c1bc 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.savedobjectsclient.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.savedobjectsclient.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [savedObjectsClient](./kibana-plugin-server.savedobjectsexportoptions.savedobjectsclient.md) - -## SavedObjectsExportOptions.savedObjectsClient property - -an instance of the SavedObjectsClient. - -Signature: - -```typescript -savedObjectsClient: SavedObjectsClientContract; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [savedObjectsClient](./kibana-plugin-server.savedobjectsexportoptions.savedobjectsclient.md) + +## SavedObjectsExportOptions.savedObjectsClient property + +an instance of the SavedObjectsClient. + +Signature: + +```typescript +savedObjectsClient: SavedObjectsClientContract; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.search.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.search.md index 5e44486ee65e0d..a78fccc3f0b66e 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.search.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.search.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [search](./kibana-plugin-server.savedobjectsexportoptions.search.md) - -## SavedObjectsExportOptions.search property - -optional query string to filter exported objects. - -Signature: - -```typescript -search?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [search](./kibana-plugin-server.savedobjectsexportoptions.search.md) + +## SavedObjectsExportOptions.search property + +optional query string to filter exported objects. + +Signature: + +```typescript +search?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.types.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.types.md index cf1eb676f7ab82..bf57bc253c52cf 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.types.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportoptions.types.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [types](./kibana-plugin-server.savedobjectsexportoptions.types.md) - -## SavedObjectsExportOptions.types property - -optional array of saved object types. - -Signature: - -```typescript -types?: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) > [types](./kibana-plugin-server.savedobjectsexportoptions.types.md) + +## SavedObjectsExportOptions.types property + +optional array of saved object types. + +Signature: + +```typescript +types?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.exportedcount.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.exportedcount.md index c2e588dd3c1210..9f67dea572abfa 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.exportedcount.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.exportedcount.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) > [exportedCount](./kibana-plugin-server.savedobjectsexportresultdetails.exportedcount.md) - -## SavedObjectsExportResultDetails.exportedCount property - -number of successfully exported objects - -Signature: - -```typescript -exportedCount: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) > [exportedCount](./kibana-plugin-server.savedobjectsexportresultdetails.exportedcount.md) + +## SavedObjectsExportResultDetails.exportedCount property + +number of successfully exported objects + +Signature: + +```typescript +exportedCount: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.md index fb3af350d21eaf..475918d97f7ace 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) - -## SavedObjectsExportResultDetails interface - -Structure of the export result details entry - -Signature: - -```typescript -export interface SavedObjectsExportResultDetails -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [exportedCount](./kibana-plugin-server.savedobjectsexportresultdetails.exportedcount.md) | number | number of successfully exported objects | -| [missingRefCount](./kibana-plugin-server.savedobjectsexportresultdetails.missingrefcount.md) | number | number of missing references | -| [missingReferences](./kibana-plugin-server.savedobjectsexportresultdetails.missingreferences.md) | Array<{
id: string;
type: string;
}> | missing references details | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) + +## SavedObjectsExportResultDetails interface + +Structure of the export result details entry + +Signature: + +```typescript +export interface SavedObjectsExportResultDetails +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [exportedCount](./kibana-plugin-server.savedobjectsexportresultdetails.exportedcount.md) | number | number of successfully exported objects | +| [missingRefCount](./kibana-plugin-server.savedobjectsexportresultdetails.missingrefcount.md) | number | number of missing references | +| [missingReferences](./kibana-plugin-server.savedobjectsexportresultdetails.missingreferences.md) | Array<{
id: string;
type: string;
}> | missing references details | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.missingrefcount.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.missingrefcount.md index 5b51199ea47802..bc1b359aeda80e 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.missingrefcount.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.missingrefcount.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) > [missingRefCount](./kibana-plugin-server.savedobjectsexportresultdetails.missingrefcount.md) - -## SavedObjectsExportResultDetails.missingRefCount property - -number of missing references - -Signature: - -```typescript -missingRefCount: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) > [missingRefCount](./kibana-plugin-server.savedobjectsexportresultdetails.missingrefcount.md) + +## SavedObjectsExportResultDetails.missingRefCount property + +number of missing references + +Signature: + +```typescript +missingRefCount: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.missingreferences.md b/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.missingreferences.md index 1602bfb6e6cb63..024f625b527e81 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.missingreferences.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsexportresultdetails.missingreferences.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) > [missingReferences](./kibana-plugin-server.savedobjectsexportresultdetails.missingreferences.md) - -## SavedObjectsExportResultDetails.missingReferences property - -missing references details - -Signature: - -```typescript -missingReferences: Array<{ - id: string; - type: string; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) > [missingReferences](./kibana-plugin-server.savedobjectsexportresultdetails.missingreferences.md) + +## SavedObjectsExportResultDetails.missingReferences property + +missing references details + +Signature: + +```typescript +missingReferences: Array<{ + id: string; + type: string; + }>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md index c3b7f35e351ff4..e4209bee3f8b6c 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [defaultSearchOperator](./kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md) - -## SavedObjectsFindOptions.defaultSearchOperator property - -Signature: - -```typescript -defaultSearchOperator?: 'AND' | 'OR'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [defaultSearchOperator](./kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md) + +## SavedObjectsFindOptions.defaultSearchOperator property + +Signature: + +```typescript +defaultSearchOperator?: 'AND' | 'OR'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.fields.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.fields.md index 394363abb5d4dd..b4777d45217e12 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.fields.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.fields.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [fields](./kibana-plugin-server.savedobjectsfindoptions.fields.md) - -## SavedObjectsFindOptions.fields property - -An array of fields to include in the results - -Signature: - -```typescript -fields?: string[]; -``` - -## Example - -SavedObjects.find({type: 'dashboard', fields: \['attributes.name', 'attributes.location'\]}) - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [fields](./kibana-plugin-server.savedobjectsfindoptions.fields.md) + +## SavedObjectsFindOptions.fields property + +An array of fields to include in the results + +Signature: + +```typescript +fields?: string[]; +``` + +## Example + +SavedObjects.find({type: 'dashboard', fields: \['attributes.name', 'attributes.location'\]}) + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.filter.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.filter.md index 308bebbeaf60b8..409fc337188dca 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.filter.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.filter.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [filter](./kibana-plugin-server.savedobjectsfindoptions.filter.md) - -## SavedObjectsFindOptions.filter property - -Signature: - -```typescript -filter?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [filter](./kibana-plugin-server.savedobjectsfindoptions.filter.md) + +## SavedObjectsFindOptions.filter property + +Signature: + +```typescript +filter?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.hasreference.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.hasreference.md index 01d20d898c1ef4..23f0bc712ca522 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.hasreference.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.hasreference.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [hasReference](./kibana-plugin-server.savedobjectsfindoptions.hasreference.md) - -## SavedObjectsFindOptions.hasReference property - -Signature: - -```typescript -hasReference?: { - type: string; - id: string; - }; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [hasReference](./kibana-plugin-server.savedobjectsfindoptions.hasreference.md) + +## SavedObjectsFindOptions.hasReference property + +Signature: + +```typescript +hasReference?: { + type: string; + id: string; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.md index dfd51d480db926..df1b916b0604b6 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.md @@ -1,29 +1,29 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) - -## SavedObjectsFindOptions interface - - -Signature: - -```typescript -export interface SavedObjectsFindOptions extends SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [defaultSearchOperator](./kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md) | 'AND' | 'OR' | | -| [fields](./kibana-plugin-server.savedobjectsfindoptions.fields.md) | string[] | An array of fields to include in the results | -| [filter](./kibana-plugin-server.savedobjectsfindoptions.filter.md) | string | | -| [hasReference](./kibana-plugin-server.savedobjectsfindoptions.hasreference.md) | {
type: string;
id: string;
} | | -| [page](./kibana-plugin-server.savedobjectsfindoptions.page.md) | number | | -| [perPage](./kibana-plugin-server.savedobjectsfindoptions.perpage.md) | number | | -| [search](./kibana-plugin-server.savedobjectsfindoptions.search.md) | string | Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String query argument for more information | -| [searchFields](./kibana-plugin-server.savedobjectsfindoptions.searchfields.md) | string[] | The fields to perform the parsed query against. See Elasticsearch Simple Query String fields argument for more information | -| [sortField](./kibana-plugin-server.savedobjectsfindoptions.sortfield.md) | string | | -| [sortOrder](./kibana-plugin-server.savedobjectsfindoptions.sortorder.md) | string | | -| [type](./kibana-plugin-server.savedobjectsfindoptions.type.md) | string | string[] | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) + +## SavedObjectsFindOptions interface + + +Signature: + +```typescript +export interface SavedObjectsFindOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [defaultSearchOperator](./kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md) | 'AND' | 'OR' | | +| [fields](./kibana-plugin-server.savedobjectsfindoptions.fields.md) | string[] | An array of fields to include in the results | +| [filter](./kibana-plugin-server.savedobjectsfindoptions.filter.md) | string | | +| [hasReference](./kibana-plugin-server.savedobjectsfindoptions.hasreference.md) | {
type: string;
id: string;
} | | +| [page](./kibana-plugin-server.savedobjectsfindoptions.page.md) | number | | +| [perPage](./kibana-plugin-server.savedobjectsfindoptions.perpage.md) | number | | +| [search](./kibana-plugin-server.savedobjectsfindoptions.search.md) | string | Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String query argument for more information | +| [searchFields](./kibana-plugin-server.savedobjectsfindoptions.searchfields.md) | string[] | The fields to perform the parsed query against. See Elasticsearch Simple Query String fields argument for more information | +| [sortField](./kibana-plugin-server.savedobjectsfindoptions.sortfield.md) | string | | +| [sortOrder](./kibana-plugin-server.savedobjectsfindoptions.sortorder.md) | string | | +| [type](./kibana-plugin-server.savedobjectsfindoptions.type.md) | string | string[] | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.page.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.page.md index ab6faaf6649eec..40a62f9b82da43 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.page.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.page.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [page](./kibana-plugin-server.savedobjectsfindoptions.page.md) - -## SavedObjectsFindOptions.page property - -Signature: - -```typescript -page?: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [page](./kibana-plugin-server.savedobjectsfindoptions.page.md) + +## SavedObjectsFindOptions.page property + +Signature: + +```typescript +page?: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.perpage.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.perpage.md index f775aa450b93a3..c53db2089630fc 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.perpage.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.perpage.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [perPage](./kibana-plugin-server.savedobjectsfindoptions.perpage.md) - -## SavedObjectsFindOptions.perPage property - -Signature: - -```typescript -perPage?: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [perPage](./kibana-plugin-server.savedobjectsfindoptions.perpage.md) + +## SavedObjectsFindOptions.perPage property + +Signature: + +```typescript +perPage?: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.search.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.search.md index a29dda1892918a..5807307a29ad03 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.search.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.search.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [search](./kibana-plugin-server.savedobjectsfindoptions.search.md) - -## SavedObjectsFindOptions.search property - -Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String `query` argument for more information - -Signature: - -```typescript -search?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [search](./kibana-plugin-server.savedobjectsfindoptions.search.md) + +## SavedObjectsFindOptions.search property + +Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String `query` argument for more information + +Signature: + +```typescript +search?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.searchfields.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.searchfields.md index 2505bac8aec498..5e42ebd4b1dc97 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.searchfields.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.searchfields.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [searchFields](./kibana-plugin-server.savedobjectsfindoptions.searchfields.md) - -## SavedObjectsFindOptions.searchFields property - -The fields to perform the parsed query against. See Elasticsearch Simple Query String `fields` argument for more information - -Signature: - -```typescript -searchFields?: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [searchFields](./kibana-plugin-server.savedobjectsfindoptions.searchfields.md) + +## SavedObjectsFindOptions.searchFields property + +The fields to perform the parsed query against. See Elasticsearch Simple Query String `fields` argument for more information + +Signature: + +```typescript +searchFields?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.sortfield.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.sortfield.md index 3ba2916c3b0682..a67fc786a80376 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.sortfield.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.sortfield.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [sortField](./kibana-plugin-server.savedobjectsfindoptions.sortfield.md) - -## SavedObjectsFindOptions.sortField property - -Signature: - -```typescript -sortField?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [sortField](./kibana-plugin-server.savedobjectsfindoptions.sortfield.md) + +## SavedObjectsFindOptions.sortField property + +Signature: + +```typescript +sortField?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.sortorder.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.sortorder.md index bae922313db34b..32475703199e67 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.sortorder.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.sortorder.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [sortOrder](./kibana-plugin-server.savedobjectsfindoptions.sortorder.md) - -## SavedObjectsFindOptions.sortOrder property - -Signature: - -```typescript -sortOrder?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [sortOrder](./kibana-plugin-server.savedobjectsfindoptions.sortorder.md) + +## SavedObjectsFindOptions.sortOrder property + +Signature: + +```typescript +sortOrder?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.type.md index 95bac5bbc5cb8c..325cb491b71ca3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [type](./kibana-plugin-server.savedobjectsfindoptions.type.md) - -## SavedObjectsFindOptions.type property - -Signature: - -```typescript -type: string | string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [type](./kibana-plugin-server.savedobjectsfindoptions.type.md) + +## SavedObjectsFindOptions.type property + +Signature: + +```typescript +type: string | string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.md index 23299e22d80041..efdc07cea88fdc 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) - -## SavedObjectsFindResponse interface - -Return type of the Saved Objects `find()` method. - -\*Note\*: this type is different between the Public and Server Saved Objects clients. - -Signature: - -```typescript -export interface SavedObjectsFindResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [page](./kibana-plugin-server.savedobjectsfindresponse.page.md) | number | | -| [per\_page](./kibana-plugin-server.savedobjectsfindresponse.per_page.md) | number | | -| [saved\_objects](./kibana-plugin-server.savedobjectsfindresponse.saved_objects.md) | Array<SavedObject<T>> | | -| [total](./kibana-plugin-server.savedobjectsfindresponse.total.md) | number | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) + +## SavedObjectsFindResponse interface + +Return type of the Saved Objects `find()` method. + +\*Note\*: this type is different between the Public and Server Saved Objects clients. + +Signature: + +```typescript +export interface SavedObjectsFindResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [page](./kibana-plugin-server.savedobjectsfindresponse.page.md) | number | | +| [per\_page](./kibana-plugin-server.savedobjectsfindresponse.per_page.md) | number | | +| [saved\_objects](./kibana-plugin-server.savedobjectsfindresponse.saved_objects.md) | Array<SavedObject<T>> | | +| [total](./kibana-plugin-server.savedobjectsfindresponse.total.md) | number | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.page.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.page.md index 82cd16cd7b48a5..f6327563e902b6 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.page.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.page.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) > [page](./kibana-plugin-server.savedobjectsfindresponse.page.md) - -## SavedObjectsFindResponse.page property - -Signature: - -```typescript -page: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) > [page](./kibana-plugin-server.savedobjectsfindresponse.page.md) + +## SavedObjectsFindResponse.page property + +Signature: + +```typescript +page: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.per_page.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.per_page.md index d93b3024883824..d60690dcbc793d 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.per_page.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.per_page.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) > [per\_page](./kibana-plugin-server.savedobjectsfindresponse.per_page.md) - -## SavedObjectsFindResponse.per\_page property - -Signature: - -```typescript -per_page: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) > [per\_page](./kibana-plugin-server.savedobjectsfindresponse.per_page.md) + +## SavedObjectsFindResponse.per\_page property + +Signature: + +```typescript +per_page: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.saved_objects.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.saved_objects.md index 9e4247be4e02d3..aba05cd3824e00 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.saved_objects.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.saved_objects.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) > [saved\_objects](./kibana-plugin-server.savedobjectsfindresponse.saved_objects.md) - -## SavedObjectsFindResponse.saved\_objects property - -Signature: - -```typescript -saved_objects: Array>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) > [saved\_objects](./kibana-plugin-server.savedobjectsfindresponse.saved_objects.md) + +## SavedObjectsFindResponse.saved\_objects property + +Signature: + +```typescript +saved_objects: Array>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.total.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.total.md index 12e86e8d3a4e7a..84626f76d66add 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.total.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindresponse.total.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) > [total](./kibana-plugin-server.savedobjectsfindresponse.total.md) - -## SavedObjectsFindResponse.total property - -Signature: - -```typescript -total: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindResponse](./kibana-plugin-server.savedobjectsfindresponse.md) > [total](./kibana-plugin-server.savedobjectsfindresponse.total.md) + +## SavedObjectsFindResponse.total property + +Signature: + +```typescript +total: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportconflicterror.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportconflicterror.md index 485500da504a9e..ade9e50b05a0e6 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportconflicterror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportconflicterror.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportConflictError](./kibana-plugin-server.savedobjectsimportconflicterror.md) - -## SavedObjectsImportConflictError interface - -Represents a failure to import due to a conflict. - -Signature: - -```typescript -export interface SavedObjectsImportConflictError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [type](./kibana-plugin-server.savedobjectsimportconflicterror.type.md) | 'conflict' | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportConflictError](./kibana-plugin-server.savedobjectsimportconflicterror.md) + +## SavedObjectsImportConflictError interface + +Represents a failure to import due to a conflict. + +Signature: + +```typescript +export interface SavedObjectsImportConflictError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [type](./kibana-plugin-server.savedobjectsimportconflicterror.type.md) | 'conflict' | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportconflicterror.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportconflicterror.type.md index bd85de140674af..f37d4615b2248f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportconflicterror.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportconflicterror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportConflictError](./kibana-plugin-server.savedobjectsimportconflicterror.md) > [type](./kibana-plugin-server.savedobjectsimportconflicterror.type.md) - -## SavedObjectsImportConflictError.type property - -Signature: - -```typescript -type: 'conflict'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportConflictError](./kibana-plugin-server.savedobjectsimportconflicterror.md) > [type](./kibana-plugin-server.savedobjectsimportconflicterror.type.md) + +## SavedObjectsImportConflictError.type property + +Signature: + +```typescript +type: 'conflict'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.error.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.error.md index 0828ca9e01c34d..fd5c667c11a6fa 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.error.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.error.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) > [error](./kibana-plugin-server.savedobjectsimporterror.error.md) - -## SavedObjectsImportError.error property - -Signature: - -```typescript -error: SavedObjectsImportConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) > [error](./kibana-plugin-server.savedobjectsimporterror.error.md) + +## SavedObjectsImportError.error property + +Signature: + +```typescript +error: SavedObjectsImportConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.id.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.id.md index 0791d668f46261..791797b88cc63d 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) > [id](./kibana-plugin-server.savedobjectsimporterror.id.md) - -## SavedObjectsImportError.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) > [id](./kibana-plugin-server.savedobjectsimporterror.id.md) + +## SavedObjectsImportError.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.md index 0d734c21c31514..f0a734c2f29cc6 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) - -## SavedObjectsImportError interface - -Represents a failure to import. - -Signature: - -```typescript -export interface SavedObjectsImportError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [error](./kibana-plugin-server.savedobjectsimporterror.error.md) | SavedObjectsImportConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError | | -| [id](./kibana-plugin-server.savedobjectsimporterror.id.md) | string | | -| [title](./kibana-plugin-server.savedobjectsimporterror.title.md) | string | | -| [type](./kibana-plugin-server.savedobjectsimporterror.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) + +## SavedObjectsImportError interface + +Represents a failure to import. + +Signature: + +```typescript +export interface SavedObjectsImportError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [error](./kibana-plugin-server.savedobjectsimporterror.error.md) | SavedObjectsImportConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError | | +| [id](./kibana-plugin-server.savedobjectsimporterror.id.md) | string | | +| [title](./kibana-plugin-server.savedobjectsimporterror.title.md) | string | | +| [type](./kibana-plugin-server.savedobjectsimporterror.type.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.title.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.title.md index bd0beeb4d79dd5..80b8b695ea4670 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.title.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.title.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) > [title](./kibana-plugin-server.savedobjectsimporterror.title.md) - -## SavedObjectsImportError.title property - -Signature: - -```typescript -title?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) > [title](./kibana-plugin-server.savedobjectsimporterror.title.md) + +## SavedObjectsImportError.title property + +Signature: + +```typescript +title?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.type.md index 0b48cc4bbaecf3..6d4edf37d7a2cf 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimporterror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) > [type](./kibana-plugin-server.savedobjectsimporterror.type.md) - -## SavedObjectsImportError.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportError](./kibana-plugin-server.savedobjectsimporterror.md) > [type](./kibana-plugin-server.savedobjectsimporterror.type.md) + +## SavedObjectsImportError.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.blocking.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.blocking.md index bbbd499ea5844e..44564f6db6976f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.blocking.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.blocking.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) > [blocking](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.blocking.md) - -## SavedObjectsImportMissingReferencesError.blocking property - -Signature: - -```typescript -blocking: Array<{ - type: string; - id: string; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) > [blocking](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.blocking.md) + +## SavedObjectsImportMissingReferencesError.blocking property + +Signature: + +```typescript +blocking: Array<{ + type: string; + id: string; + }>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.md index fb4e997fe17baf..72ce40bd6edfa2 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) - -## SavedObjectsImportMissingReferencesError interface - -Represents a failure to import due to missing references. - -Signature: - -```typescript -export interface SavedObjectsImportMissingReferencesError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [blocking](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.blocking.md) | Array<{
type: string;
id: string;
}> | | -| [references](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.references.md) | Array<{
type: string;
id: string;
}> | | -| [type](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.type.md) | 'missing_references' | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) + +## SavedObjectsImportMissingReferencesError interface + +Represents a failure to import due to missing references. + +Signature: + +```typescript +export interface SavedObjectsImportMissingReferencesError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [blocking](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.blocking.md) | Array<{
type: string;
id: string;
}> | | +| [references](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.references.md) | Array<{
type: string;
id: string;
}> | | +| [type](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.type.md) | 'missing_references' | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.references.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.references.md index 593d2b48d456c8..795bfa9fc9ea90 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.references.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.references.md @@ -1,14 +1,14 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) > [references](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.references.md) - -## SavedObjectsImportMissingReferencesError.references property - -Signature: - -```typescript -references: Array<{ - type: string; - id: string; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) > [references](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.references.md) + +## SavedObjectsImportMissingReferencesError.references property + +Signature: + +```typescript +references: Array<{ + type: string; + id: string; + }>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.type.md index 3e6e80f77c4479..80ac2efb28dbcf 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportmissingreferenceserror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) > [type](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.type.md) - -## SavedObjectsImportMissingReferencesError.type property - -Signature: - -```typescript -type: 'missing_references'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportMissingReferencesError](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.md) > [type](./kibana-plugin-server.savedobjectsimportmissingreferenceserror.type.md) + +## SavedObjectsImportMissingReferencesError.type property + +Signature: + +```typescript +type: 'missing_references'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.md index a1ea33e11b14f7..9653fa802a3e85 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) - -## SavedObjectsImportOptions interface - -Options to control the import operation. - -Signature: - -```typescript -export interface SavedObjectsImportOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [namespace](./kibana-plugin-server.savedobjectsimportoptions.namespace.md) | string | | -| [objectLimit](./kibana-plugin-server.savedobjectsimportoptions.objectlimit.md) | number | | -| [overwrite](./kibana-plugin-server.savedobjectsimportoptions.overwrite.md) | boolean | | -| [readStream](./kibana-plugin-server.savedobjectsimportoptions.readstream.md) | Readable | | -| [savedObjectsClient](./kibana-plugin-server.savedobjectsimportoptions.savedobjectsclient.md) | SavedObjectsClientContract | | -| [supportedTypes](./kibana-plugin-server.savedobjectsimportoptions.supportedtypes.md) | string[] | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) + +## SavedObjectsImportOptions interface + +Options to control the import operation. + +Signature: + +```typescript +export interface SavedObjectsImportOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [namespace](./kibana-plugin-server.savedobjectsimportoptions.namespace.md) | string | | +| [objectLimit](./kibana-plugin-server.savedobjectsimportoptions.objectlimit.md) | number | | +| [overwrite](./kibana-plugin-server.savedobjectsimportoptions.overwrite.md) | boolean | | +| [readStream](./kibana-plugin-server.savedobjectsimportoptions.readstream.md) | Readable | | +| [savedObjectsClient](./kibana-plugin-server.savedobjectsimportoptions.savedobjectsclient.md) | SavedObjectsClientContract | | +| [supportedTypes](./kibana-plugin-server.savedobjectsimportoptions.supportedtypes.md) | string[] | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.namespace.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.namespace.md index 600a4dc1176f3a..2b15ba2a1b7ec3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.namespace.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.namespace.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [namespace](./kibana-plugin-server.savedobjectsimportoptions.namespace.md) - -## SavedObjectsImportOptions.namespace property - -Signature: - -```typescript -namespace?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [namespace](./kibana-plugin-server.savedobjectsimportoptions.namespace.md) + +## SavedObjectsImportOptions.namespace property + +Signature: + +```typescript +namespace?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.objectlimit.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.objectlimit.md index bb040a560b89b0..89c01a13644b86 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.objectlimit.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.objectlimit.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [objectLimit](./kibana-plugin-server.savedobjectsimportoptions.objectlimit.md) - -## SavedObjectsImportOptions.objectLimit property - -Signature: - -```typescript -objectLimit: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [objectLimit](./kibana-plugin-server.savedobjectsimportoptions.objectlimit.md) + +## SavedObjectsImportOptions.objectLimit property + +Signature: + +```typescript +objectLimit: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.overwrite.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.overwrite.md index 4586a935685881..54728aaa80fed5 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.overwrite.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.overwrite.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [overwrite](./kibana-plugin-server.savedobjectsimportoptions.overwrite.md) - -## SavedObjectsImportOptions.overwrite property - -Signature: - -```typescript -overwrite: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [overwrite](./kibana-plugin-server.savedobjectsimportoptions.overwrite.md) + +## SavedObjectsImportOptions.overwrite property + +Signature: + +```typescript +overwrite: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.readstream.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.readstream.md index 4b54f931797cf3..7739fdfbc8460b 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.readstream.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.readstream.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [readStream](./kibana-plugin-server.savedobjectsimportoptions.readstream.md) - -## SavedObjectsImportOptions.readStream property - -Signature: - -```typescript -readStream: Readable; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [readStream](./kibana-plugin-server.savedobjectsimportoptions.readstream.md) + +## SavedObjectsImportOptions.readStream property + +Signature: + +```typescript +readStream: Readable; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.savedobjectsclient.md index f0d439aedc0058..23d5aba5fe1144 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.savedobjectsclient.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.savedobjectsclient.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [savedObjectsClient](./kibana-plugin-server.savedobjectsimportoptions.savedobjectsclient.md) - -## SavedObjectsImportOptions.savedObjectsClient property - -Signature: - -```typescript -savedObjectsClient: SavedObjectsClientContract; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [savedObjectsClient](./kibana-plugin-server.savedobjectsimportoptions.savedobjectsclient.md) + +## SavedObjectsImportOptions.savedObjectsClient property + +Signature: + +```typescript +savedObjectsClient: SavedObjectsClientContract; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.supportedtypes.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.supportedtypes.md index 0359c53d8fcf10..03ee12ab2a0f7d 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.supportedtypes.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportoptions.supportedtypes.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [supportedTypes](./kibana-plugin-server.savedobjectsimportoptions.supportedtypes.md) - -## SavedObjectsImportOptions.supportedTypes property - -Signature: - -```typescript -supportedTypes: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportOptions](./kibana-plugin-server.savedobjectsimportoptions.md) > [supportedTypes](./kibana-plugin-server.savedobjectsimportoptions.supportedtypes.md) + +## SavedObjectsImportOptions.supportedTypes property + +Signature: + +```typescript +supportedTypes: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.errors.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.errors.md index c59390c6d45e05..1df7c0a37323ea 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.errors.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.errors.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) > [errors](./kibana-plugin-server.savedobjectsimportresponse.errors.md) - -## SavedObjectsImportResponse.errors property - -Signature: - -```typescript -errors?: SavedObjectsImportError[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) > [errors](./kibana-plugin-server.savedobjectsimportresponse.errors.md) + +## SavedObjectsImportResponse.errors property + +Signature: + +```typescript +errors?: SavedObjectsImportError[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.md index 23f6526dc6367d..3e42307e90a4a8 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) - -## SavedObjectsImportResponse interface - -The response describing the result of an import. - -Signature: - -```typescript -export interface SavedObjectsImportResponse -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [errors](./kibana-plugin-server.savedobjectsimportresponse.errors.md) | SavedObjectsImportError[] | | -| [success](./kibana-plugin-server.savedobjectsimportresponse.success.md) | boolean | | -| [successCount](./kibana-plugin-server.savedobjectsimportresponse.successcount.md) | number | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) + +## SavedObjectsImportResponse interface + +The response describing the result of an import. + +Signature: + +```typescript +export interface SavedObjectsImportResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [errors](./kibana-plugin-server.savedobjectsimportresponse.errors.md) | SavedObjectsImportError[] | | +| [success](./kibana-plugin-server.savedobjectsimportresponse.success.md) | boolean | | +| [successCount](./kibana-plugin-server.savedobjectsimportresponse.successcount.md) | number | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.success.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.success.md index 5fd76959c556c5..77e528e8541ce3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.success.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.success.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) > [success](./kibana-plugin-server.savedobjectsimportresponse.success.md) - -## SavedObjectsImportResponse.success property - -Signature: - -```typescript -success: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) > [success](./kibana-plugin-server.savedobjectsimportresponse.success.md) + +## SavedObjectsImportResponse.success property + +Signature: + +```typescript +success: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.successcount.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.successcount.md index 4b49f57e8367d3..4c1fbcdbcc854d 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.successcount.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportresponse.successcount.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) > [successCount](./kibana-plugin-server.savedobjectsimportresponse.successcount.md) - -## SavedObjectsImportResponse.successCount property - -Signature: - -```typescript -successCount: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportResponse](./kibana-plugin-server.savedobjectsimportresponse.md) > [successCount](./kibana-plugin-server.savedobjectsimportresponse.successcount.md) + +## SavedObjectsImportResponse.successCount property + +Signature: + +```typescript +successCount: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.id.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.id.md index 568185b2438b78..6491f514c4a3d5 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) > [id](./kibana-plugin-server.savedobjectsimportretry.id.md) - -## SavedObjectsImportRetry.id property - -Signature: - -```typescript -id: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) > [id](./kibana-plugin-server.savedobjectsimportretry.id.md) + +## SavedObjectsImportRetry.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.md index dc842afbf9f294..d7fcc613b2508a 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) - -## SavedObjectsImportRetry interface - -Describes a retry operation for importing a saved object. - -Signature: - -```typescript -export interface SavedObjectsImportRetry -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [id](./kibana-plugin-server.savedobjectsimportretry.id.md) | string | | -| [overwrite](./kibana-plugin-server.savedobjectsimportretry.overwrite.md) | boolean | | -| [replaceReferences](./kibana-plugin-server.savedobjectsimportretry.replacereferences.md) | Array<{
type: string;
from: string;
to: string;
}> | | -| [type](./kibana-plugin-server.savedobjectsimportretry.type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) + +## SavedObjectsImportRetry interface + +Describes a retry operation for importing a saved object. + +Signature: + +```typescript +export interface SavedObjectsImportRetry +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-server.savedobjectsimportretry.id.md) | string | | +| [overwrite](./kibana-plugin-server.savedobjectsimportretry.overwrite.md) | boolean | | +| [replaceReferences](./kibana-plugin-server.savedobjectsimportretry.replacereferences.md) | Array<{
type: string;
from: string;
to: string;
}> | | +| [type](./kibana-plugin-server.savedobjectsimportretry.type.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.overwrite.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.overwrite.md index 36a31e836aebc3..68310c61ca0bd8 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.overwrite.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.overwrite.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) > [overwrite](./kibana-plugin-server.savedobjectsimportretry.overwrite.md) - -## SavedObjectsImportRetry.overwrite property - -Signature: - -```typescript -overwrite: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) > [overwrite](./kibana-plugin-server.savedobjectsimportretry.overwrite.md) + +## SavedObjectsImportRetry.overwrite property + +Signature: + +```typescript +overwrite: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.replacereferences.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.replacereferences.md index c3439bb554e13e..659230932c8754 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.replacereferences.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.replacereferences.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) > [replaceReferences](./kibana-plugin-server.savedobjectsimportretry.replacereferences.md) - -## SavedObjectsImportRetry.replaceReferences property - -Signature: - -```typescript -replaceReferences: Array<{ - type: string; - from: string; - to: string; - }>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) > [replaceReferences](./kibana-plugin-server.savedobjectsimportretry.replacereferences.md) + +## SavedObjectsImportRetry.replaceReferences property + +Signature: + +```typescript +replaceReferences: Array<{ + type: string; + from: string; + to: string; + }>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.type.md index 8f0408dcbc11e6..db3f3d1c321920 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportretry.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) > [type](./kibana-plugin-server.savedobjectsimportretry.type.md) - -## SavedObjectsImportRetry.type property - -Signature: - -```typescript -type: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportRetry](./kibana-plugin-server.savedobjectsimportretry.md) > [type](./kibana-plugin-server.savedobjectsimportretry.type.md) + +## SavedObjectsImportRetry.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.md index 913038c5bc67d4..cd6a553b4da193 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) - -## SavedObjectsImportUnknownError interface - -Represents a failure to import due to an unknown reason. - -Signature: - -```typescript -export interface SavedObjectsImportUnknownError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [message](./kibana-plugin-server.savedobjectsimportunknownerror.message.md) | string | | -| [statusCode](./kibana-plugin-server.savedobjectsimportunknownerror.statuscode.md) | number | | -| [type](./kibana-plugin-server.savedobjectsimportunknownerror.type.md) | 'unknown' | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) + +## SavedObjectsImportUnknownError interface + +Represents a failure to import due to an unknown reason. + +Signature: + +```typescript +export interface SavedObjectsImportUnknownError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [message](./kibana-plugin-server.savedobjectsimportunknownerror.message.md) | string | | +| [statusCode](./kibana-plugin-server.savedobjectsimportunknownerror.statuscode.md) | number | | +| [type](./kibana-plugin-server.savedobjectsimportunknownerror.type.md) | 'unknown' | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.message.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.message.md index 96b8b98bf6a9f0..0056be3b61018e 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.message.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.message.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) > [message](./kibana-plugin-server.savedobjectsimportunknownerror.message.md) - -## SavedObjectsImportUnknownError.message property - -Signature: - -```typescript -message: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) > [message](./kibana-plugin-server.savedobjectsimportunknownerror.message.md) + +## SavedObjectsImportUnknownError.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.statuscode.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.statuscode.md index 9cdef84ff4ea7d..1511aaa786fe1d 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.statuscode.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.statuscode.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) > [statusCode](./kibana-plugin-server.savedobjectsimportunknownerror.statuscode.md) - -## SavedObjectsImportUnknownError.statusCode property - -Signature: - -```typescript -statusCode: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) > [statusCode](./kibana-plugin-server.savedobjectsimportunknownerror.statuscode.md) + +## SavedObjectsImportUnknownError.statusCode property + +Signature: + +```typescript +statusCode: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.type.md index cf31166157ab7e..aeb948de0aa000 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunknownerror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) > [type](./kibana-plugin-server.savedobjectsimportunknownerror.type.md) - -## SavedObjectsImportUnknownError.type property - -Signature: - -```typescript -type: 'unknown'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnknownError](./kibana-plugin-server.savedobjectsimportunknownerror.md) > [type](./kibana-plugin-server.savedobjectsimportunknownerror.type.md) + +## SavedObjectsImportUnknownError.type property + +Signature: + +```typescript +type: 'unknown'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md index cc775b20bb8f29..cff068345d8015 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md) - -## SavedObjectsImportUnsupportedTypeError interface - -Represents a failure to import due to having an unsupported saved object type. - -Signature: - -```typescript -export interface SavedObjectsImportUnsupportedTypeError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [type](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.type.md) | 'unsupported_type' | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md) + +## SavedObjectsImportUnsupportedTypeError interface + +Represents a failure to import due to having an unsupported saved object type. + +Signature: + +```typescript +export interface SavedObjectsImportUnsupportedTypeError +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [type](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.type.md) | 'unsupported_type' | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunsupportedtypeerror.type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunsupportedtypeerror.type.md index ae69911020c186..6145eefed84c9e 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsimportunsupportedtypeerror.type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsimportunsupportedtypeerror.type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md) > [type](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.type.md) - -## SavedObjectsImportUnsupportedTypeError.type property - -Signature: - -```typescript -type: 'unsupported_type'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.md) > [type](./kibana-plugin-server.savedobjectsimportunsupportedtypeerror.type.md) + +## SavedObjectsImportUnsupportedTypeError.type property + +Signature: + +```typescript +type: 'unsupported_type'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.md index 38ee40157888f5..b53ec0247511fa 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsIncrementCounterOptions](./kibana-plugin-server.savedobjectsincrementcounteroptions.md) - -## SavedObjectsIncrementCounterOptions interface - - -Signature: - -```typescript -export interface SavedObjectsIncrementCounterOptions extends SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [migrationVersion](./kibana-plugin-server.savedobjectsincrementcounteroptions.migrationversion.md) | SavedObjectsMigrationVersion | | -| [refresh](./kibana-plugin-server.savedobjectsincrementcounteroptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsIncrementCounterOptions](./kibana-plugin-server.savedobjectsincrementcounteroptions.md) + +## SavedObjectsIncrementCounterOptions interface + + +Signature: + +```typescript +export interface SavedObjectsIncrementCounterOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [migrationVersion](./kibana-plugin-server.savedobjectsincrementcounteroptions.migrationversion.md) | SavedObjectsMigrationVersion | | +| [refresh](./kibana-plugin-server.savedobjectsincrementcounteroptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.migrationversion.md b/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.migrationversion.md index 3b80dea4fecde6..6e24d916969b9b 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.migrationversion.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.migrationversion.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsIncrementCounterOptions](./kibana-plugin-server.savedobjectsincrementcounteroptions.md) > [migrationVersion](./kibana-plugin-server.savedobjectsincrementcounteroptions.migrationversion.md) - -## SavedObjectsIncrementCounterOptions.migrationVersion property - -Signature: - -```typescript -migrationVersion?: SavedObjectsMigrationVersion; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsIncrementCounterOptions](./kibana-plugin-server.savedobjectsincrementcounteroptions.md) > [migrationVersion](./kibana-plugin-server.savedobjectsincrementcounteroptions.migrationversion.md) + +## SavedObjectsIncrementCounterOptions.migrationVersion property + +Signature: + +```typescript +migrationVersion?: SavedObjectsMigrationVersion; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.refresh.md index acd8d6f0916f9f..13104808f8dec7 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.refresh.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsincrementcounteroptions.refresh.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsIncrementCounterOptions](./kibana-plugin-server.savedobjectsincrementcounteroptions.md) > [refresh](./kibana-plugin-server.savedobjectsincrementcounteroptions.refresh.md) - -## SavedObjectsIncrementCounterOptions.refresh property - -The Elasticsearch Refresh setting for this operation - -Signature: - -```typescript -refresh?: MutatingOperationRefreshSetting; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsIncrementCounterOptions](./kibana-plugin-server.savedobjectsincrementcounteroptions.md) > [refresh](./kibana-plugin-server.savedobjectsincrementcounteroptions.refresh.md) + +## SavedObjectsIncrementCounterOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.debug.md b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.debug.md index be44bc7422d6ce..64854078d41d60 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.debug.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.debug.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) > [debug](./kibana-plugin-server.savedobjectsmigrationlogger.debug.md) - -## SavedObjectsMigrationLogger.debug property - -Signature: - -```typescript -debug: (msg: string) => void; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) > [debug](./kibana-plugin-server.savedobjectsmigrationlogger.debug.md) + +## SavedObjectsMigrationLogger.debug property + +Signature: + +```typescript +debug: (msg: string) => void; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.info.md b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.info.md index f8bbd5e4e6250a..57bb1e77d0e788 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.info.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.info.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) > [info](./kibana-plugin-server.savedobjectsmigrationlogger.info.md) - -## SavedObjectsMigrationLogger.info property - -Signature: - -```typescript -info: (msg: string) => void; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) > [info](./kibana-plugin-server.savedobjectsmigrationlogger.info.md) + +## SavedObjectsMigrationLogger.info property + +Signature: + +```typescript +info: (msg: string) => void; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.md b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.md index 9e21cb0641bafc..a98d88700cd555 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) - -## SavedObjectsMigrationLogger interface - - -Signature: - -```typescript -export interface SavedObjectsMigrationLogger -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [debug](./kibana-plugin-server.savedobjectsmigrationlogger.debug.md) | (msg: string) => void | | -| [info](./kibana-plugin-server.savedobjectsmigrationlogger.info.md) | (msg: string) => void | | -| [warning](./kibana-plugin-server.savedobjectsmigrationlogger.warning.md) | (msg: string) => void | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) + +## SavedObjectsMigrationLogger interface + + +Signature: + +```typescript +export interface SavedObjectsMigrationLogger +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [debug](./kibana-plugin-server.savedobjectsmigrationlogger.debug.md) | (msg: string) => void | | +| [info](./kibana-plugin-server.savedobjectsmigrationlogger.info.md) | (msg: string) => void | | +| [warning](./kibana-plugin-server.savedobjectsmigrationlogger.warning.md) | (msg: string) => void | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.warning.md b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.warning.md index 978090f9fc8855..a87955d603b704 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.warning.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationlogger.warning.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) > [warning](./kibana-plugin-server.savedobjectsmigrationlogger.warning.md) - -## SavedObjectsMigrationLogger.warning property - -Signature: - -```typescript -warning: (msg: string) => void; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationLogger](./kibana-plugin-server.savedobjectsmigrationlogger.md) > [warning](./kibana-plugin-server.savedobjectsmigrationlogger.warning.md) + +## SavedObjectsMigrationLogger.warning property + +Signature: + +```typescript +warning: (msg: string) => void; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationversion.md b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationversion.md index b7f9c8fd8fe988..5e32cf5985a3e8 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationversion.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsmigrationversion.md @@ -1,18 +1,18 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationVersion](./kibana-plugin-server.savedobjectsmigrationversion.md) - -## SavedObjectsMigrationVersion interface - -Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. - -Signature: - -```typescript -export interface SavedObjectsMigrationVersion -``` - -## Example - -migrationVersion: { dashboard: '7.1.1', space: '6.6.6', } - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsMigrationVersion](./kibana-plugin-server.savedobjectsmigrationversion.md) + +## SavedObjectsMigrationVersion interface + +Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. + +Signature: + +```typescript +export interface SavedObjectsMigrationVersion +``` + +## Example + +migrationVersion: { dashboard: '7.1.1', space: '6.6.6', } + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._id.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._id.md index cd16eadf519318..05f5e93b9a87c1 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._id.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._id.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_id](./kibana-plugin-server.savedobjectsrawdoc._id.md) - -## SavedObjectsRawDoc.\_id property - -Signature: - -```typescript -_id: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_id](./kibana-plugin-server.savedobjectsrawdoc._id.md) + +## SavedObjectsRawDoc.\_id property + +Signature: + +```typescript +_id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._primary_term.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._primary_term.md index c5eef82322f580..25bd447013039c 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._primary_term.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._primary_term.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_primary\_term](./kibana-plugin-server.savedobjectsrawdoc._primary_term.md) - -## SavedObjectsRawDoc.\_primary\_term property - -Signature: - -```typescript -_primary_term?: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_primary\_term](./kibana-plugin-server.savedobjectsrawdoc._primary_term.md) + +## SavedObjectsRawDoc.\_primary\_term property + +Signature: + +```typescript +_primary_term?: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._seq_no.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._seq_no.md index a3b9a943a708c8..86f8ce619a709f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._seq_no.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._seq_no.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_seq\_no](./kibana-plugin-server.savedobjectsrawdoc._seq_no.md) - -## SavedObjectsRawDoc.\_seq\_no property - -Signature: - -```typescript -_seq_no?: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_seq\_no](./kibana-plugin-server.savedobjectsrawdoc._seq_no.md) + +## SavedObjectsRawDoc.\_seq\_no property + +Signature: + +```typescript +_seq_no?: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._source.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._source.md index 1babaab14f14db..dcf207f8120ea3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._source.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._source.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_source](./kibana-plugin-server.savedobjectsrawdoc._source.md) - -## SavedObjectsRawDoc.\_source property - -Signature: - -```typescript -_source: any; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_source](./kibana-plugin-server.savedobjectsrawdoc._source.md) + +## SavedObjectsRawDoc.\_source property + +Signature: + +```typescript +_source: any; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._type.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._type.md index 31c40e15b53c09..5480b401ba6cef 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._type.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc._type.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_type](./kibana-plugin-server.savedobjectsrawdoc._type.md) - -## SavedObjectsRawDoc.\_type property - -Signature: - -```typescript -_type?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) > [\_type](./kibana-plugin-server.savedobjectsrawdoc._type.md) + +## SavedObjectsRawDoc.\_type property + +Signature: + +```typescript +_type?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc.md index 5864a854653965..b0130df01817f3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrawdoc.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) - -## SavedObjectsRawDoc interface - -A raw document as represented directly in the saved object index. - -Signature: - -```typescript -export interface RawDoc -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [\_id](./kibana-plugin-server.savedobjectsrawdoc._id.md) | string | | -| [\_primary\_term](./kibana-plugin-server.savedobjectsrawdoc._primary_term.md) | number | | -| [\_seq\_no](./kibana-plugin-server.savedobjectsrawdoc._seq_no.md) | number | | -| [\_source](./kibana-plugin-server.savedobjectsrawdoc._source.md) | any | | -| [\_type](./kibana-plugin-server.savedobjectsrawdoc._type.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) + +## SavedObjectsRawDoc interface + +A raw document as represented directly in the saved object index. + +Signature: + +```typescript +export interface RawDoc +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [\_id](./kibana-plugin-server.savedobjectsrawdoc._id.md) | string | | +| [\_primary\_term](./kibana-plugin-server.savedobjectsrawdoc._primary_term.md) | number | | +| [\_seq\_no](./kibana-plugin-server.savedobjectsrawdoc._seq_no.md) | number | | +| [\_source](./kibana-plugin-server.savedobjectsrawdoc._source.md) | any | | +| [\_type](./kibana-plugin-server.savedobjectsrawdoc._type.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkcreate.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkcreate.md index 003bc6ac72466d..dfe9e51e62483c 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkcreate.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkcreate.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [bulkCreate](./kibana-plugin-server.savedobjectsrepository.bulkcreate.md) - -## SavedObjectsRepository.bulkCreate() method - -Creates multiple documents at once - -Signature: - -```typescript -bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| objects | Array<SavedObjectsBulkCreateObject<T>> | | -| options | SavedObjectsCreateOptions | | - -Returns: - -`Promise>` - -{promise} - {saved\_objects: \[\[{ id, type, version, references, attributes, error: { message } }\]} - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [bulkCreate](./kibana-plugin-server.savedobjectsrepository.bulkcreate.md) + +## SavedObjectsRepository.bulkCreate() method + +Creates multiple documents at once + +Signature: + +```typescript +bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | Array<SavedObjectsBulkCreateObject<T>> | | +| options | SavedObjectsCreateOptions | | + +Returns: + +`Promise>` + +{promise} - {saved\_objects: \[\[{ id, type, version, references, attributes, error: { message } }\]} + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkget.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkget.md index 605984d5dea30d..34b113bce5410e 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkget.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkget.md @@ -1,31 +1,31 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [bulkGet](./kibana-plugin-server.savedobjectsrepository.bulkget.md) - -## SavedObjectsRepository.bulkGet() method - -Returns an array of objects by id - -Signature: - -```typescript -bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| objects | SavedObjectsBulkGetObject[] | | -| options | SavedObjectsBaseOptions | | - -Returns: - -`Promise>` - -{promise} - { saved\_objects: \[{ id, type, version, attributes }\] } - -## Example - -bulkGet(\[ { id: 'one', type: 'config' }, { id: 'foo', type: 'index-pattern' } \]) - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [bulkGet](./kibana-plugin-server.savedobjectsrepository.bulkget.md) + +## SavedObjectsRepository.bulkGet() method + +Returns an array of objects by id + +Signature: + +```typescript +bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | SavedObjectsBulkGetObject[] | | +| options | SavedObjectsBaseOptions | | + +Returns: + +`Promise>` + +{promise} - { saved\_objects: \[{ id, type, version, attributes }\] } + +## Example + +bulkGet(\[ { id: 'one', type: 'config' }, { id: 'foo', type: 'index-pattern' } \]) + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkupdate.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkupdate.md index 52a73c83b4c3a4..23c7a926249573 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkupdate.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.bulkupdate.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [bulkUpdate](./kibana-plugin-server.savedobjectsrepository.bulkupdate.md) - -## SavedObjectsRepository.bulkUpdate() method - -Updates multiple objects in bulk - -Signature: - -```typescript -bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| objects | Array<SavedObjectsBulkUpdateObject<T>> | | -| options | SavedObjectsBulkUpdateOptions | | - -Returns: - -`Promise>` - -{promise} - {saved\_objects: \[\[{ id, type, version, references, attributes, error: { message } }\]} - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [bulkUpdate](./kibana-plugin-server.savedobjectsrepository.bulkupdate.md) + +## SavedObjectsRepository.bulkUpdate() method + +Updates multiple objects in bulk + +Signature: + +```typescript +bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | Array<SavedObjectsBulkUpdateObject<T>> | | +| options | SavedObjectsBulkUpdateOptions | | + +Returns: + +`Promise>` + +{promise} - {saved\_objects: \[\[{ id, type, version, references, attributes, error: { message } }\]} + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.create.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.create.md index 3a731629156e23..29e3c3ab246546 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.create.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.create.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [create](./kibana-plugin-server.savedobjectsrepository.create.md) - -## SavedObjectsRepository.create() method - -Persists an object - -Signature: - -```typescript -create(type: string, attributes: T, options?: SavedObjectsCreateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| attributes | T | | -| options | SavedObjectsCreateOptions | | - -Returns: - -`Promise>` - -{promise} - { id, type, version, attributes } - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [create](./kibana-plugin-server.savedobjectsrepository.create.md) + +## SavedObjectsRepository.create() method + +Persists an object + +Signature: + +```typescript +create(type: string, attributes: T, options?: SavedObjectsCreateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| attributes | T | | +| options | SavedObjectsCreateOptions | | + +Returns: + +`Promise>` + +{promise} - { id, type, version, attributes } + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.delete.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.delete.md index 52c36d2da162d2..a53f9423ba7e12 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.delete.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.delete.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [delete](./kibana-plugin-server.savedobjectsrepository.delete.md) - -## SavedObjectsRepository.delete() method - -Deletes an object - -Signature: - -```typescript -delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| id | string | | -| options | SavedObjectsDeleteOptions | | - -Returns: - -`Promise<{}>` - -{promise} - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [delete](./kibana-plugin-server.savedobjectsrepository.delete.md) + +## SavedObjectsRepository.delete() method + +Deletes an object + +Signature: + +```typescript +delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| options | SavedObjectsDeleteOptions | | + +Returns: + +`Promise<{}>` + +{promise} + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.deletebynamespace.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.deletebynamespace.md index ab6eb30e664f19..364443a3444eb5 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.deletebynamespace.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.deletebynamespace.md @@ -1,27 +1,27 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [deleteByNamespace](./kibana-plugin-server.savedobjectsrepository.deletebynamespace.md) - -## SavedObjectsRepository.deleteByNamespace() method - -Deletes all objects from the provided namespace. - -Signature: - -```typescript -deleteByNamespace(namespace: string, options?: SavedObjectsDeleteByNamespaceOptions): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| namespace | string | | -| options | SavedObjectsDeleteByNamespaceOptions | | - -Returns: - -`Promise` - -{promise} - { took, timed\_out, total, deleted, batches, version\_conflicts, noops, retries, failures } - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [deleteByNamespace](./kibana-plugin-server.savedobjectsrepository.deletebynamespace.md) + +## SavedObjectsRepository.deleteByNamespace() method + +Deletes all objects from the provided namespace. + +Signature: + +```typescript +deleteByNamespace(namespace: string, options?: SavedObjectsDeleteByNamespaceOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| namespace | string | | +| options | SavedObjectsDeleteByNamespaceOptions | | + +Returns: + +`Promise` + +{promise} - { took, timed\_out, total, deleted, batches, version\_conflicts, noops, retries, failures } + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.find.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.find.md index 3c2855ed9a50cb..dbf6d59e78d85f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.find.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.find.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [find](./kibana-plugin-server.savedobjectsrepository.find.md) - -## SavedObjectsRepository.find() method - -Signature: - -```typescript -find({ search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespace, type, filter, }: SavedObjectsFindOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| { search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespace, type, filter, } | SavedObjectsFindOptions | | - -Returns: - -`Promise>` - -{promise} - { saved\_objects: \[{ id, type, version, attributes }\], total, per\_page, page } - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [find](./kibana-plugin-server.savedobjectsrepository.find.md) + +## SavedObjectsRepository.find() method + +Signature: + +```typescript +find({ search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespace, type, filter, }: SavedObjectsFindOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespace, type, filter, } | SavedObjectsFindOptions | | + +Returns: + +`Promise>` + +{promise} - { saved\_objects: \[{ id, type, version, attributes }\], total, per\_page, page } + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.get.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.get.md index dd1d81f225937d..930a4647ca1750 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.get.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.get.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [get](./kibana-plugin-server.savedobjectsrepository.get.md) - -## SavedObjectsRepository.get() method - -Gets a single object - -Signature: - -```typescript -get(type: string, id: string, options?: SavedObjectsBaseOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| id | string | | -| options | SavedObjectsBaseOptions | | - -Returns: - -`Promise>` - -{promise} - { id, type, version, attributes } - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [get](./kibana-plugin-server.savedobjectsrepository.get.md) + +## SavedObjectsRepository.get() method + +Gets a single object + +Signature: + +```typescript +get(type: string, id: string, options?: SavedObjectsBaseOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| options | SavedObjectsBaseOptions | | + +Returns: + +`Promise>` + +{promise} - { id, type, version, attributes } + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.incrementcounter.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.incrementcounter.md index f20e9a73d99a14..6b30a05c1c918f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.incrementcounter.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.incrementcounter.md @@ -1,43 +1,43 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [incrementCounter](./kibana-plugin-server.savedobjectsrepository.incrementcounter.md) - -## SavedObjectsRepository.incrementCounter() method - -Increases a counter field by one. Creates the document if one doesn't exist for the given id. - -Signature: - -```typescript -incrementCounter(type: string, id: string, counterFieldName: string, options?: SavedObjectsIncrementCounterOptions): Promise<{ - id: string; - type: string; - updated_at: string; - references: any; - version: string; - attributes: any; - }>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| id | string | | -| counterFieldName | string | | -| options | SavedObjectsIncrementCounterOptions | | - -Returns: - -`Promise<{ - id: string; - type: string; - updated_at: string; - references: any; - version: string; - attributes: any; - }>` - -{promise} - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [incrementCounter](./kibana-plugin-server.savedobjectsrepository.incrementcounter.md) + +## SavedObjectsRepository.incrementCounter() method + +Increases a counter field by one. Creates the document if one doesn't exist for the given id. + +Signature: + +```typescript +incrementCounter(type: string, id: string, counterFieldName: string, options?: SavedObjectsIncrementCounterOptions): Promise<{ + id: string; + type: string; + updated_at: string; + references: any; + version: string; + attributes: any; + }>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| counterFieldName | string | | +| options | SavedObjectsIncrementCounterOptions | | + +Returns: + +`Promise<{ + id: string; + type: string; + updated_at: string; + references: any; + version: string; + attributes: any; + }>` + +{promise} + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.md index 681b2233a1e87a..156a92047cc789 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.md @@ -1,28 +1,28 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) - -## SavedObjectsRepository class - - -Signature: - -```typescript -export declare class SavedObjectsRepository -``` - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [bulkCreate(objects, options)](./kibana-plugin-server.savedobjectsrepository.bulkcreate.md) | | Creates multiple documents at once | -| [bulkGet(objects, options)](./kibana-plugin-server.savedobjectsrepository.bulkget.md) | | Returns an array of objects by id | -| [bulkUpdate(objects, options)](./kibana-plugin-server.savedobjectsrepository.bulkupdate.md) | | Updates multiple objects in bulk | -| [create(type, attributes, options)](./kibana-plugin-server.savedobjectsrepository.create.md) | | Persists an object | -| [delete(type, id, options)](./kibana-plugin-server.savedobjectsrepository.delete.md) | | Deletes an object | -| [deleteByNamespace(namespace, options)](./kibana-plugin-server.savedobjectsrepository.deletebynamespace.md) | | Deletes all objects from the provided namespace. | -| [find({ search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespace, type, filter, })](./kibana-plugin-server.savedobjectsrepository.find.md) | | | -| [get(type, id, options)](./kibana-plugin-server.savedobjectsrepository.get.md) | | Gets a single object | -| [incrementCounter(type, id, counterFieldName, options)](./kibana-plugin-server.savedobjectsrepository.incrementcounter.md) | | Increases a counter field by one. Creates the document if one doesn't exist for the given id. | -| [update(type, id, attributes, options)](./kibana-plugin-server.savedobjectsrepository.update.md) | | Updates an object | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) + +## SavedObjectsRepository class + + +Signature: + +```typescript +export declare class SavedObjectsRepository +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [bulkCreate(objects, options)](./kibana-plugin-server.savedobjectsrepository.bulkcreate.md) | | Creates multiple documents at once | +| [bulkGet(objects, options)](./kibana-plugin-server.savedobjectsrepository.bulkget.md) | | Returns an array of objects by id | +| [bulkUpdate(objects, options)](./kibana-plugin-server.savedobjectsrepository.bulkupdate.md) | | Updates multiple objects in bulk | +| [create(type, attributes, options)](./kibana-plugin-server.savedobjectsrepository.create.md) | | Persists an object | +| [delete(type, id, options)](./kibana-plugin-server.savedobjectsrepository.delete.md) | | Deletes an object | +| [deleteByNamespace(namespace, options)](./kibana-plugin-server.savedobjectsrepository.deletebynamespace.md) | | Deletes all objects from the provided namespace. | +| [find({ search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespace, type, filter, })](./kibana-plugin-server.savedobjectsrepository.find.md) | | | +| [get(type, id, options)](./kibana-plugin-server.savedobjectsrepository.get.md) | | Gets a single object | +| [incrementCounter(type, id, counterFieldName, options)](./kibana-plugin-server.savedobjectsrepository.incrementcounter.md) | | Increases a counter field by one. Creates the document if one doesn't exist for the given id. | +| [update(type, id, attributes, options)](./kibana-plugin-server.savedobjectsrepository.update.md) | | Updates an object | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.update.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.update.md index 15890ab9211aa8..5e9f69ecc567bb 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.update.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepository.update.md @@ -1,29 +1,29 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [update](./kibana-plugin-server.savedobjectsrepository.update.md) - -## SavedObjectsRepository.update() method - -Updates an object - -Signature: - -```typescript -update(type: string, id: string, attributes: Partial, options?: SavedObjectsUpdateOptions): Promise>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | -| id | string | | -| attributes | Partial<T> | | -| options | SavedObjectsUpdateOptions | | - -Returns: - -`Promise>` - -{promise} - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) > [update](./kibana-plugin-server.savedobjectsrepository.update.md) + +## SavedObjectsRepository.update() method + +Updates an object + +Signature: + +```typescript +update(type: string, id: string, attributes: Partial, options?: SavedObjectsUpdateOptions): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| attributes | Partial<T> | | +| options | SavedObjectsUpdateOptions | | + +Returns: + +`Promise>` + +{promise} + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.createinternalrepository.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.createinternalrepository.md new file mode 100644 index 00000000000000..b808d38793fffc --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.createinternalrepository.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepositoryFactory](./kibana-plugin-server.savedobjectsrepositoryfactory.md) > [createInternalRepository](./kibana-plugin-server.savedobjectsrepositoryfactory.createinternalrepository.md) + +## SavedObjectsRepositoryFactory.createInternalRepository property + +Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. + +Signature: + +```typescript +createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.createscopedrepository.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.createscopedrepository.md new file mode 100644 index 00000000000000..20322d809dce76 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.createscopedrepository.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepositoryFactory](./kibana-plugin-server.savedobjectsrepositoryfactory.md) > [createScopedRepository](./kibana-plugin-server.savedobjectsrepositoryfactory.createscopedrepository.md) + +## SavedObjectsRepositoryFactory.createScopedRepository property + +Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. + +Signature: + +```typescript +createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.md b/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.md new file mode 100644 index 00000000000000..fc6c4a516284ad --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsrepositoryfactory.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsRepositoryFactory](./kibana-plugin-server.savedobjectsrepositoryfactory.md) + +## SavedObjectsRepositoryFactory interface + +Factory provided when invoking a [client factory provider](./kibana-plugin-server.savedobjectsclientfactoryprovider.md) See [SavedObjectsServiceSetup.setClientFactoryProvider](./kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md) + +Signature: + +```typescript +export interface SavedObjectsRepositoryFactory +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [createInternalRepository](./kibana-plugin-server.savedobjectsrepositoryfactory.createinternalrepository.md) | (extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. | +| [createScopedRepository](./kibana-plugin-server.savedobjectsrepositoryfactory.createscopedrepository.md) | (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md index e3542714d96bb7..8ed978d4a2639a 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md @@ -1,25 +1,25 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) - -## SavedObjectsResolveImportErrorsOptions interface - -Options to control the "resolve import" operation. - -Signature: - -```typescript -export interface SavedObjectsResolveImportErrorsOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [namespace](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.namespace.md) | string | | -| [objectLimit](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.objectlimit.md) | number | | -| [readStream](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.readstream.md) | Readable | | -| [retries](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.retries.md) | SavedObjectsImportRetry[] | | -| [savedObjectsClient](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md) | SavedObjectsClientContract | | -| [supportedTypes](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.supportedtypes.md) | string[] | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) + +## SavedObjectsResolveImportErrorsOptions interface + +Options to control the "resolve import" operation. + +Signature: + +```typescript +export interface SavedObjectsResolveImportErrorsOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [namespace](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.namespace.md) | string | | +| [objectLimit](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.objectlimit.md) | number | | +| [readStream](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.readstream.md) | Readable | | +| [retries](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.retries.md) | SavedObjectsImportRetry[] | | +| [savedObjectsClient](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md) | SavedObjectsClientContract | | +| [supportedTypes](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.supportedtypes.md) | string[] | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.namespace.md b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.namespace.md index 6175e75a4bbecc..b88f124545bd58 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.namespace.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.namespace.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [namespace](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.namespace.md) - -## SavedObjectsResolveImportErrorsOptions.namespace property - -Signature: - -```typescript -namespace?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [namespace](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.namespace.md) + +## SavedObjectsResolveImportErrorsOptions.namespace property + +Signature: + +```typescript +namespace?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.objectlimit.md b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.objectlimit.md index d5616851e13867..a2753ceccc36fe 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.objectlimit.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.objectlimit.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [objectLimit](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.objectlimit.md) - -## SavedObjectsResolveImportErrorsOptions.objectLimit property - -Signature: - -```typescript -objectLimit: number; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [objectLimit](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.objectlimit.md) + +## SavedObjectsResolveImportErrorsOptions.objectLimit property + +Signature: + +```typescript +objectLimit: number; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.readstream.md b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.readstream.md index e4b5d92d7b05af..e7a31deed6faa3 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.readstream.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.readstream.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [readStream](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.readstream.md) - -## SavedObjectsResolveImportErrorsOptions.readStream property - -Signature: - -```typescript -readStream: Readable; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [readStream](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.readstream.md) + +## SavedObjectsResolveImportErrorsOptions.readStream property + +Signature: + +```typescript +readStream: Readable; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.retries.md b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.retries.md index 7dc825f762fe91..658aa64cfc33f9 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.retries.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.retries.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [retries](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.retries.md) - -## SavedObjectsResolveImportErrorsOptions.retries property - -Signature: - -```typescript -retries: SavedObjectsImportRetry[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [retries](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.retries.md) + +## SavedObjectsResolveImportErrorsOptions.retries property + +Signature: + +```typescript +retries: SavedObjectsImportRetry[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md index ae5edc98d3a9ed..8a8c620b2cf217 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [savedObjectsClient](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md) - -## SavedObjectsResolveImportErrorsOptions.savedObjectsClient property - -Signature: - -```typescript -savedObjectsClient: SavedObjectsClientContract; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [savedObjectsClient](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md) + +## SavedObjectsResolveImportErrorsOptions.savedObjectsClient property + +Signature: + +```typescript +savedObjectsClient: SavedObjectsClientContract; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.supportedtypes.md b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.supportedtypes.md index 5a92a8d0a99363..9cc97c34669b7e 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.supportedtypes.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsresolveimporterrorsoptions.supportedtypes.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [supportedTypes](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.supportedtypes.md) - -## SavedObjectsResolveImportErrorsOptions.supportedTypes property - -Signature: - -```typescript -supportedTypes: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) > [supportedTypes](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.supportedtypes.md) + +## SavedObjectsResolveImportErrorsOptions.supportedTypes property + +Signature: + +```typescript +supportedTypes: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md index e787d737ada17e..becff5bd2821e1 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) > [addClientWrapper](./kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md) - -## SavedObjectsServiceSetup.addClientWrapper property - -Add a client wrapper with the given priority. - -Signature: - -```typescript -addClientWrapper: (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) > [addClientWrapper](./kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md) + +## SavedObjectsServiceSetup.addClientWrapper property + +Add a [client wrapper factory](./kibana-plugin-server.savedobjectsclientwrapperfactory.md) with the given priority. + +Signature: + +```typescript +addClientWrapper: (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.createinternalrepository.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.createinternalrepository.md deleted file mode 100644 index 492aa1a2453a19..00000000000000 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.createinternalrepository.md +++ /dev/null @@ -1,18 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) > [createInternalRepository](./kibana-plugin-server.savedobjectsservicesetup.createinternalrepository.md) - -## SavedObjectsServiceSetup.createInternalRepository property - -Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. - -Signature: - -```typescript -createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; -``` - -## Remarks - -The repository should only be used for creating and registering a client factory or client wrapper. Using the repository directly for interacting with Saved Objects is an anti-pattern. Use the Saved Objects client from the [SavedObjectsServiceStart\#getScopedClient](./kibana-plugin-server.savedobjectsservicestart.md) method or the [route handler context](./kibana-plugin-server.requesthandlercontext.md) instead. - diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.createscopedrepository.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.createscopedrepository.md deleted file mode 100644 index fc5aa40c21a208..00000000000000 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.createscopedrepository.md +++ /dev/null @@ -1,18 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) > [createScopedRepository](./kibana-plugin-server.savedobjectsservicesetup.createscopedrepository.md) - -## SavedObjectsServiceSetup.createScopedRepository property - -Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. - -Signature: - -```typescript -createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; -``` - -## Remarks - -The repository should only be used for creating and registering a client factory or client wrapper. Using the repository directly for interacting with Saved Objects is an anti-pattern. Use the Saved Objects client from the [SavedObjectsServiceStart\#getScopedClient](./kibana-plugin-server.savedobjectsservicestart.md) method or the [route handler context](./kibana-plugin-server.requesthandlercontext.md) instead. - diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md index 95bd817a43da68..64fb1f4a5f6389 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.md @@ -1,35 +1,33 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) - -## SavedObjectsServiceSetup interface - -Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for creating and registering Saved Object client wrappers. - -Signature: - -```typescript -export interface SavedObjectsServiceSetup -``` - -## Remarks - -Note: The Saved Object setup API's should only be used for creating and registering client wrappers. Constructing a Saved Objects client or repository for use within your own plugin won't have any of the registered wrappers applied and is considered an anti-pattern. Use the Saved Objects client from the [SavedObjectsServiceStart\#getScopedClient](./kibana-plugin-server.savedobjectsservicestart.md) method or the [route handler context](./kibana-plugin-server.requesthandlercontext.md) instead. - -When plugins access the Saved Objects client, a new client is created using the factory provided to `setClientFactory` and wrapped by all wrappers registered through `addClientWrapper`. To create a factory or wrapper, plugins will have to construct a Saved Objects client. First create a repository by calling `scopedRepository` or `internalRepository` and then use this repository as the argument to the [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) constructor. - -## Example - -import {SavedObjectsClient, CoreSetup} from 'src/core/server'; - -export class Plugin() { setup: (core: CoreSetup) => { core.savedObjects.setClientFactory(({request: KibanaRequest}) => { return new SavedObjectsClient(core.savedObjects.scopedRepository(request)); }) } } - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [addClientWrapper](./kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md) | (priority: number, id: string, factory: SavedObjectsClientWrapperFactory<KibanaRequest>) => void | Add a client wrapper with the given priority. | -| [createInternalRepository](./kibana-plugin-server.savedobjectsservicesetup.createinternalrepository.md) | (extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. | -| [createScopedRepository](./kibana-plugin-server.savedobjectsservicesetup.createscopedrepository.md) | (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | -| [setClientFactory](./kibana-plugin-server.savedobjectsservicesetup.setclientfactory.md) | (customClientFactory: SavedObjectsClientFactory<KibanaRequest>) => void | Set a default factory for creating Saved Objects clients. Only one client factory can be set, subsequent calls to this method will fail. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) + +## SavedObjectsServiceSetup interface + +Saved Objects is Kibana's data persistence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for creating and registering Saved Object client wrappers. + +Signature: + +```typescript +export interface SavedObjectsServiceSetup +``` + +## Remarks + +Note: The Saved Object setup API's should only be used for creating and registering client wrappers. Constructing a Saved Objects client or repository for use within your own plugin won't have any of the registered wrappers applied and is considered an anti-pattern. Use the Saved Objects client from the [SavedObjectsServiceStart\#getScopedClient](./kibana-plugin-server.savedobjectsservicestart.md) method or the [route handler context](./kibana-plugin-server.requesthandlercontext.md) instead. + +When plugins access the Saved Objects client, a new client is created using the factory provided to `setClientFactory` and wrapped by all wrappers registered through `addClientWrapper`. To create a factory or wrapper, plugins will have to construct a Saved Objects client. First create a repository by calling `scopedRepository` or `internalRepository` and then use this repository as the argument to the [SavedObjectsClient](./kibana-plugin-server.savedobjectsclient.md) constructor. + +## Example + +import { SavedObjectsClient, CoreSetup } from 'src/core/server'; + +export class Plugin() { setup: (core: CoreSetup) => { core.savedObjects.setClientFactory(({ request: KibanaRequest }) => { return new SavedObjectsClient(core.savedObjects.scopedRepository(request)); }) } } + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [addClientWrapper](./kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md) | (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void | Add a [client wrapper factory](./kibana-plugin-server.savedobjectsclientwrapperfactory.md) with the given priority. | +| [setClientFactoryProvider](./kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md) | (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void | Set the default [factory provider](./kibana-plugin-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-server.savedobjectsservicesetup.setclientfactory.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.setclientfactory.md deleted file mode 100644 index 544e0b9d5fa736..00000000000000 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.setclientfactory.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) > [setClientFactory](./kibana-plugin-server.savedobjectsservicesetup.setclientfactory.md) - -## SavedObjectsServiceSetup.setClientFactory property - -Set a default factory for creating Saved Objects clients. Only one client factory can be set, subsequent calls to this method will fail. - -Signature: - -```typescript -setClientFactory: (customClientFactory: SavedObjectsClientFactory) => void; -``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md new file mode 100644 index 00000000000000..ed11255048f19e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-server.savedobjectsservicesetup.md) > [setClientFactoryProvider](./kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md) + +## SavedObjectsServiceSetup.setClientFactoryProvider property + +Set the default [factory provider](./kibana-plugin-server.savedobjectsclientfactoryprovider.md) for creating Saved Objects clients. Only one provider can be set, subsequent calls to this method will fail. + +Signature: + +```typescript +setClientFactoryProvider: (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.createinternalrepository.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.createinternalrepository.md new file mode 100644 index 00000000000000..d639a8bc66b7e5 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.createinternalrepository.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) > [createInternalRepository](./kibana-plugin-server.savedobjectsservicestart.createinternalrepository.md) + +## SavedObjectsServiceStart.createInternalRepository property + +Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. + +Signature: + +```typescript +createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.createscopedrepository.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.createscopedrepository.md new file mode 100644 index 00000000000000..7683a9e46c51d6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.createscopedrepository.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) > [createScopedRepository](./kibana-plugin-server.savedobjectsservicestart.createscopedrepository.md) + +## SavedObjectsServiceStart.createScopedRepository property + +Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. + +Signature: + +```typescript +createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; +``` + +## Remarks + +Prefer using `getScopedClient`. This should only be used when using methods not exposed on [SavedObjectsClientContract](./kibana-plugin-server.savedobjectsclientcontract.md) + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.getscopedclient.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.getscopedclient.md index e87979a124bdc1..341906856e342e 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.getscopedclient.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.getscopedclient.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) > [getScopedClient](./kibana-plugin-server.savedobjectsservicestart.getscopedclient.md) - -## SavedObjectsServiceStart.getScopedClient property - -Creates a [Saved Objects client](./kibana-plugin-server.savedobjectsclientcontract.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. If other plugins have registered Saved Objects client wrappers, these will be applied to extend the functionality of the client. - -A client that is already scoped to the incoming request is also exposed from the route handler context see [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md). - -Signature: - -```typescript -getScopedClient: (req: KibanaRequest, options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) > [getScopedClient](./kibana-plugin-server.savedobjectsservicestart.getscopedclient.md) + +## SavedObjectsServiceStart.getScopedClient property + +Creates a [Saved Objects client](./kibana-plugin-server.savedobjectsclientcontract.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. If other plugins have registered Saved Objects client wrappers, these will be applied to extend the functionality of the client. + +A client that is already scoped to the incoming request is also exposed from the route handler context see [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md). + +Signature: + +```typescript +getScopedClient: (req: KibanaRequest, options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.md index 5a869b3b6c1cbc..cf2b4f57a74612 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.md @@ -1,20 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) - -## SavedObjectsServiceStart interface - -Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceStart API provides a scoped Saved Objects client for interacting with Saved Objects. - -Signature: - -```typescript -export interface SavedObjectsServiceStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [getScopedClient](./kibana-plugin-server.savedobjectsservicestart.getscopedclient.md) | (req: KibanaRequest, options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract | Creates a [Saved Objects client](./kibana-plugin-server.savedobjectsclientcontract.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. If other plugins have registered Saved Objects client wrappers, these will be applied to extend the functionality of the client.A client that is already scoped to the incoming request is also exposed from the route handler context see [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md). | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsServiceStart](./kibana-plugin-server.savedobjectsservicestart.md) + +## SavedObjectsServiceStart interface + +Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceStart API provides a scoped Saved Objects client for interacting with Saved Objects. + +Signature: + +```typescript +export interface SavedObjectsServiceStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [createInternalRepository](./kibana-plugin-server.savedobjectsservicestart.createinternalrepository.md) | (extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. | +| [createScopedRepository](./kibana-plugin-server.savedobjectsservicestart.createscopedrepository.md) | (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | +| [getScopedClient](./kibana-plugin-server.savedobjectsservicestart.getscopedclient.md) | (req: KibanaRequest, options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract | Creates a [Saved Objects client](./kibana-plugin-server.savedobjectsclientcontract.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. If other plugins have registered Saved Objects client wrappers, these will be applied to extend the functionality of the client.A client that is already scoped to the incoming request is also exposed from the route handler context see [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md). | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.md index 49e8946ad28269..8850bd1b6482fb 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) - -## SavedObjectsUpdateOptions interface - - -Signature: - -```typescript -export interface SavedObjectsUpdateOptions extends SavedObjectsBaseOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [references](./kibana-plugin-server.savedobjectsupdateoptions.references.md) | SavedObjectReference[] | A reference to another saved object. | -| [refresh](./kibana-plugin-server.savedobjectsupdateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | -| [version](./kibana-plugin-server.savedobjectsupdateoptions.version.md) | string | An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) + +## SavedObjectsUpdateOptions interface + + +Signature: + +```typescript +export interface SavedObjectsUpdateOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [references](./kibana-plugin-server.savedobjectsupdateoptions.references.md) | SavedObjectReference[] | A reference to another saved object. | +| [refresh](./kibana-plugin-server.savedobjectsupdateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | +| [version](./kibana-plugin-server.savedobjectsupdateoptions.version.md) | string | An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.references.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.references.md index 76eca68dba37fd..7a9ba971d05f66 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.references.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.references.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) > [references](./kibana-plugin-server.savedobjectsupdateoptions.references.md) - -## SavedObjectsUpdateOptions.references property - -A reference to another saved object. - -Signature: - -```typescript -references?: SavedObjectReference[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) > [references](./kibana-plugin-server.savedobjectsupdateoptions.references.md) + +## SavedObjectsUpdateOptions.references property + +A reference to another saved object. + +Signature: + +```typescript +references?: SavedObjectReference[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.refresh.md index bb1142c2420120..faad2837159011 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.refresh.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.refresh.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) > [refresh](./kibana-plugin-server.savedobjectsupdateoptions.refresh.md) - -## SavedObjectsUpdateOptions.refresh property - -The Elasticsearch Refresh setting for this operation - -Signature: - -```typescript -refresh?: MutatingOperationRefreshSetting; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) > [refresh](./kibana-plugin-server.savedobjectsupdateoptions.refresh.md) + +## SavedObjectsUpdateOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.version.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.version.md index 6e399b343556b6..c9c37e0184cb9b 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.version.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.version.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) > [version](./kibana-plugin-server.savedobjectsupdateoptions.version.md) - -## SavedObjectsUpdateOptions.version property - -An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. - -Signature: - -```typescript -version?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) > [version](./kibana-plugin-server.savedobjectsupdateoptions.version.md) + +## SavedObjectsUpdateOptions.version property + +An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. + +Signature: + +```typescript +version?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.attributes.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.attributes.md index 7d1edb3bb65945..961bb56e33557c 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.attributes.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.attributes.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) > [attributes](./kibana-plugin-server.savedobjectsupdateresponse.attributes.md) - -## SavedObjectsUpdateResponse.attributes property - -Signature: - -```typescript -attributes: Partial; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) > [attributes](./kibana-plugin-server.savedobjectsupdateresponse.attributes.md) + +## SavedObjectsUpdateResponse.attributes property + +Signature: + +```typescript +attributes: Partial; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.md index 0731ff5549bd44..64c90377353585 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) - -## SavedObjectsUpdateResponse interface - - -Signature: - -```typescript -export interface SavedObjectsUpdateResponse extends Omit, 'attributes' | 'references'> -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [attributes](./kibana-plugin-server.savedobjectsupdateresponse.attributes.md) | Partial<T> | | -| [references](./kibana-plugin-server.savedobjectsupdateresponse.references.md) | SavedObjectReference[] | undefined | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) + +## SavedObjectsUpdateResponse interface + + +Signature: + +```typescript +export interface SavedObjectsUpdateResponse extends Omit, 'attributes' | 'references'> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [attributes](./kibana-plugin-server.savedobjectsupdateresponse.attributes.md) | Partial<T> | | +| [references](./kibana-plugin-server.savedobjectsupdateresponse.references.md) | SavedObjectReference[] | undefined | | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.references.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.references.md index 26e33694b943c0..aa2aac98696e3f 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.references.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateresponse.references.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) > [references](./kibana-plugin-server.savedobjectsupdateresponse.references.md) - -## SavedObjectsUpdateResponse.references property - -Signature: - -```typescript -references: SavedObjectReference[] | undefined; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) > [references](./kibana-plugin-server.savedobjectsupdateresponse.references.md) + +## SavedObjectsUpdateResponse.references property + +Signature: + +```typescript +references: SavedObjectReference[] | undefined; +``` diff --git a/docs/development/core/server/kibana-plugin-server.scopeablerequest.md b/docs/development/core/server/kibana-plugin-server.scopeablerequest.md index 5a9443376996d1..d7d829e37d8056 100644 --- a/docs/development/core/server/kibana-plugin-server.scopeablerequest.md +++ b/docs/development/core/server/kibana-plugin-server.scopeablerequest.md @@ -1,15 +1,15 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopeableRequest](./kibana-plugin-server.scopeablerequest.md) - -## ScopeableRequest type - -A user credentials container. It accommodates the necessary auth credentials to impersonate the current user. - -See [KibanaRequest](./kibana-plugin-server.kibanarequest.md). - -Signature: - -```typescript -export declare type ScopeableRequest = KibanaRequest | LegacyRequest | FakeRequest; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopeableRequest](./kibana-plugin-server.scopeablerequest.md) + +## ScopeableRequest type + +A user credentials container. It accommodates the necessary auth credentials to impersonate the current user. + +See [KibanaRequest](./kibana-plugin-server.kibanarequest.md). + +Signature: + +```typescript +export declare type ScopeableRequest = KibanaRequest | LegacyRequest | FakeRequest; +``` diff --git a/docs/development/core/server/kibana-plugin-server.scopedclusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-server.scopedclusterclient._constructor_.md index c9f22356afc3c9..e592772a60e1c6 100644 --- a/docs/development/core/server/kibana-plugin-server.scopedclusterclient._constructor_.md +++ b/docs/development/core/server/kibana-plugin-server.scopedclusterclient._constructor_.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) > [(constructor)](./kibana-plugin-server.scopedclusterclient._constructor_.md) - -## ScopedClusterClient.(constructor) - -Constructs a new instance of the `ScopedClusterClient` class - -Signature: - -```typescript -constructor(internalAPICaller: APICaller, scopedAPICaller: APICaller, headers?: Headers | undefined); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| internalAPICaller | APICaller | | -| scopedAPICaller | APICaller | | -| headers | Headers | undefined | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) > [(constructor)](./kibana-plugin-server.scopedclusterclient._constructor_.md) + +## ScopedClusterClient.(constructor) + +Constructs a new instance of the `ScopedClusterClient` class + +Signature: + +```typescript +constructor(internalAPICaller: APICaller, scopedAPICaller: APICaller, headers?: Headers | undefined); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| internalAPICaller | APICaller | | +| scopedAPICaller | APICaller | | +| headers | Headers | undefined | | + diff --git a/docs/development/core/server/kibana-plugin-server.scopedclusterclient.callascurrentuser.md b/docs/development/core/server/kibana-plugin-server.scopedclusterclient.callascurrentuser.md index 1f532700421856..5af2f7ca79ccb0 100644 --- a/docs/development/core/server/kibana-plugin-server.scopedclusterclient.callascurrentuser.md +++ b/docs/development/core/server/kibana-plugin-server.scopedclusterclient.callascurrentuser.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) > [callAsCurrentUser](./kibana-plugin-server.scopedclusterclient.callascurrentuser.md) - -## ScopedClusterClient.callAsCurrentUser() method - -Calls specified `endpoint` with provided `clientParams` on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [APICaller](./kibana-plugin-server.apicaller.md). - -Signature: - -```typescript -callAsCurrentUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| endpoint | string | String descriptor of the endpoint e.g. cluster.getSettings or ping. | -| clientParams | Record<string, any> | A dictionary of parameters that will be passed directly to the Elasticsearch JS client. | -| options | CallAPIOptions | Options that affect the way we call the API and process the result. | - -Returns: - -`Promise` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) > [callAsCurrentUser](./kibana-plugin-server.scopedclusterclient.callascurrentuser.md) + +## ScopedClusterClient.callAsCurrentUser() method + +Calls specified `endpoint` with provided `clientParams` on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [APICaller](./kibana-plugin-server.apicaller.md). + +Signature: + +```typescript +callAsCurrentUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endpoint | string | String descriptor of the endpoint e.g. cluster.getSettings or ping. | +| clientParams | Record<string, any> | A dictionary of parameters that will be passed directly to the Elasticsearch JS client. | +| options | CallAPIOptions | Options that affect the way we call the API and process the result. | + +Returns: + +`Promise` + diff --git a/docs/development/core/server/kibana-plugin-server.scopedclusterclient.callasinternaluser.md b/docs/development/core/server/kibana-plugin-server.scopedclusterclient.callasinternaluser.md index 7249af7b429e4b..89d343338e7b57 100644 --- a/docs/development/core/server/kibana-plugin-server.scopedclusterclient.callasinternaluser.md +++ b/docs/development/core/server/kibana-plugin-server.scopedclusterclient.callasinternaluser.md @@ -1,26 +1,26 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) > [callAsInternalUser](./kibana-plugin-server.scopedclusterclient.callasinternaluser.md) - -## ScopedClusterClient.callAsInternalUser() method - -Calls specified `endpoint` with provided `clientParams` on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-server.apicaller.md). - -Signature: - -```typescript -callAsInternalUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| endpoint | string | String descriptor of the endpoint e.g. cluster.getSettings or ping. | -| clientParams | Record<string, any> | A dictionary of parameters that will be passed directly to the Elasticsearch JS client. | -| options | CallAPIOptions | Options that affect the way we call the API and process the result. | - -Returns: - -`Promise` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) > [callAsInternalUser](./kibana-plugin-server.scopedclusterclient.callasinternaluser.md) + +## ScopedClusterClient.callAsInternalUser() method + +Calls specified `endpoint` with provided `clientParams` on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-server.apicaller.md). + +Signature: + +```typescript +callAsInternalUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| endpoint | string | String descriptor of the endpoint e.g. cluster.getSettings or ping. | +| clientParams | Record<string, any> | A dictionary of parameters that will be passed directly to the Elasticsearch JS client. | +| options | CallAPIOptions | Options that affect the way we call the API and process the result. | + +Returns: + +`Promise` + diff --git a/docs/development/core/server/kibana-plugin-server.scopedclusterclient.md b/docs/development/core/server/kibana-plugin-server.scopedclusterclient.md index dcbf869bc93604..4c1854b61be850 100644 --- a/docs/development/core/server/kibana-plugin-server.scopedclusterclient.md +++ b/docs/development/core/server/kibana-plugin-server.scopedclusterclient.md @@ -1,29 +1,29 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) - -## ScopedClusterClient class - -Serves the same purpose as "normal" `ClusterClient` but exposes additional `callAsCurrentUser` method that doesn't use credentials of the Kibana internal user (as `callAsInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API. - -See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). - -Signature: - -```typescript -export declare class ScopedClusterClient implements IScopedClusterClient -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(internalAPICaller, scopedAPICaller, headers)](./kibana-plugin-server.scopedclusterclient._constructor_.md) | | Constructs a new instance of the ScopedClusterClient class | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [callAsCurrentUser(endpoint, clientParams, options)](./kibana-plugin-server.scopedclusterclient.callascurrentuser.md) | | Calls specified endpoint with provided clientParams on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [APICaller](./kibana-plugin-server.apicaller.md). | -| [callAsInternalUser(endpoint, clientParams, options)](./kibana-plugin-server.scopedclusterclient.callasinternaluser.md) | | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-server.apicaller.md). | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) + +## ScopedClusterClient class + +Serves the same purpose as "normal" `ClusterClient` but exposes additional `callAsCurrentUser` method that doesn't use credentials of the Kibana internal user (as `callAsInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API. + +See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). + +Signature: + +```typescript +export declare class ScopedClusterClient implements IScopedClusterClient +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(internalAPICaller, scopedAPICaller, headers)](./kibana-plugin-server.scopedclusterclient._constructor_.md) | | Constructs a new instance of the ScopedClusterClient class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [callAsCurrentUser(endpoint, clientParams, options)](./kibana-plugin-server.scopedclusterclient.callascurrentuser.md) | | Calls specified endpoint with provided clientParams on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [APICaller](./kibana-plugin-server.apicaller.md). | +| [callAsInternalUser(endpoint, clientParams, options)](./kibana-plugin-server.scopedclusterclient.callasinternaluser.md) | | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-server.apicaller.md). | + diff --git a/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.isvalid.md b/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.isvalid.md index 6e5f6acca2eb90..297bc4e5f3aee0 100644 --- a/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.isvalid.md +++ b/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.isvalid.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionCookieValidationResult](./kibana-plugin-server.sessioncookievalidationresult.md) > [isValid](./kibana-plugin-server.sessioncookievalidationresult.isvalid.md) - -## SessionCookieValidationResult.isValid property - -Whether the cookie is valid or not. - -Signature: - -```typescript -isValid: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionCookieValidationResult](./kibana-plugin-server.sessioncookievalidationresult.md) > [isValid](./kibana-plugin-server.sessioncookievalidationresult.isvalid.md) + +## SessionCookieValidationResult.isValid property + +Whether the cookie is valid or not. + +Signature: + +```typescript +isValid: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.md b/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.md index 6d32c4cca3dd6a..4dbeb5603c1557 100644 --- a/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.md +++ b/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionCookieValidationResult](./kibana-plugin-server.sessioncookievalidationresult.md) - -## SessionCookieValidationResult interface - -Return type from a function to validate cookie contents. - -Signature: - -```typescript -export interface SessionCookieValidationResult -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [isValid](./kibana-plugin-server.sessioncookievalidationresult.isvalid.md) | boolean | Whether the cookie is valid or not. | -| [path](./kibana-plugin-server.sessioncookievalidationresult.path.md) | string | The "Path" attribute of the cookie; if the cookie is invalid, this is used to clear it. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionCookieValidationResult](./kibana-plugin-server.sessioncookievalidationresult.md) + +## SessionCookieValidationResult interface + +Return type from a function to validate cookie contents. + +Signature: + +```typescript +export interface SessionCookieValidationResult +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [isValid](./kibana-plugin-server.sessioncookievalidationresult.isvalid.md) | boolean | Whether the cookie is valid or not. | +| [path](./kibana-plugin-server.sessioncookievalidationresult.path.md) | string | The "Path" attribute of the cookie; if the cookie is invalid, this is used to clear it. | + diff --git a/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.path.md b/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.path.md index 8ca6d452213aac..bab84448497866 100644 --- a/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.path.md +++ b/docs/development/core/server/kibana-plugin-server.sessioncookievalidationresult.path.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionCookieValidationResult](./kibana-plugin-server.sessioncookievalidationresult.md) > [path](./kibana-plugin-server.sessioncookievalidationresult.path.md) - -## SessionCookieValidationResult.path property - -The "Path" attribute of the cookie; if the cookie is invalid, this is used to clear it. - -Signature: - -```typescript -path?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionCookieValidationResult](./kibana-plugin-server.sessioncookievalidationresult.md) > [path](./kibana-plugin-server.sessioncookievalidationresult.path.md) + +## SessionCookieValidationResult.path property + +The "Path" attribute of the cookie; if the cookie is invalid, this is used to clear it. + +Signature: + +```typescript +path?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.sessionstorage.clear.md b/docs/development/core/server/kibana-plugin-server.sessionstorage.clear.md index 1f5813e181548f..cfb92812af94f3 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstorage.clear.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstorage.clear.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorage](./kibana-plugin-server.sessionstorage.md) > [clear](./kibana-plugin-server.sessionstorage.clear.md) - -## SessionStorage.clear() method - -Clears current session. - -Signature: - -```typescript -clear(): void; -``` -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorage](./kibana-plugin-server.sessionstorage.md) > [clear](./kibana-plugin-server.sessionstorage.clear.md) + +## SessionStorage.clear() method + +Clears current session. + +Signature: + +```typescript +clear(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.sessionstorage.get.md b/docs/development/core/server/kibana-plugin-server.sessionstorage.get.md index 26c63884ee71ac..d3459de75638d1 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstorage.get.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstorage.get.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorage](./kibana-plugin-server.sessionstorage.md) > [get](./kibana-plugin-server.sessionstorage.get.md) - -## SessionStorage.get() method - -Retrieves session value from the session storage. - -Signature: - -```typescript -get(): Promise; -``` -Returns: - -`Promise` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorage](./kibana-plugin-server.sessionstorage.md) > [get](./kibana-plugin-server.sessionstorage.get.md) + +## SessionStorage.get() method + +Retrieves session value from the session storage. + +Signature: + +```typescript +get(): Promise; +``` +Returns: + +`Promise` + diff --git a/docs/development/core/server/kibana-plugin-server.sessionstorage.md b/docs/development/core/server/kibana-plugin-server.sessionstorage.md index 02e48c1dd3dc4b..e7213570324367 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstorage.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstorage.md @@ -1,22 +1,22 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorage](./kibana-plugin-server.sessionstorage.md) - -## SessionStorage interface - -Provides an interface to store and retrieve data across requests. - -Signature: - -```typescript -export interface SessionStorage -``` - -## Methods - -| Method | Description | -| --- | --- | -| [clear()](./kibana-plugin-server.sessionstorage.clear.md) | Clears current session. | -| [get()](./kibana-plugin-server.sessionstorage.get.md) | Retrieves session value from the session storage. | -| [set(sessionValue)](./kibana-plugin-server.sessionstorage.set.md) | Puts current session value into the session storage. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorage](./kibana-plugin-server.sessionstorage.md) + +## SessionStorage interface + +Provides an interface to store and retrieve data across requests. + +Signature: + +```typescript +export interface SessionStorage +``` + +## Methods + +| Method | Description | +| --- | --- | +| [clear()](./kibana-plugin-server.sessionstorage.clear.md) | Clears current session. | +| [get()](./kibana-plugin-server.sessionstorage.get.md) | Retrieves session value from the session storage. | +| [set(sessionValue)](./kibana-plugin-server.sessionstorage.set.md) | Puts current session value into the session storage. | + diff --git a/docs/development/core/server/kibana-plugin-server.sessionstorage.set.md b/docs/development/core/server/kibana-plugin-server.sessionstorage.set.md index 7e3a2a4361244d..40d1c373d2a715 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstorage.set.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstorage.set.md @@ -1,24 +1,24 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorage](./kibana-plugin-server.sessionstorage.md) > [set](./kibana-plugin-server.sessionstorage.set.md) - -## SessionStorage.set() method - -Puts current session value into the session storage. - -Signature: - -```typescript -set(sessionValue: T): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| sessionValue | T | value to put | - -Returns: - -`void` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorage](./kibana-plugin-server.sessionstorage.md) > [set](./kibana-plugin-server.sessionstorage.set.md) + +## SessionStorage.set() method + +Puts current session value into the session storage. + +Signature: + +```typescript +set(sessionValue: T): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| sessionValue | T | value to put | + +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.encryptionkey.md b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.encryptionkey.md index ef65735e7bdbab..ddaa0adff3570b 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.encryptionkey.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.encryptionkey.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) > [encryptionKey](./kibana-plugin-server.sessionstoragecookieoptions.encryptionkey.md) - -## SessionStorageCookieOptions.encryptionKey property - -A key used to encrypt a cookie's value. Should be at least 32 characters long. - -Signature: - -```typescript -encryptionKey: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) > [encryptionKey](./kibana-plugin-server.sessionstoragecookieoptions.encryptionkey.md) + +## SessionStorageCookieOptions.encryptionKey property + +A key used to encrypt a cookie's value. Should be at least 32 characters long. + +Signature: + +```typescript +encryptionKey: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.issecure.md b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.issecure.md index 824fc9d136a3ff..7153bc0730926f 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.issecure.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.issecure.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) > [isSecure](./kibana-plugin-server.sessionstoragecookieoptions.issecure.md) - -## SessionStorageCookieOptions.isSecure property - -Flag indicating whether the cookie should be sent only via a secure connection. - -Signature: - -```typescript -isSecure: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) > [isSecure](./kibana-plugin-server.sessionstoragecookieoptions.issecure.md) + +## SessionStorageCookieOptions.isSecure property + +Flag indicating whether the cookie should be sent only via a secure connection. + +Signature: + +```typescript +isSecure: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.md b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.md index 778dc27a190d91..6b058864a4d9c2 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.md @@ -1,23 +1,23 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) - -## SessionStorageCookieOptions interface - -Configuration used to create HTTP session storage based on top of cookie mechanism. - -Signature: - -```typescript -export interface SessionStorageCookieOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [encryptionKey](./kibana-plugin-server.sessionstoragecookieoptions.encryptionkey.md) | string | A key used to encrypt a cookie's value. Should be at least 32 characters long. | -| [isSecure](./kibana-plugin-server.sessionstoragecookieoptions.issecure.md) | boolean | Flag indicating whether the cookie should be sent only via a secure connection. | -| [name](./kibana-plugin-server.sessionstoragecookieoptions.name.md) | string | Name of the session cookie. | -| [validate](./kibana-plugin-server.sessionstoragecookieoptions.validate.md) | (sessionValue: T | T[]) => SessionCookieValidationResult | Function called to validate a cookie's decrypted value. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) + +## SessionStorageCookieOptions interface + +Configuration used to create HTTP session storage based on top of cookie mechanism. + +Signature: + +```typescript +export interface SessionStorageCookieOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [encryptionKey](./kibana-plugin-server.sessionstoragecookieoptions.encryptionkey.md) | string | A key used to encrypt a cookie's value. Should be at least 32 characters long. | +| [isSecure](./kibana-plugin-server.sessionstoragecookieoptions.issecure.md) | boolean | Flag indicating whether the cookie should be sent only via a secure connection. | +| [name](./kibana-plugin-server.sessionstoragecookieoptions.name.md) | string | Name of the session cookie. | +| [validate](./kibana-plugin-server.sessionstoragecookieoptions.validate.md) | (sessionValue: T | T[]) => SessionCookieValidationResult | Function called to validate a cookie's decrypted value. | + diff --git a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.name.md b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.name.md index e6bc7ea3fe00f1..673f3c4f2d4229 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.name.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.name.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) > [name](./kibana-plugin-server.sessionstoragecookieoptions.name.md) - -## SessionStorageCookieOptions.name property - -Name of the session cookie. - -Signature: - -```typescript -name: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) > [name](./kibana-plugin-server.sessionstoragecookieoptions.name.md) + +## SessionStorageCookieOptions.name property + +Name of the session cookie. + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.validate.md b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.validate.md index effa4b6bbc077c..e59f4d910305ef 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.validate.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstoragecookieoptions.validate.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) > [validate](./kibana-plugin-server.sessionstoragecookieoptions.validate.md) - -## SessionStorageCookieOptions.validate property - -Function called to validate a cookie's decrypted value. - -Signature: - -```typescript -validate: (sessionValue: T | T[]) => SessionCookieValidationResult; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageCookieOptions](./kibana-plugin-server.sessionstoragecookieoptions.md) > [validate](./kibana-plugin-server.sessionstoragecookieoptions.validate.md) + +## SessionStorageCookieOptions.validate property + +Function called to validate a cookie's decrypted value. + +Signature: + +```typescript +validate: (sessionValue: T | T[]) => SessionCookieValidationResult; +``` diff --git a/docs/development/core/server/kibana-plugin-server.sessionstoragefactory.asscoped.md b/docs/development/core/server/kibana-plugin-server.sessionstoragefactory.asscoped.md index fcc5b90e2dd0cc..4a42a52e56bd0c 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstoragefactory.asscoped.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstoragefactory.asscoped.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) > [asScoped](./kibana-plugin-server.sessionstoragefactory.asscoped.md) - -## SessionStorageFactory.asScoped property - -Signature: - -```typescript -asScoped: (request: KibanaRequest) => SessionStorage; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) > [asScoped](./kibana-plugin-server.sessionstoragefactory.asscoped.md) + +## SessionStorageFactory.asScoped property + +Signature: + +```typescript +asScoped: (request: KibanaRequest) => SessionStorage; +``` diff --git a/docs/development/core/server/kibana-plugin-server.sessionstoragefactory.md b/docs/development/core/server/kibana-plugin-server.sessionstoragefactory.md index eb559005575b1b..a5b4ebdf5b8cd2 100644 --- a/docs/development/core/server/kibana-plugin-server.sessionstoragefactory.md +++ b/docs/development/core/server/kibana-plugin-server.sessionstoragefactory.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) - -## SessionStorageFactory interface - -SessionStorage factory to bind one to an incoming request - -Signature: - -```typescript -export interface SessionStorageFactory -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [asScoped](./kibana-plugin-server.sessionstoragefactory.asscoped.md) | (request: KibanaRequest) => SessionStorage<T> | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) + +## SessionStorageFactory interface + +SessionStorage factory to bind one to an incoming request + +Signature: + +```typescript +export interface SessionStorageFactory +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [asScoped](./kibana-plugin-server.sessionstoragefactory.asscoped.md) | (request: KibanaRequest) => SessionStorage<T> | | + diff --git a/docs/development/core/server/kibana-plugin-server.sharedglobalconfig.md b/docs/development/core/server/kibana-plugin-server.sharedglobalconfig.md index 418d406d4c8905..f5329824ad7f6c 100644 --- a/docs/development/core/server/kibana-plugin-server.sharedglobalconfig.md +++ b/docs/development/core/server/kibana-plugin-server.sharedglobalconfig.md @@ -1,16 +1,16 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SharedGlobalConfig](./kibana-plugin-server.sharedglobalconfig.md) - -## SharedGlobalConfig type - - -Signature: - -```typescript -export declare type SharedGlobalConfig = RecursiveReadonly<{ - kibana: Pick; - elasticsearch: Pick; - path: Pick; -}>; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SharedGlobalConfig](./kibana-plugin-server.sharedglobalconfig.md) + +## SharedGlobalConfig type + + +Signature: + +```typescript +export declare type SharedGlobalConfig = RecursiveReadonly<{ + kibana: Pick; + elasticsearch: Pick; + path: Pick; +}>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidation.md b/docs/development/core/server/kibana-plugin-server.stringvalidation.md index cc52c853ce2489..7da69b141d82c7 100644 --- a/docs/development/core/server/kibana-plugin-server.stringvalidation.md +++ b/docs/development/core/server/kibana-plugin-server.stringvalidation.md @@ -1,19 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidation](./kibana-plugin-server.stringvalidation.md) - -## StringValidation interface - -Signature: - -```typescript -export interface StringValidation -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [message](./kibana-plugin-server.stringvalidation.message.md) | string | | -| [regexString](./kibana-plugin-server.stringvalidation.regexstring.md) | string | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidation](./kibana-plugin-server.stringvalidation.md) + +## StringValidation type + +Allows regex objects or a regex string + +Signature: + +```typescript +export declare type StringValidation = StringValidationRegex | StringValidationRegexString; +``` diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidation.message.md b/docs/development/core/server/kibana-plugin-server.stringvalidation.message.md deleted file mode 100644 index a15fe8b9314039..00000000000000 --- a/docs/development/core/server/kibana-plugin-server.stringvalidation.message.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidation](./kibana-plugin-server.stringvalidation.md) > [message](./kibana-plugin-server.stringvalidation.message.md) - -## StringValidation.message property - -Signature: - -```typescript -message: string; -``` diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidation.regexstring.md b/docs/development/core/server/kibana-plugin-server.stringvalidation.regexstring.md deleted file mode 100644 index e19560237f77de..00000000000000 --- a/docs/development/core/server/kibana-plugin-server.stringvalidation.regexstring.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidation](./kibana-plugin-server.stringvalidation.md) > [regexString](./kibana-plugin-server.stringvalidation.regexstring.md) - -## StringValidation.regexString property - -Signature: - -```typescript -regexString: string; -``` diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidationregex.md b/docs/development/core/server/kibana-plugin-server.stringvalidationregex.md new file mode 100644 index 00000000000000..b082978c4ee654 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.stringvalidationregex.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidationRegex](./kibana-plugin-server.stringvalidationregex.md) + +## StringValidationRegex interface + +StringValidation with regex object + +Signature: + +```typescript +export interface StringValidationRegex +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [message](./kibana-plugin-server.stringvalidationregex.message.md) | string | | +| [regex](./kibana-plugin-server.stringvalidationregex.regex.md) | RegExp | | + diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidationregex.message.md b/docs/development/core/server/kibana-plugin-server.stringvalidationregex.message.md new file mode 100644 index 00000000000000..66197813b2be47 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.stringvalidationregex.message.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidationRegex](./kibana-plugin-server.stringvalidationregex.md) > [message](./kibana-plugin-server.stringvalidationregex.message.md) + +## StringValidationRegex.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidationregex.regex.md b/docs/development/core/server/kibana-plugin-server.stringvalidationregex.regex.md new file mode 100644 index 00000000000000..4e295791454f9d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.stringvalidationregex.regex.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidationRegex](./kibana-plugin-server.stringvalidationregex.md) > [regex](./kibana-plugin-server.stringvalidationregex.regex.md) + +## StringValidationRegex.regex property + +Signature: + +```typescript +regex: RegExp; +``` diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.md b/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.md new file mode 100644 index 00000000000000..6bd23b999a7c3b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidationRegexString](./kibana-plugin-server.stringvalidationregexstring.md) + +## StringValidationRegexString interface + +StringValidation as regex string + +Signature: + +```typescript +export interface StringValidationRegexString +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [message](./kibana-plugin-server.stringvalidationregexstring.message.md) | string | | +| [regexString](./kibana-plugin-server.stringvalidationregexstring.regexstring.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.message.md b/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.message.md new file mode 100644 index 00000000000000..96d1f1980eff9e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.message.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidationRegexString](./kibana-plugin-server.stringvalidationregexstring.md) > [message](./kibana-plugin-server.stringvalidationregexstring.message.md) + +## StringValidationRegexString.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.regexstring.md b/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.regexstring.md new file mode 100644 index 00000000000000..61a0d53dcc511e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.stringvalidationregexstring.regexstring.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [StringValidationRegexString](./kibana-plugin-server.stringvalidationregexstring.md) > [regexString](./kibana-plugin-server.stringvalidationregexstring.regexstring.md) + +## StringValidationRegexString.regexString property + +Signature: + +```typescript +regexString: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.category.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.category.md index 6bf1b17dc947a4..3754bc01103d6f 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.category.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.category.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [category](./kibana-plugin-server.uisettingsparams.category.md) - -## UiSettingsParams.category property - -used to group the configured setting in the UI - -Signature: - -```typescript -category?: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [category](./kibana-plugin-server.uisettingsparams.category.md) + +## UiSettingsParams.category property + +used to group the configured setting in the UI + +Signature: + +```typescript +category?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.deprecation.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.deprecation.md index 7ad26b85bf81c8..4581f098642261 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.deprecation.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.deprecation.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [deprecation](./kibana-plugin-server.uisettingsparams.deprecation.md) - -## UiSettingsParams.deprecation property - -optional deprecation information. Used to generate a deprecation warning. - -Signature: - -```typescript -deprecation?: DeprecationSettings; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [deprecation](./kibana-plugin-server.uisettingsparams.deprecation.md) + +## UiSettingsParams.deprecation property + +optional deprecation information. Used to generate a deprecation warning. + +Signature: + +```typescript +deprecation?: DeprecationSettings; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.description.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.description.md index 6a203629f5425c..783c8ddde1d5ec 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.description.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.description.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [description](./kibana-plugin-server.uisettingsparams.description.md) - -## UiSettingsParams.description property - -description provided to a user in UI - -Signature: - -```typescript -description?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [description](./kibana-plugin-server.uisettingsparams.description.md) + +## UiSettingsParams.description property + +description provided to a user in UI + +Signature: + +```typescript +description?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.md index fc2f8038f973fa..3e20f4744ee511 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.md @@ -1,30 +1,30 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) - -## UiSettingsParams interface - -UiSettings parameters defined by the plugins. - -Signature: - -```typescript -export interface UiSettingsParams -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [category](./kibana-plugin-server.uisettingsparams.category.md) | string[] | used to group the configured setting in the UI | -| [deprecation](./kibana-plugin-server.uisettingsparams.deprecation.md) | DeprecationSettings | optional deprecation information. Used to generate a deprecation warning. | -| [description](./kibana-plugin-server.uisettingsparams.description.md) | string | description provided to a user in UI | -| [name](./kibana-plugin-server.uisettingsparams.name.md) | string | title in the UI | -| [optionLabels](./kibana-plugin-server.uisettingsparams.optionlabels.md) | Record<string, string> | text labels for 'select' type UI element | -| [options](./kibana-plugin-server.uisettingsparams.options.md) | string[] | array of permitted values for this setting | -| [readonly](./kibana-plugin-server.uisettingsparams.readonly.md) | boolean | a flag indicating that value cannot be changed | -| [requiresPageReload](./kibana-plugin-server.uisettingsparams.requirespagereload.md) | boolean | a flag indicating whether new value applying requires page reloading | -| [type](./kibana-plugin-server.uisettingsparams.type.md) | UiSettingsType | defines a type of UI element [UiSettingsType](./kibana-plugin-server.uisettingstype.md) | -| [validation](./kibana-plugin-server.uisettingsparams.validation.md) | ImageValidation | StringValidation | | -| [value](./kibana-plugin-server.uisettingsparams.value.md) | SavedObjectAttribute | default value to fall back to if a user doesn't provide any | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) + +## UiSettingsParams interface + +UiSettings parameters defined by the plugins. + +Signature: + +```typescript +export interface UiSettingsParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [category](./kibana-plugin-server.uisettingsparams.category.md) | string[] | used to group the configured setting in the UI | +| [deprecation](./kibana-plugin-server.uisettingsparams.deprecation.md) | DeprecationSettings | optional deprecation information. Used to generate a deprecation warning. | +| [description](./kibana-plugin-server.uisettingsparams.description.md) | string | description provided to a user in UI | +| [name](./kibana-plugin-server.uisettingsparams.name.md) | string | title in the UI | +| [optionLabels](./kibana-plugin-server.uisettingsparams.optionlabels.md) | Record<string, string> | text labels for 'select' type UI element | +| [options](./kibana-plugin-server.uisettingsparams.options.md) | string[] | array of permitted values for this setting | +| [readonly](./kibana-plugin-server.uisettingsparams.readonly.md) | boolean | a flag indicating that value cannot be changed | +| [requiresPageReload](./kibana-plugin-server.uisettingsparams.requirespagereload.md) | boolean | a flag indicating whether new value applying requires page reloading | +| [type](./kibana-plugin-server.uisettingsparams.type.md) | UiSettingsType | defines a type of UI element [UiSettingsType](./kibana-plugin-server.uisettingstype.md) | +| [validation](./kibana-plugin-server.uisettingsparams.validation.md) | ImageValidation | StringValidation | | +| [value](./kibana-plugin-server.uisettingsparams.value.md) | SavedObjectAttribute | default value to fall back to if a user doesn't provide any | + diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.name.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.name.md index 07905ca7de20af..f445d970fe0b2b 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.name.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.name.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [name](./kibana-plugin-server.uisettingsparams.name.md) - -## UiSettingsParams.name property - -title in the UI - -Signature: - -```typescript -name?: string; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [name](./kibana-plugin-server.uisettingsparams.name.md) + +## UiSettingsParams.name property + +title in the UI + +Signature: + +```typescript +name?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.optionlabels.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.optionlabels.md index cb0e196fdcaccb..7f970cfd474fc6 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.optionlabels.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.optionlabels.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [optionLabels](./kibana-plugin-server.uisettingsparams.optionlabels.md) - -## UiSettingsParams.optionLabels property - -text labels for 'select' type UI element - -Signature: - -```typescript -optionLabels?: Record; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [optionLabels](./kibana-plugin-server.uisettingsparams.optionlabels.md) + +## UiSettingsParams.optionLabels property + +text labels for 'select' type UI element + +Signature: + +```typescript +optionLabels?: Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.options.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.options.md index 2220feab74ffde..d25043623a6da6 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.options.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.options.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [options](./kibana-plugin-server.uisettingsparams.options.md) - -## UiSettingsParams.options property - -array of permitted values for this setting - -Signature: - -```typescript -options?: string[]; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [options](./kibana-plugin-server.uisettingsparams.options.md) + +## UiSettingsParams.options property + +array of permitted values for this setting + +Signature: + +```typescript +options?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.readonly.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.readonly.md index faec4d6eadbccf..276b965ec128a8 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.readonly.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.readonly.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [readonly](./kibana-plugin-server.uisettingsparams.readonly.md) - -## UiSettingsParams.readonly property - -a flag indicating that value cannot be changed - -Signature: - -```typescript -readonly?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [readonly](./kibana-plugin-server.uisettingsparams.readonly.md) + +## UiSettingsParams.readonly property + +a flag indicating that value cannot be changed + +Signature: + +```typescript +readonly?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.requirespagereload.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.requirespagereload.md index 224b3695224b96..7d6ce9ef8b2330 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.requirespagereload.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.requirespagereload.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [requiresPageReload](./kibana-plugin-server.uisettingsparams.requirespagereload.md) - -## UiSettingsParams.requiresPageReload property - -a flag indicating whether new value applying requires page reloading - -Signature: - -```typescript -requiresPageReload?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [requiresPageReload](./kibana-plugin-server.uisettingsparams.requirespagereload.md) + +## UiSettingsParams.requiresPageReload property + +a flag indicating whether new value applying requires page reloading + +Signature: + +```typescript +requiresPageReload?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.type.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.type.md index ccf2d67b2dffbb..b66483cf4624a4 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.type.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.type.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [type](./kibana-plugin-server.uisettingsparams.type.md) - -## UiSettingsParams.type property - -defines a type of UI element [UiSettingsType](./kibana-plugin-server.uisettingstype.md) - -Signature: - -```typescript -type?: UiSettingsType; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [type](./kibana-plugin-server.uisettingsparams.type.md) + +## UiSettingsParams.type property + +defines a type of UI element [UiSettingsType](./kibana-plugin-server.uisettingstype.md) + +Signature: + +```typescript +type?: UiSettingsType; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.validation.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.validation.md index f097f36e999ba8..ee0a9d6c865408 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.validation.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.validation.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [validation](./kibana-plugin-server.uisettingsparams.validation.md) - -## UiSettingsParams.validation property - -Signature: - -```typescript -validation?: ImageValidation | StringValidation; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [validation](./kibana-plugin-server.uisettingsparams.validation.md) + +## UiSettingsParams.validation property + +Signature: + +```typescript +validation?: ImageValidation | StringValidation; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.value.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.value.md index 397498ccf5c111..256d72b2cbf2f7 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.value.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.value.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [value](./kibana-plugin-server.uisettingsparams.value.md) - -## UiSettingsParams.value property - -default value to fall back to if a user doesn't provide any - -Signature: - -```typescript -value?: SavedObjectAttribute; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [value](./kibana-plugin-server.uisettingsparams.value.md) + +## UiSettingsParams.value property + +default value to fall back to if a user doesn't provide any + +Signature: + +```typescript +value?: SavedObjectAttribute; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.md b/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.md index 8dde78f633d883..78f5c2a7dd03a6 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) - -## UiSettingsServiceSetup interface - - -Signature: - -```typescript -export interface UiSettingsServiceSetup -``` - -## Methods - -| Method | Description | -| --- | --- | -| [register(settings)](./kibana-plugin-server.uisettingsservicesetup.register.md) | Sets settings with default values for the uiSettings. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) + +## UiSettingsServiceSetup interface + + +Signature: + +```typescript +export interface UiSettingsServiceSetup +``` + +## Methods + +| Method | Description | +| --- | --- | +| [register(settings)](./kibana-plugin-server.uisettingsservicesetup.register.md) | Sets settings with default values for the uiSettings. | + diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.register.md b/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.register.md index 0047b5275408ed..366888ed2ce18f 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.register.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.register.md @@ -1,40 +1,40 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) > [register](./kibana-plugin-server.uisettingsservicesetup.register.md) - -## UiSettingsServiceSetup.register() method - -Sets settings with default values for the uiSettings. - -Signature: - -```typescript -register(settings: Record): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| settings | Record<string, UiSettingsParams> | | - -Returns: - -`void` - -## Example - - -```ts -setup(core: CoreSetup){ - core.uiSettings.register([{ - foo: { - name: i18n.translate('my foo settings'), - value: true, - description: 'add some awesomeness', - }, - }]); -} - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsServiceSetup](./kibana-plugin-server.uisettingsservicesetup.md) > [register](./kibana-plugin-server.uisettingsservicesetup.register.md) + +## UiSettingsServiceSetup.register() method + +Sets settings with default values for the uiSettings. + +Signature: + +```typescript +register(settings: Record): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| settings | Record<string, UiSettingsParams> | | + +Returns: + +`void` + +## Example + + +```ts +setup(core: CoreSetup){ + core.uiSettings.register([{ + foo: { + name: i18n.translate('my foo settings'), + value: true, + description: 'add some awesomeness', + }, + }]); +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsservicestart.asscopedtoclient.md b/docs/development/core/server/kibana-plugin-server.uisettingsservicestart.asscopedtoclient.md index 072dd39faa0845..9e202d15a1bebc 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsservicestart.asscopedtoclient.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsservicestart.asscopedtoclient.md @@ -1,37 +1,37 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) > [asScopedToClient](./kibana-plugin-server.uisettingsservicestart.asscopedtoclient.md) - -## UiSettingsServiceStart.asScopedToClient() method - -Creates a [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) with provided \*scoped\* saved objects client. - -This should only be used in the specific case where the client needs to be accessed from outside of the scope of a [RequestHandler](./kibana-plugin-server.requesthandler.md). - -Signature: - -```typescript -asScopedToClient(savedObjectsClient: SavedObjectsClientContract): IUiSettingsClient; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| savedObjectsClient | SavedObjectsClientContract | | - -Returns: - -`IUiSettingsClient` - -## Example - - -```ts -start(core: CoreStart) { - const soClient = core.savedObjects.getScopedClient(arbitraryRequest); - const uiSettingsClient = core.uiSettings.asScopedToClient(soClient); -} - -``` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) > [asScopedToClient](./kibana-plugin-server.uisettingsservicestart.asscopedtoclient.md) + +## UiSettingsServiceStart.asScopedToClient() method + +Creates a [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) with provided \*scoped\* saved objects client. + +This should only be used in the specific case where the client needs to be accessed from outside of the scope of a [RequestHandler](./kibana-plugin-server.requesthandler.md). + +Signature: + +```typescript +asScopedToClient(savedObjectsClient: SavedObjectsClientContract): IUiSettingsClient; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| savedObjectsClient | SavedObjectsClientContract | | + +Returns: + +`IUiSettingsClient` + +## Example + + +```ts +start(core: CoreStart) { + const soClient = core.savedObjects.getScopedClient(arbitraryRequest); + const uiSettingsClient = core.uiSettings.asScopedToClient(soClient); +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsservicestart.md b/docs/development/core/server/kibana-plugin-server.uisettingsservicestart.md index ee3563552275a6..e4375303a1b3d4 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingsservicestart.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingsservicestart.md @@ -1,19 +1,19 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) - -## UiSettingsServiceStart interface - - -Signature: - -```typescript -export interface UiSettingsServiceStart -``` - -## Methods - -| Method | Description | -| --- | --- | -| [asScopedToClient(savedObjectsClient)](./kibana-plugin-server.uisettingsservicestart.asscopedtoclient.md) | Creates a [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) with provided \*scoped\* saved objects client.This should only be used in the specific case where the client needs to be accessed from outside of the scope of a [RequestHandler](./kibana-plugin-server.requesthandler.md). | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsServiceStart](./kibana-plugin-server.uisettingsservicestart.md) + +## UiSettingsServiceStart interface + + +Signature: + +```typescript +export interface UiSettingsServiceStart +``` + +## Methods + +| Method | Description | +| --- | --- | +| [asScopedToClient(savedObjectsClient)](./kibana-plugin-server.uisettingsservicestart.asscopedtoclient.md) | Creates a [IUiSettingsClient](./kibana-plugin-server.iuisettingsclient.md) with provided \*scoped\* saved objects client.This should only be used in the specific case where the client needs to be accessed from outside of the scope of a [RequestHandler](./kibana-plugin-server.requesthandler.md). | + diff --git a/docs/development/core/server/kibana-plugin-server.uisettingstype.md b/docs/development/core/server/kibana-plugin-server.uisettingstype.md index 789d4d5788468e..09fb43e974d9b8 100644 --- a/docs/development/core/server/kibana-plugin-server.uisettingstype.md +++ b/docs/development/core/server/kibana-plugin-server.uisettingstype.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsType](./kibana-plugin-server.uisettingstype.md) - -## UiSettingsType type - -UI element type to represent the settings. - -Signature: - -```typescript -export declare type UiSettingsType = 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string'; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsType](./kibana-plugin-server.uisettingstype.md) + +## UiSettingsType type + +UI element type to represent the settings. + +Signature: + +```typescript +export declare type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string' | 'array' | 'image'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.userprovidedvalues.isoverridden.md b/docs/development/core/server/kibana-plugin-server.userprovidedvalues.isoverridden.md index 01e04b490595d5..304999f911fa44 100644 --- a/docs/development/core/server/kibana-plugin-server.userprovidedvalues.isoverridden.md +++ b/docs/development/core/server/kibana-plugin-server.userprovidedvalues.isoverridden.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UserProvidedValues](./kibana-plugin-server.userprovidedvalues.md) > [isOverridden](./kibana-plugin-server.userprovidedvalues.isoverridden.md) - -## UserProvidedValues.isOverridden property - -Signature: - -```typescript -isOverridden?: boolean; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UserProvidedValues](./kibana-plugin-server.userprovidedvalues.md) > [isOverridden](./kibana-plugin-server.userprovidedvalues.isoverridden.md) + +## UserProvidedValues.isOverridden property + +Signature: + +```typescript +isOverridden?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.userprovidedvalues.md b/docs/development/core/server/kibana-plugin-server.userprovidedvalues.md index e0f5f7fadd12f4..e00672070bba81 100644 --- a/docs/development/core/server/kibana-plugin-server.userprovidedvalues.md +++ b/docs/development/core/server/kibana-plugin-server.userprovidedvalues.md @@ -1,21 +1,21 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UserProvidedValues](./kibana-plugin-server.userprovidedvalues.md) - -## UserProvidedValues interface - -Describes the values explicitly set by user. - -Signature: - -```typescript -export interface UserProvidedValues -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [isOverridden](./kibana-plugin-server.userprovidedvalues.isoverridden.md) | boolean | | -| [userValue](./kibana-plugin-server.userprovidedvalues.uservalue.md) | T | | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UserProvidedValues](./kibana-plugin-server.userprovidedvalues.md) + +## UserProvidedValues interface + +Describes the values explicitly set by user. + +Signature: + +```typescript +export interface UserProvidedValues +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [isOverridden](./kibana-plugin-server.userprovidedvalues.isoverridden.md) | boolean | | +| [userValue](./kibana-plugin-server.userprovidedvalues.uservalue.md) | T | | + diff --git a/docs/development/core/server/kibana-plugin-server.userprovidedvalues.uservalue.md b/docs/development/core/server/kibana-plugin-server.userprovidedvalues.uservalue.md index 59d25651b7697d..c45efa92968318 100644 --- a/docs/development/core/server/kibana-plugin-server.userprovidedvalues.uservalue.md +++ b/docs/development/core/server/kibana-plugin-server.userprovidedvalues.uservalue.md @@ -1,11 +1,11 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UserProvidedValues](./kibana-plugin-server.userprovidedvalues.md) > [userValue](./kibana-plugin-server.userprovidedvalues.uservalue.md) - -## UserProvidedValues.userValue property - -Signature: - -```typescript -userValue?: T; -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UserProvidedValues](./kibana-plugin-server.userprovidedvalues.md) > [userValue](./kibana-plugin-server.userprovidedvalues.uservalue.md) + +## UserProvidedValues.userValue property + +Signature: + +```typescript +userValue?: T; +``` diff --git a/docs/development/core/server/kibana-plugin-server.uuidservicesetup.getinstanceuuid.md b/docs/development/core/server/kibana-plugin-server.uuidservicesetup.getinstanceuuid.md index e0b7012bea4aa1..c937b49f08e745 100644 --- a/docs/development/core/server/kibana-plugin-server.uuidservicesetup.getinstanceuuid.md +++ b/docs/development/core/server/kibana-plugin-server.uuidservicesetup.getinstanceuuid.md @@ -1,17 +1,17 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) > [getInstanceUuid](./kibana-plugin-server.uuidservicesetup.getinstanceuuid.md) - -## UuidServiceSetup.getInstanceUuid() method - -Retrieve the Kibana instance uuid. - -Signature: - -```typescript -getInstanceUuid(): string; -``` -Returns: - -`string` - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) > [getInstanceUuid](./kibana-plugin-server.uuidservicesetup.getinstanceuuid.md) + +## UuidServiceSetup.getInstanceUuid() method + +Retrieve the Kibana instance uuid. + +Signature: + +```typescript +getInstanceUuid(): string; +``` +Returns: + +`string` + diff --git a/docs/development/core/server/kibana-plugin-server.uuidservicesetup.md b/docs/development/core/server/kibana-plugin-server.uuidservicesetup.md index f2a6cfdeac7045..fa319779e01d52 100644 --- a/docs/development/core/server/kibana-plugin-server.uuidservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.uuidservicesetup.md @@ -1,20 +1,20 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) - -## UuidServiceSetup interface - -APIs to access the application's instance uuid. - -Signature: - -```typescript -export interface UuidServiceSetup -``` - -## Methods - -| Method | Description | -| --- | --- | -| [getInstanceUuid()](./kibana-plugin-server.uuidservicesetup.getinstanceuuid.md) | Retrieve the Kibana instance uuid. | - + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UuidServiceSetup](./kibana-plugin-server.uuidservicesetup.md) + +## UuidServiceSetup interface + +APIs to access the application's instance uuid. + +Signature: + +```typescript +export interface UuidServiceSetup +``` + +## Methods + +| Method | Description | +| --- | --- | +| [getInstanceUuid()](./kibana-plugin-server.uuidservicesetup.getinstanceuuid.md) | Retrieve the Kibana instance uuid. | + diff --git a/docs/development/core/server/kibana-plugin-server.validbodyoutput.md b/docs/development/core/server/kibana-plugin-server.validbodyoutput.md index ea866abf887fb8..2230fcc988d762 100644 --- a/docs/development/core/server/kibana-plugin-server.validbodyoutput.md +++ b/docs/development/core/server/kibana-plugin-server.validbodyoutput.md @@ -1,13 +1,13 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [validBodyOutput](./kibana-plugin-server.validbodyoutput.md) - -## validBodyOutput variable - -The set of valid body.output - -Signature: - -```typescript -validBodyOutput: readonly ["data", "stream"] -``` + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [validBodyOutput](./kibana-plugin-server.validbodyoutput.md) + +## validBodyOutput variable + +The set of valid body.output + +Signature: + +```typescript +validBodyOutput: readonly ["data", "stream"] +``` diff --git a/docs/images/Dashboard_add_new_visualization.png b/docs/images/Dashboard_add_new_visualization.png new file mode 100644 index 00000000000000..b871131805ab53 Binary files /dev/null and b/docs/images/Dashboard_add_new_visualization.png differ diff --git a/docs/images/management-index-templates-mappings.png b/docs/images/management-index-templates-mappings.png new file mode 100755 index 00000000000000..62321fc0e46660 Binary files /dev/null and b/docs/images/management-index-templates-mappings.png differ diff --git a/docs/management/managing-indices.asciidoc b/docs/management/managing-indices.asciidoc index 4c7f6c2aee6e6f..7a3480c860b16f 100644 --- a/docs/management/managing-indices.asciidoc +++ b/docs/management/managing-indices.asciidoc @@ -5,43 +5,43 @@ *Index Management* enables you to view index settings, mappings, and statistics and perform index-level operations. These include refreshing, flushing, clearing the cache, force merging segments, -freezing indices, and more. Practicing good index management helps ensure +freezing indices, and more. Practicing good index management helps ensure that your data is stored in the most cost-effective way possible. -*Index Management* also helps you create index templates. A template reduces -the amount of bookkeeping when working with indices. Instead of manually -setting up your indices, you can create them automatically from a template, +*Index Management* also helps you create index templates. A template reduces +the amount of bookkeeping when working with indices. Instead of manually +setting up your indices, you can create them automatically from a template, ensuring that your settings, mappings, and aliases are consistently defined. -To manage your indices, go to *Management > {es} > Index Management*. +To manage your indices, go to *Management > {es} > Index Management*. [role="screenshot"] image::images/management_index_labels.png[Index Management UI] If security is enabled, -you must have the `monitor` cluster privilege and the `view_index_metadata` -and `manage` index privileges to view the data. +you must have the `monitor` cluster privilege and the `view_index_metadata` +and `manage` index privileges to view the data. For index templates, you must have the `manage_index_templates` cluster privilege. See {ref}/security-privileges.html[Security privileges] for more information. -Before using this feature, you should be familiar with index management +Before using this feature, you should be familiar with index management operations. Refer to the {ref}/indices.html[index management APIs] and the {ref}/indices-templates.html[index template APIs]. [float] === View and edit indices -When you open *Index Management*, you’re presented an overview of your configured indices. -Badges indicate if an index is {ref}/frozen-indices.html[frozen], -a {ref}/ccr-put-follow.html[follower index], -or a {ref}/rollup-get-rollup-index-caps.html[rollup index]. +When you open *Index Management*, you’re presented an overview of your configured indices. +Badges indicate if an index is {ref}/frozen-indices.html[frozen], +a {ref}/ccr-put-follow.html[follower index], +or a {ref}/rollup-get-rollup-index-caps.html[rollup index]. -Clicking a badge narrows the list to only indices of that type. +Clicking a badge narrows the list to only indices of that type. You can also filter your indices using the search bar. -You can drill down into each index to investigate the index -{ref}/index-modules.html#index-modules-settings[settings], {ref}/mapping.html[mapping], and statistics. +You can drill down into each index to investigate the index +{ref}/index-modules.html#index-modules-settings[settings], {ref}/mapping.html[mapping], and statistics. From this view, you can also edit the index settings. [role="screenshot"] @@ -50,35 +50,35 @@ image::images/management_index_details.png[Index Management UI] [float] === Perform index-level operations -Use the *Manage* menu to perform index-level operations. This menu -is available in the index details view, or when you select the checkbox of one or more -indices on the overview page. The menu includes the following actions: +Use the *Manage* menu to perform index-level operations. This menu +is available in the index details view, or when you select the checkbox of one or more +indices on the overview page. The menu includes the following actions: -* *Close index*. Blocks the index from read/write operations. -A closed index exists in the cluster, but doesn't consume resources -other than disk space. If you reopen a closed index, it goes through the -normal recovery process. +* *Close index*. Blocks the index from read/write operations. +A closed index exists in the cluster, but doesn't consume resources +other than disk space. If you reopen a closed index, it goes through the +normal recovery process. -* *Force merge index*. Reduces the number of segments in your shard by +* *Force merge index*. Reduces the number of segments in your shard by merging smaller files and clearing deleted ones. Only force merge a read-only index. -* *Refresh index*. Writes the operations in the indexing buffer to the -filesystem cache. This action is automatically performed once per second. Forcing a manual -refresh is useful during testing, but should not be routinely done in +* *Refresh index*. Writes the operations in the indexing buffer to the +filesystem cache. This action is automatically performed once per second. Forcing a manual +refresh is useful during testing, but should not be routinely done in production because it has a performance impact. -* *Clear index cache*. Clears all caches associated with the index. +* *Clear index cache*. Clears all caches associated with the index. -* *Flush index*. Frees memory by syncing the filesystem cache to disk and +* *Flush index*. Frees memory by syncing the filesystem cache to disk and clearing the cache. Once the sync is complete, the internal transaction log is reset. -* *Freeze index*. Makes the index read-only and reduces its memory footprint -by moving shards to disk. Frozen indices remain +* *Freeze index*. Makes the index read-only and reduces its memory footprint +by moving shards to disk. Frozen indices remain searchable, but queries take longer. * *Delete index*. Permanently removes the index and all of its documents. -* *Add lifecycle policy*. Specifies a policy for managing the lifecycle of the +* *Add lifecycle policy*. Specifies a policy for managing the lifecycle of the index. [float] @@ -86,20 +86,20 @@ index. === Manage index templates An index template defines {ref}/index-modules.html#index-modules-settings[settings], -{ref}/mapping.html[mappings], and {ref}/indices-add-alias.html[aliases] -that you can automatically apply when creating a new index. {es} applies a +{ref}/mapping.html[mappings], and {ref}/indices-add-alias.html[aliases] +that you can automatically apply when creating a new index. {es} applies a template to a new index based on an index pattern that matches the index name. -The *Index Templates* view lists your templates and enables you to examine, edit, clone, and -delete them. Changes you make to an index template +The *Index Templates* view lists your templates and enables you to examine, edit, clone, and +delete them. Changes you make to an index template do not affect existing indices. [role="screenshot"] image::images/management-index-templates.png[Index templates] -If you don't have any templates, you can create one using the *Create template* wizard. -Index templates are applied during index creation, -so you must create the +If you don't have any templates, you can create one using the *Create template* wizard. +Index templates are applied during index creation, +so you must create the template before you create the indices. [float] @@ -107,47 +107,38 @@ template before you create the indices. In this example, you’ll create an index template for randomly generated log files. -Open the *Create template* wizard, and enter `logs_template` in the *Name* +Open the *Create template* wizard, and enter `logs_template` in the *Name* field. Set *Index pattern* to `logstash*` so the template matches any index -with that index pattern. The merge order and version are both optional, +with that index pattern. The merge order and version are both optional, and you'll leave them blank in this example. - + [role="screenshot"] image::images/management_index_create_wizard.png[Create wizard] -The second step in the *Create template* wizard allows you to define index settings. -These settings are optional, and this example skips this step. +The second step in the *Create template* wizard allows you to define index settings. +These settings are optional, and this example skips this step. -The logs data set requires a -mapping to label the latitude and longitude pairs as geographic locations -by applying the geo_point type. In the third step of the wizard, define -this mapping as follows: +The logs data set requires a +mapping to label the latitude and longitude pairs as geographic locations +by applying the geo_point type. In the third step of the wizard, define this mapping +under the *Mapped fields* tab as follows: -[source,js] ----------------------------------- -{ - "properties": { - "geo": { - "properties": { - "coordinates": { - "type": "geo_point" - } - } - } - } -} ----------------------------------- +[role="screenshot"] +image::images/management-index-templates-mappings.png[Mapped fields page] + +You can create additional mapping configurations in the *Dynamic templates* and +*Advanced options* tabs. No additional mappings are required for this example. In the fourth step, define an alias named `logstash`. - + [source,js] ---------------------------------- { "logstash": {} } ---------------------------------- - -A summary of the template is in step 5. If everything looks right, click *Create template*. + +A summary of the template is in step 5. If everything looks right, click *Create template*. At this point, you’re ready to use the {es} index API to load the logs data. In the {kib} *Console*, index two documents: @@ -186,5 +177,5 @@ POST /logstash-2019.05.20/_doc } ---------------------------------- -The mappings and alias are configured automatically based on the template. To verify, you +The mappings and alias are configured automatically based on the template. To verify, you can view one of the newly created indices using the {ref}/indices-get-index.html#indices-get-index[index API]. diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 535ad169782170..6fdb81c780a7d7 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -229,23 +229,25 @@ Kibana, the server needs to be CORS-enabled so Kibana can download the file. The following example shows a valid regionmap configuration. + -- - map.regionmap: + map includeElasticMapsService: false - layers: - - name: "Departments of France" - url: "http://my.cors.enabled.server.org/france_departements.geojson" - attribution: "INRAP" - fields: - - name: "department" + regionmap: + layers: + - name: "Departments of France" + url: "http://my.cors.enabled.server.org/france_departements.geojson" + attribution: "INRAP" + fields: + - name: "department" description: "Full department name" - - name: "INSEE" + - name: "INSEE" description: "INSEE numeric identifier" -- -[[regionmap-ES-map]]`map.regionmap.includeElasticMapsService:`:: Turns on or off +[[regionmap-ES-map]]`map.includeElasticMapsService:`:: Turns on or off whether layers from the Elastic Maps Service should be included in the vector layer option list. Supported on Elastic Cloud Enterprise. By turning this off, -only the layers that are configured here will be included. The default is `true`. +only the layers that are configured here will be included. The default is `true`. +This also affects whether tile-service from the Elastic Maps Service will be available. [[regionmap-attribution]]`map.regionmap.layers[].attribution:`:: Optional. References the originating source of the geojson file. Supported on {ece}. diff --git a/docs/user/dashboard.asciidoc b/docs/user/dashboard.asciidoc index 2923e42c1ab34b..490edb9d263381 100644 --- a/docs/user/dashboard.asciidoc +++ b/docs/user/dashboard.asciidoc @@ -4,25 +4,23 @@ [partintro] -- -A {kib} _dashboard_ is a collection of visualizations, searches, and -maps, typically in real-time. Dashboards provide -at-a-glance insights into your data and enable you to drill down into details. +A _dashboard_ is a collection of visualizations, searches, and +maps, typically in real-time. Dashboards provide +at-a-glance insights into your data and enable you to drill down into details. -To start working with dashboards, click *Dashboard* in the side navigation. With *Dashboard*, you can: -* <> -* <> -* <> -* <> -* <> -* <> +* Add visualizations, saved searches, and maps for side-by-side analysis +* Arrange dashboard elements to display exactly how you want + +* Customize time ranges to display only the data you want + +* Inspect and edit dashboard elements to find out exactly what kind of data is displayed [role="screenshot"] image:images/Dashboard_example.png[Example dashboard] - [float] [[dashboard-read-only-access]] === [xpack]#Read only access# @@ -32,56 +30,61 @@ then you don't have sufficient privileges to create and save dashboards. The but dashboards are not visible. For more information, see <>. [role="screenshot"] -image::images/dashboard-read-only-badge.png[Example of Dashboard's read only access indicator in Kibana's header] +image::images/dashboard-read-only-badge.png[Example of Dashboard read only access indicator in Kibana header] -[float] -[[dashboard-getting-started]] -=== Interact with dashboards +-- + +[[dashboard-create-new-dashboard]] +== Create a dashboard -When you open *Dashboard*, you're presented an overview of your dashboards. -If you don't have any dashboards, you can add +To create a dashboard, you must have data indexed into {es}, an index pattern +to retrieve the data from {es}, and +visualizations, saved searches, or maps. If these don't exist, you're prompted to +add them as you create the dashboard, or you can add <>, -which include pre-built dashboards. +which include pre-built dashboards. -Once you open a dashboard, you can filter the data -by entering a search query, changing the time filter, or clicking -in the visualizations, searches, and maps. If a dashboard element has a stored query, -both queries are applied. +To begin, open *Dashboard*, then click *Create new dashboard.* --- +[float] +[[dashboard-add-elements]] +=== Add elements -[[dashboard-create-new-dashboard]] -== Create a dashboard +The visualizations, saved searches, and maps are stored as elements in panels +that you can move and resize. -To create a dashboard, you must have data indexed into {es}, an index pattern -to retrieve the data from {es}, and -visualizations, saved searches, or maps. If these don't exist, you're prompted to -add them as you create the dashboard. +You can add elements from multiple indices, and the same element can appear in +multiple dashboards. -For an end-to-end example, see <>. +To create an element: + +. Click *Create new*. +. On the *New Visualization* window, click the visualization type. ++ +[role="screenshot"] +image:images/Dashboard_add_new_visualization.png[Example add new visualization to dashboard] ++ +For information on how to create visualizations, see <>. ++ +For information on how to create Maps, see <>. + +To add an existing element: -. Open *Dashboard.* -. Click *Create new dashboard.* . Click *Add*. -. Use *Add panels* to add elements to the dashboard. + +. On the *Add panels* flyout, select the panel. + -The visualizations, saved searches, and maps -are stored in panels that you can move and resize. A -menu in the upper right of the panel has options for customizing -the panel. You can add elements from -multiple indices, and the same element can appear in multiple dashboards. +When a dashboard element has a stored query, +both queries are applied. + [role="screenshot"] image:images/Dashboard_add_visualization.png[Example add visualization to dashboard] -. When you're finished adding and arranging the panels, -*Save* the dashboard. - [float] [[customizing-your-dashboard]] === Arrange dashboard elements -In *Edit* mode, you can move, resize, customize, and delete panels to suit your needs. +In *Edit* mode, you can move, resize, customize, and delete panels to suit your needs. [[moving-containers]] * To move a panel, click and hold the panel header and drag to the new location. @@ -95,16 +98,33 @@ to the new dimensions. * To delete a panel, open the panel menu and select *Delete from dashboard.* Deleting a panel from a dashboard does *not* delete the saved visualization or search. +[float] +[[viewing-detailed-information]] +=== Inspect and edit elements + +Many dashboard elements allow you to drill down into the data and requests +behind the element. + +From the panel menu, select *Inspect*. +The data that displays depends on the element that you inspect. + +[role="screenshot"] +image:images/Dashboard_inspect.png[Inspect in dashboard] + +To open an element for editing, put the dashboard in *Edit* mode, +and then select *Edit visualization* from the panel menu. The changes you make appear in +every dashboard that uses the element. + [float] [[dashboard-customize-filter]] === Customize time ranges You can configure each visualization, saved search, and map on your dashboard for a specific time range. For example, you might want one visualization to show -the monthly trend for CPU usage and another to show the current CPU usage. +the monthly trend for CPU usage and another to show the current CPU usage. -From the panel menu, select *Customize time range* to expose a time filter -dedicated to that panel. Panels that are not restricted by a specific +From the panel menu, select *Customize time range* to expose a time filter +dedicated to that panel. Panels that are not restricted by a specific time range are controlled by the global time filter. @@ -112,20 +132,30 @@ global time filter. image:images/time_range_per_panel.gif[Time range per dashboard panel] [float] +[[save-dashboards]] +=== Save the dashboard + +When you're finished adding and arranging the panels, save the dashboard. + +. In the {kib} toolbar, click *Save*. + +. Enter the dashboard *Title* and optional *Description*, then *Save* the dashboard. + [[sharing-dashboards]] -=== Share a dashboard +=== Share the dashboard [[embedding-dashboards]] -When you've finished your dashboard, you can share it with your teammates. +Share your dashboard outside of {kib}. + From the *Share* menu, you can: -* Embed the code in a web page. Users must have Kibana access +* Embed the code in a web page. Users must have {kib} access to view an embedded dashboard. * Share a direct link to a {kib} dashboard * Generate a PDF report * Generate a PNG report -TIP: You can create a link to a dashboard by title by doing this: + +TIP: To create a link to a dashboard by title, use: + `${domain}/${basepath?}/app/kibana#/dashboards?title=${yourdashboardtitle}` TIP: When sharing a link to a dashboard snapshot, use the *Short URL*. Snapshot @@ -134,29 +164,7 @@ tools. To create a short URL, you must have write access to {kib}. [float] [[import-dashboards]] -=== Import and export dashboards - -To import and export dashboards, go to *Management > Saved Objects*. For details, -see <>. - -[float] -[[viewing-detailed-information]] -=== Inspect and edit elements - -Many dashboard elements allow you to drill down into the data and requests -behind the element. Open the menu in the upper right of the panel and select *Inspect*. -The views you see depend on the element that you inspect. - -[role="screenshot"] -image:images/Dashboard_inspect.png[Inspect in dashboard] - -To open an element for editing, put the dashboard in *Edit* mode, -and then select *Edit* from the panel menu. The changes you make appear in -every dashboard that uses the element. - - - - - - +=== Export the dashboard +To export the dashboard, go to *Management > Saved Objects*. For more information, +see <>. diff --git a/docs/user/security/securing-communications/index.asciidoc b/docs/user/security/securing-communications/index.asciidoc index b370c35905bce4..3e022315a4d842 100644 --- a/docs/user/security/securing-communications/index.asciidoc +++ b/docs/user/security/securing-communications/index.asciidoc @@ -4,8 +4,9 @@ Encrypting communications ++++ -{kib} supports Transport Layer Security (TLS/SSL) encryption for all forms of data-in-transit. Browsers send traffic to {kib} and {kib} -sends traffic to {es}. These communications are configured separately. +{kib} supports Transport Layer Security (TLS/SSL) encryption for all forms of +data-in-transit. Browsers send traffic to {kib} and {kib} sends traffic to {es}. +These communications are configured separately. [[configuring-tls-browser-kib]] ==== Encrypting traffic between the browser and {kib} @@ -78,7 +79,8 @@ NOTE: To perform this step, you must {ref}/configuring-security.html[enable the {es} {security-features}] or you must have a proxy that provides an HTTPS endpoint for {es}. -. Specify the HTTPS URL in the `elasticsearch.hosts` setting in the {kib} configuration file, `kibana.yml`: +. Specify the HTTPS URL in the `elasticsearch.hosts` setting in the {kib} +configuration file, `kibana.yml`: + -- [source,yaml] @@ -86,7 +88,9 @@ must have a proxy that provides an HTTPS endpoint for {es}. elasticsearch.hosts: ["https://.com:9200"] -------------------------------------------------------------------------------- -Using the HTTPS protocol results in a default `elasticsearch.ssl.verificationMode` option of `full`, which utilizes hostname verification. +Using the HTTPS protocol results in a default +`elasticsearch.ssl.verificationMode` option of `full`, which utilizes hostname +verification. For more information, see <>. -- @@ -95,8 +99,10 @@ For more information, see <>. + -- -If you are using your own CA to sign certificates for {es}, then you need to specify the CA certificate chain in {kib} to properly establish -trust in TLS connections. If your CA certificate chain is contained in a PKCS #12 trust store, specify it like so: +If you are using your own CA to sign certificates for {es}, then you need to +specify the CA certificate chain in {kib} to properly establish trust in TLS +connections. If your CA certificate chain is contained in a PKCS #12 trust store, +specify it like so: [source,yaml] -------------------------------------------------------------------------------- @@ -104,15 +110,21 @@ elasticsearch.ssl.truststore.path: "/path/to/your/truststore.p12" elasticsearch.ssl.truststore.password: "optional decryption password" -------------------------------------------------------------------------------- -Otherwise, if your CA certificate chain is in PEM format, specify each certificate like so: +Otherwise, if your CA certificate chain is in PEM format, specify each +certificate like so: [source,yaml] -------------------------------------------------------------------------------- elasticsearch.ssl.certificateAuthorities: ["/path/to/your/cacert1.pem", "/path/to/your/cacert2.pem"] -------------------------------------------------------------------------------- +TIP: You can use the {ref}/certutil.html[`elasticsearch-certutil http` command] +to generate a PEM format x.509 certificate for the {es} CA. It also provides +detailed configuration details in readme files. + -- -. (Optional) If the Elastic {monitor-features} are enabled, configure {kib} to connect to the {es} monitoring cluster via HTTPS. The steps -are the same as above, but each setting is prefixed by `xpack.monitoring.`. For example, `xpack.monitoring.elasticsearch.hosts`, +. (Optional) If the Elastic {monitor-features} are enabled, configure {kib} to +connect to the {es} monitoring cluster via HTTPS. The steps are the same as +above, but each setting is prefixed by `xpack.monitoring.`. For example, `xpack.monitoring.elasticsearch.hosts`, `xpack.monitoring.elasticsearch.ssl.truststore.path`, etc. diff --git a/docs/user/visualize.asciidoc b/docs/user/visualize.asciidoc index e69d62daf74353..cfd2bac4989c11 100644 --- a/docs/user/visualize.asciidoc +++ b/docs/user/visualize.asciidoc @@ -3,9 +3,9 @@ [partintro] -- -_Visualize_ enables you to create visualizations of the data from your Elasticsearch indices, which you can then add to dashboards for analysis. +_Visualize_ enables you to create visualizations of the data from your {es} indices, which you can then add to dashboards for analysis. -{kib} visualizations are based on Elasticsearch queries. By using a series of {es} {ref}/search-aggregations.html[aggregations] to extract and process your data, you can create charts that show you the trends, spikes, and dips you need to know about. +{kib} visualizations are based on {es} queries. By using a series of {es} {ref}/search-aggregations.html[aggregations] to extract and process your data, you can create charts that show you the trends, spikes, and dips you need to know about. [float] [[create-a-visualization]] @@ -15,42 +15,59 @@ _Visualize_ enables you to create visualizations of the data from your Elasticse . Click *Create new visualization*. . Choose the visualization type: + -* *Basic charts* -<>:: Quickly build several types of basic visualizations by simply dragging and dropping the data fields you want to display. +* Basic charts +[horizontal] +<>:: +Quickly build several types of basic visualizations by simply dragging and dropping the data fields you want to display. + * *<>* [horizontal] Line, area, and bar charts:: Compare different series in X/Y charts. + Pie chart:: Display each source contribution to a total. + Data table:: Flattens aggregations into table format. + Metric:: Display a single number. + Goal and gauge:: Display a number with progress indicators. -Heat maps:: Display shaded cells within a matrix. + Tag cloud:: Display words in a cloud, where the size of the word corresponds to its importance. + * *Time series optimized* [horizontal] <>:: Visualize time series data using pipeline aggregations. + <>:: Compute and combine data from multiple time series data sets. + * *Maps* [horizontal] -<>:: The most powerful way of visualizing map data in {kib}. -<>:: Displays points on a map using a geohash aggregation. -<>:: Merge any structured map data onto a shape. -* *<>* +<>:: The most powerful way of visualizing map data in {kib}. + +<>:: Displays points on a map using a geohash aggregation. + +<>:: Merge any structured map data onto a shape. + +<>:: Display shaded cells within a matrix. + +* *<>* [horizontal] <>:: Provides the ability to add interactive inputs to a Dashboard. + <>:: Display free-form information or instructions. + * *For developers* [horizontal] <>:: Complete control over query and display. . Specify a search query to retrieve the data for your visualization: ** To enter new search criteria, select the <> for the indices that -contain the data you want to visualize. This opens the visualization builder +contain the data you want to visualize. The visualization builder opens with a wildcard query that matches all of the documents in the selected indices. ** To build a visualization from a saved search, click the name of the saved -search you want to use. This opens the visualization builder and loads the +search you want to use. The visualization builder opens and loads the selected query. + NOTE: When you build a visualization from a saved search, any subsequent @@ -58,9 +75,12 @@ modifications to the saved search are automatically reflected in the visualization. To disable automatic updates, you can disconnect a visualization from the saved search. + -- include::{kib-repo-dir}/visualize/visualize_rollup_data.asciidoc[] +include::{kib-repo-dir}/visualize/aggregations.asciidoc[] + include::{kib-repo-dir}/visualize/lens.asciidoc[] include::{kib-repo-dir}/visualize/most-frequent.asciidoc[] @@ -70,6 +90,7 @@ include::{kib-repo-dir}/visualize/timelion.asciidoc[] include::{kib-repo-dir}/visualize/tilemap.asciidoc[] include::{kib-repo-dir}/visualize/regionmap.asciidoc[] +include::{kib-repo-dir}/visualize/heatmap.asciidoc[] include::{kib-repo-dir}/visualize/for-dashboard.asciidoc[] diff --git a/docs/visualize/aggregations.asciidoc b/docs/visualize/aggregations.asciidoc index 36ddb0063dfc30..95aa586e6ba180 100644 --- a/docs/visualize/aggregations.asciidoc +++ b/docs/visualize/aggregations.asciidoc @@ -1,136 +1,112 @@ [[supported-aggregations]] -=== Supported aggregations +== Supported aggregations -The most frequently used visualizations support the following aggregations. +Use the supported aggregations to build your visualizations. [float] [[visualize-metric-aggregations]] -==== Metric aggregations +=== Metric aggregations -The *Count* metric lets you visualize the number of documents in a bucket. -If there are no bucket aggregations defined, this is the total number of documents that match the query. -It is the default selection. - -All other metric aggregations require a field selection, which will read from the indexed values. Alternatively, -you can override field values with a script using the <>. The -other metric aggregations are: +Metric aggregations extract field from documents to generate data values. {ref}/search-aggregations-metrics-avg-aggregation.html[Average]:: The mean value. -{ref}/search-aggregations-metrics-max-aggregation.html[Maximum]:: The highest value. -{ref}/search-aggregations-metrics-percentile-aggregation.html[Median]:: The value that is in the 50% percentile. -{ref}/search-aggregations-metrics-min-aggregation.html[Minimum]:: The lowest value. -{ref}/search-aggregations-metrics-sum-aggregation.html[Sum]:: The total value. -Unique Count:: The {ref}/search-aggregations-metrics-cardinality-aggregation.html[Cardinality] of the field within the bucket. -Supports any data type. +{ref}/search-aggregations-metrics-valuecount-aggregation.html[Count]:: The total number of documents that match the query, which allows you to visualize the number of documents in a bucket. Count is the default value. -Standard Deviation:: Requires a numeric field. Uses the {ref}/search-aggregations-metrics-extendedstats-aggregation.html[_extended stats_] aggregation. +{ref}/search-aggregations-metrics-max-aggregation.html[Max]:: The highest value. + +{ref}/search-aggregations-metrics-percentile-aggregation.html[Median]:: The value that is in the 50% percentile. + +{ref}/search-aggregations-metrics-min-aggregation.html[Min]:: The lowest value. -{ref}/search-aggregations-metrics-top-hits-aggregation.html[Top Hit]:: Returns a sample of individual documents. When the Top Hit aggregation is matched to more than one document, you must choose a technique for combining the values. Techniques include average, minimum, maximum, and sum. +{ref}/search-aggregations-metrics-percentile-rank-aggregation.html[Percentile ranks]:: Returns the percentile rankings for the values in the specified numeric field. Select a numeric field from the drop-down, then specify one or more percentile rank values in the *Values* fields. {ref}/search-aggregations-metrics-percentile-aggregation.html[Percentiles]:: Divides the -values in a numeric field into specified percentile bands. Select a field from the drop-down, then specify one or more ranges in the *Percentiles* fields. Click the *X* to remove a percentile field. Click *+ Add* to add a percentile field. +values in a numeric field into specified percentile bands. Select a field from the drop-down, then specify one or more ranges in the *Percentiles* fields. -{ref}/search-aggregations-metrics-percentile-rank-aggregation.html[Percentile Rank]:: Returns the percentile rankings for the values in the specified numeric field. Select a numeric field from the drop-down, then specify one or more percentile rank values in the *Values* fields. Click the *X* to remove a values field. Click *+Add* to add a values field. +Standard Deviation:: Requires a numeric field. Uses the {ref}/search-aggregations-metrics-extendedstats-aggregation.html[_extended stats_] aggregation. -[float] -[[visualize-sibling-pipeline-aggregations]] -==== Sibling pipeline aggregations +{ref}/search-aggregations-metrics-sum-aggregation.html[Sum]:: The total value. -For each of the sibling pipeline aggregations you have to define a bucket and metric to calculate. This -has the effect of condensing many buckets into one number. +{ref}/search-aggregations-metrics-top-hits-aggregation.html[Top hit]:: Returns a sample of individual documents. When the Top Hit aggregation is matched to more than one document, you must choose a technique for combining the values. Techniques include average, minimum, maximum, and sum. -{ref}/search-aggregations-pipeline-avg-bucket-aggregation.html[Average Bucket]:: Calculates the mean, or average, value of a specified metric in a sibling aggregation. +Unique Count:: The {ref}/search-aggregations-metrics-cardinality-aggregation.html[Cardinality] of the field within the bucket. -{ref}/search-aggregations-pipeline-avg-bucket-aggregation.html[Sum Bucket]:: Calculates the sum of the values of a specified metric in a sibling aggregation. +Alternatively, you can override the field values with a script using JSON input. For example: -{ref}/search-aggregations-pipeline-avg-bucket-aggregation.html[Min Bucket]:: Calculates the minimum value of a specified metric in a sibling aggregation. +[source,shell] +{ "script" : "doc['grade'].value * 1.2" } -{ref}/search-aggregations-pipeline-avg-bucket-aggregation.html[Max Bucket]:: Calculates the maximum value of a specified metric in a sibling aggregation. +The example implements a {es} {ref}/search-aggregations.html[Script Value Source], which replaces +the value in the metric. The options available depend on the aggregation you choose. [float] -[[visualize-bucket-aggregations]] -==== Bucket aggregations - -{ref}/search-aggregations-bucket-datehistogram-aggregation.html[Date Histogram]:: Splits a date field into buckets by interval. If the date field is the primary time field for the index pattern, it will pick an automatic interval for you. You can also choose a minimum time interval, or specify a custom interval frame by selecting *Custom* as the interval and -specifying a number and a time unit in the text field. Custom interval time units are *s* for seconds, *m* for minutes, -*h* for hours, *d* for days, *w* for weeks, and *y* for years. Different units support different levels of precision, -down to one millisecond. Intervals are labeled at the start of the interval, using the date-key returned by Elasticsearch.For example, the tooltip for a monthly interval will show the first day of the month. +[[visualize-parent-pipeline-aggregations]] +=== Parent pipeline aggregations -{ref}/search-aggregations-bucket-histogram-aggregation.html[Histogram]:: Builds from a numeric field. Specify an integer interval for this field. Select the *Show empty buckets* checkbox to include empty intervals in the histogram. +Parent pipeline aggregations assume the bucket aggregations are ordered and are especially useful for time series data. For each parent pipeline aggregation, you must define a bucket aggregation and metric aggregation. -{ref}/search-aggregations-bucket-range-aggregation.html[Range]:: Specify ranges of values for a numeric field. Click *Add Range* to add a set of range endpoints. Click the red *(x)* symbol to remove a range. +You can also nest these aggregations. For example, if you want to produce a third derivative. -{ref}/search-aggregations-bucket-daterange-aggregation.html[Date Range]:: Reports values that are within a range of dates that you specify. You can specify the ranges for the dates using {ref}/common-options.html#date-math[_date math_] expressions. Click *Add Range* to add a set of range endpoints. -Click the red *(x)* symbol to remove a range. +{ref}/search-aggregations-pipeline-bucket-script-aggregation.html[Bucket script]:: Executes a script that performs computations for each bucket that specifies metrics in the parent multi-bucket aggregation. -{ref}/search-aggregations-bucket-iprange-aggregation.html[IPv4 Range]:: Specify ranges of IPv4 addresses. Click *Add Range* to add a set of range endpoints. Click the red *(x)* symbol to remove a range. +{ref}/search-aggregations-pipeline-cumulative-sum-aggregation.html[Cumulative sum]:: Calculates the cumulative sum of a specified metric in a parent histogram. -*Filters*:: Each filter creates a bucket of documents. You can specify a filter as a -<> or <> query string. Click *Add Filter* to -add another filter. Click the image:images/labelbutton.png[Label button icon] *label* button to open the label field, where -you can type in a name to display on the visualization. +{ref}/search-aggregations-pipeline-derivative-aggregation.html[Derivative]:: Calculates the derivative of specific metrics. -{ref}/search-aggregations-bucket-terms-aggregation.html[Terms]:: Specify the top or bottom _n_ elements of a given field to display, ordered by count or a custom metric. +{ref}/search-aggregations-pipeline-movavg-aggregation.html[Moving avg]:: Slides a window across the data and emits the average value of the window. -{ref}/search-aggregations-bucket-significantterms-aggregation.html[Significant Terms]:: Returns interesting or unusual occurrences of terms in a set. +{ref}/search-aggregations-pipeline-serialdiff-aggregation.html[Serial diff]:: Values in a time series are subtracted from itself at different time lags or periods. -Both Terms and Significant Terms support {es} {ref}/search-aggregations-bucket-terms-aggregation.html#_filtering_values_4[exclude and include patterns] which -are available by clicking *Advanced* after selecting a field. +Custom {kib} plugins can <>, which includes support for adding more aggregations. -Kibana only supports filtering string fields with regular expression patterns, it does not support matching with arrays or filtering numeric fields. -Patterns are case sensitive. +[float] +[[visualize-sibling-pipeline-aggregations]] +=== Sibling pipeline aggregations -Example: +Sibling pipeline aggregations condense many buckets into one. For each sibling pipeline aggregation, you must define a bucket aggregations and metric aggregation. -* You want to exclude the metricbeat process from your visualization of top processes: `metricbeat.*` -* You only want to show processes collecting beats: `.*beat` -* You want to exclude two specific values, the string `"empty"` and `"none"`: `empty|none` +{ref}/search-aggregations-pipeline-avg-bucket-aggregation.html[Average bucket]:: Calculates the mean, or average, value of a specified metric in a sibling aggregation. -*Geo aggregations* +{ref}/search-aggregations-pipeline-avg-bucket-aggregation.html[Max Bucket]:: Calculates the maximum value of a specified metric in a sibling aggregation. -These are only supported by the tile map and table visualizations: +{ref}/search-aggregations-pipeline-avg-bucket-aggregation.html[Min Bucket]:: Calculates the minimum value of a specified metric in a sibling aggregation. -{ref}/search-aggregations-bucket-geohashgrid-aggregation.html[Geohash]:: Displays points based on a geohash. +{ref}/search-aggregations-pipeline-avg-bucket-aggregation.html[Sum Bucket]:: Calculates the sum of the values of a specified metric in a sibling aggregation. -{ref}/search-aggregations-bucket-geotilegrid-aggregation.html[Geotile]:: Groups points based on web map tiling. +[float] +[[visualize-bucket-aggregations]] +=== Bucket aggregations +Bucket aggregations sort documents into buckets, depending on the contents of the document. -[float] -[[visualize-parent-pipeline-aggregations]] -==== Parent pipeline aggregations +{ref}/search-aggregations-bucket-datehistogram-aggregation.html[Date histogram]:: Splits a date field into buckets by interval. If the date field is the primary time field for the index pattern, it chooses an automatic interval for you. Intervals are labeled at the start of the interval, using the date-key returned by {es}. For example, the tooltip for a monthly interval displays the first day of the month. -For each of the parent pipeline aggregations you have to define a bucket and metric to calculate. These -metrics expect the buckets to be ordered, and are especially useful for time series data. -You can also nest these aggregations. For example, if you want to produce a third derivative. +{ref}/search-aggregations-bucket-daterange-aggregation.html[Date range]:: Reports values that are within a range of dates that you specify. You can specify the ranges for the dates using {ref}/common-options.html#date-math[_date math_] expressions. -These visualizations support parent pipeline aggregations: +{ref}/search-aggregations-bucket-filter-aggregation.html[Filter]:: Each filter creates a bucket of documents. You can specify a filter as a +<> or <> query string. -* Line, Area and Bar charts -* Data table +{ref}/search-aggregations-bucket-geohashgrid-aggregation.html[Geohash]:: Displays points based on a geohash. Supported by the tile map and data table visualizations. -{ref}/search-aggregations-pipeline-derivative-aggregation.html[Derivative]:: Calculates the derivative of specific metrics. +{ref}/search-aggregations-bucket-geotilegrid-aggregation.html[Geotile]:: Groups points based on web map tiling. Supported by the tile map and data table visualizations. -{ref}/search-aggregations-pipeline-cumulative-sum-aggregation.html[Cumulative Sum]:: Calculates the cumulative sum of a specified metric in a parent histogram. +{ref}/search-aggregations-bucket-histogram-aggregation.html[Histogram]:: Builds from a numeric field. -{ref}/search-aggregations-pipeline-movavg-aggregation.html[Moving Average]:: Slides a window across the data and emits the average value of the window. +{ref}/search-aggregations-bucket-iprange-aggregation.html[IPv4 range]:: Specify ranges of IPv4 addresses. -{ref}/search-aggregations-pipeline-serialdiff-aggregation.html[Serial Diff]:: Values in a time series are subtracted from itself at different time lags or periods. +{ref}/search-aggregations-bucket-range-aggregation.html[Range]:: Specify ranges of values for a numeric field. -Custom {kib} plugins can <>, which includes support for adding more aggregations. +{ref}/search-aggregations-bucket-significantterms-aggregation.html[Significant terms]:: Returns interesting or unusual occurrences of terms in a set. Supports {es} {ref}/search-aggregations-bucket-terms-aggregation.html#_filtering_values_4[exclude and include patterns]. -[float] -[[visualize-advanced-aggregation-options]] -==== Advanced aggregation options +{ref}/search-aggregations-bucket-terms-aggregation.html[Terms]:: Specify the top or bottom _n_ elements of a given field to display, ordered by count or a custom metric. Supports {es} {ref}/search-aggregations-bucket-terms-aggregation.html#_filtering_values_4[exclude and include patterns]. -*JSON Input*:: A text field where you can add specific JSON-formatted properties to merge with the aggregation -definition, as in the following example: +{kib} filters string fields with only regular expression patterns, and does not filter numeric fields or match with arrays. -[source,shell] -{ "script" : "doc['grade'].value * 1.2" } +For example: -This example implements a {es} {ref}/search-aggregations.html[Script Value Source] which replaces -the value in the metric. The availability of these options varies depending on the aggregation -you choose. +* You want to exclude the metricbeat process from your visualization of top processes: `metricbeat.*` +* You only want to show processes collecting beats: `.*beat` +* You want to exclude two specific values, the string `"empty"` and `"none"`: `empty|none` -When multiple bucket aggregations are defined, you can use the drag target on each aggregation to change the priority. For more information about working with aggregation order, see https://www.elastic.co/blog/kibana-aggregation-execution-order-and-you[Kibana, Aggregation Execution Order, and You]. +Patterns are case sensitive. diff --git a/docs/visualize/heatmap.asciidoc b/docs/visualize/heatmap.asciidoc new file mode 100644 index 00000000000000..18c4018213390b --- /dev/null +++ b/docs/visualize/heatmap.asciidoc @@ -0,0 +1,40 @@ +[[heatmap]] +== Heat map + +Heat maps are graphical representations of data where the individual values are represented as colors. + +NOTE: Heat map has been replaced with <>, which offers more functionality and is easier to use. + +[float] +[[heatmap-aggregation]] +=== Supported aggregations + +Heat maps support the following aggregations: + +* <> + +* <> + +* <> + +* <> + +[float] +[[navigate-heatmap]] +=== Change the color ranges + +When only one color displays on the heat map, you might need to change the color ranges. + +To specify the number of color ranges: + +. Click *Options*. + +. Enter the *Number of colors* to display. + +To specify custom ranges: + +. Click *Options*. + +. Select *Use custom ranges*. + +. Enter the ranges to display. diff --git a/docs/visualize/lens.asciidoc b/docs/visualize/lens.asciidoc index e61895a29891ba..e3f61565453b5e 100644 --- a/docs/visualize/lens.asciidoc +++ b/docs/visualize/lens.asciidoc @@ -4,7 +4,7 @@ beta[] -*Lens* provides you with a simple and fast way to create visualizations from your Elasticsearch data. With Lens, you can: +*Lens* provides you with a simple and fast way to create visualizations from your {es} data. With Lens, you can: * Quickly build visualizations by dragging and dropping data fields. @@ -14,6 +14,20 @@ beta[] * Save your visualization for use in a dashboard. +[float] +[[lens-aggregation]] +=== Supported aggregations + +Lens supports the following aggregations: + +* <> + +* <> + +* <> + +* <> + [float] [[drag-drop]] === Drag and drop diff --git a/docs/visualize/metric.asciidoc b/docs/visualize/metric.asciidoc index 9cbc4a0f7a5508..ddcf5fe3b73bdb 100644 --- a/docs/visualize/metric.asciidoc +++ b/docs/visualize/metric.asciidoc @@ -2,3 +2,15 @@ === Metric Click the *Options* tab to display the font size slider. + +[float] +[[metric-aggregation]] +==== Supported aggregations + +Metric support the following aggregations: + +* <> + +* <> + +* <> diff --git a/docs/visualize/most-frequent.asciidoc b/docs/visualize/most-frequent.asciidoc index e9085d18185ec3..2cb8aa7cb3c1fb 100644 --- a/docs/visualize/most-frequent.asciidoc +++ b/docs/visualize/most-frequent.asciidoc @@ -1,30 +1,41 @@ [[most-frequent]] == Most frequently used visualizations -The most frequently used visualizations allow you to plot aggregated data from a <> or <>. They all support a single level of -Elasticsearch {es} {ref}/search-aggregations-metrics.html[metric] aggregations, and one or more -levels of {es} {ref}/search-aggregations-bucket.html[bucket] aggregations. +The most frequently used visualizations allow you to plot aggregated data from a <> or <>. The most frequently used visualizations include: * Line, area, and bar charts -* Pie charts -* Data tables -* Metric, goals, and gauges -* Heat maps -* Tag clouds +* Pie chart +* Data table +* Metric, goal, and gauge +* Tag cloud + +[float] +[[frequently-used-viz-aggregation]] +=== Supported aggregations + +The most frequently used visualizations support the following aggregations: + +* <> + +* <> + +* <> + +* <> [float] === Configure your visualization -You configure visualizations using the default editor, which is broken into metrics and buckets, and includes a default count -metric. Each visualization supports different configurations for what the metrics and buckets -represent. For example, a bar chart allows you to add an X-axis: +You configure visualizations using the default editor. Each visualization supports different configurations of the metrics and buckets. + +For example, a bar chart allows you to add an x-axis: [role="screenshot"] image::images/add-bucket.png["",height=478] -A common configuration for the X-axis is to use a {es} {ref}/search-aggregations-bucket-datehistogram-aggregation.html[date histogram] aggregation: +A common configuration for the x-axis is to use a {es} {ref}/search-aggregations-bucket-datehistogram-aggregation.html[date histogram] aggregation: [role="screenshot"] image::images/visualize-date-histogram.png[] @@ -58,5 +69,3 @@ Each visualization also has its own customization options. Most visualizations a [role="screenshot"] image::images/color-picker.png[An array of color dots that users can select,height=267] - -include::aggregations.asciidoc[] diff --git a/docs/visualize/regionmap.asciidoc b/docs/visualize/regionmap.asciidoc index c39282963ef7bc..accabd16e5fcdf 100644 --- a/docs/visualize/regionmap.asciidoc +++ b/docs/visualize/regionmap.asciidoc @@ -18,17 +18,18 @@ To create a region map, you configure an inner join that joins the result of an and a reference vector file based on a shared key. [float] -==== Data +[[region-map-aggregation]] +=== Supported aggregations -[float] -===== Metrics +Region maps support the following aggregations: -Select any of the supported _Metric_ or _Sibling Pipeline Aggregations_. +* <> -[float] -===== Buckets +* <> + +* <> -Configure a _Terms_ aggregation. The term is the _key_ that is used to join the results to the vector data on the map. +Use the _key_ term to join the results to the vector data on the map. [float] ==== Options diff --git a/docs/visualize/tilemap.asciidoc b/docs/visualize/tilemap.asciidoc index 2b499d098a956e..08cf666345e34d 100644 --- a/docs/visualize/tilemap.asciidoc +++ b/docs/visualize/tilemap.asciidoc @@ -17,36 +17,11 @@ in `kibana.yml`. [[coordinate-map-aggregation]] === Supported aggregations -Coordinate maps support the metric and bucket aggregations. +Coordinate maps support the following aggregations: -[float] -===== Metric aggregations - -The following metric aggregations are supported: - -{ref}/search-aggregations-metrics-valuecount-aggregation.html[Count]:: Returns a raw count of -the elements in the index pattern. The default metrics aggregation for a coordinate map is *Count*. - -{ref}/search-aggregations-metrics-avg-aggregation.html[Average]:: Returns the average of a numeric -field. - -{ref}/search-aggregations-metrics-sum-aggregation.html[Sum]:: Returns the total sum of a numeric -field. - -{ref}/search-aggregations-metrics-min-aggregation.html[Min]:: Returns the minimum value of a -numeric field. - -{ref}/search-aggregations-metrics-max-aggregation.html[Max]:: Returns the maximum value of a -numeric field. - -{ref}/search-aggregations-metrics-cardinality-aggregation.html[Unique Count]:: Returns -the number of unique values in a field. - -[float] -[[coordinate-bucket-aggregation]] -===== Bucket aggregation +* <> -Coordinate maps support the {ref}/search-aggregations-bucket-geohashgrid-aggregation.html[_geohash_] bucket aggregation. +* <> When you deselect *Change precision on map zoom*, the *Precision* slider appears. The *Precision* slider determines the granularity of the results displayed on the map. For details on the area specified by each precision level, refer to {ref}/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator[geohash grid]. diff --git a/docs/visualize/tsvb.asciidoc b/docs/visualize/tsvb.asciidoc index ff4160d1ac9d20..69d6985acd1e42 100644 --- a/docs/visualize/tsvb.asciidoc +++ b/docs/visualize/tsvb.asciidoc @@ -1,8 +1,8 @@ [[TSVB]] == TSVB -TSVB is a time series data visualizer that allows you to use the full power of the -Elasticsearch aggregation framework. With TSVB, you can combine an infinite +TSVB is a time series data visualizer that allows you to use the full power of the +Elasticsearch aggregation framework. With TSVB, you can combine an infinite number of aggregations to display complex data. NOTE: In Elasticsearch version 7.3.0 and later, the time series data visualizer is now referred to as TSVB instead of Time Series Visual Builder. @@ -43,6 +43,18 @@ Table:: Display data from multiple time series by defining the field group to sh [role="screenshot"] image:images/tsvb-table.png["Table visualization"] +[float] +[[tsvb-aggregation]] +=== Supported aggregations + +TSVB supports the following aggregations: + +* <> + +* <> + +* <> + [float] [[create-tsvb-visualization]] === Create TSVB visualizations @@ -60,7 +72,7 @@ To create a single metric, add multiple data series with multiple aggregations. . Specify the data series labels and colors. .. Select *Data*. -+ ++ If you are using the *Table* visualization, select *Columns*. .. In the *Label* field, enter a name for the data series, which is used on legends and titles. @@ -79,7 +91,7 @@ For series that are grouped by a term, you can specify a mustache variable of `{ .. To add another metric, click *+*. + -When you add more than one metric, the last metric value is displayed, which is indicated by the eye icon. +When you add more than one metric, the last metric value is displayed, which is indicated by the eye icon. . To specify the format and display options, select *Options*. @@ -95,7 +107,7 @@ Change the data that you want to display and choose the style options for the pa . Select *Panel options*. -. Under *Data*, specify how much of the data that you want to display in the visualization. +. Under *Data*, specify how much of the data that you want to display in the visualization. . Under *Style*, specify how you want the visualization to look. @@ -113,7 +125,7 @@ If you are using the Time Series visualization, add annotation data sources. [[tsvb-enter-markdown]] ==== Enter Markdown text -Edit the source for the Markdown visualization. +Edit the source for the Markdown visualization. . Select *Markdown*. diff --git a/package.json b/package.json index 430ab9e1ba77d7..9707d3863d295d 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,8 @@ "**/react": "^16.12.0", "**/react-test-renderer": "^16.12.0", "**/deepmerge": "^4.2.2", - "**/serialize-javascript": "^2.1.1" + "**/serialize-javascript": "^2.1.1", + "**/fast-deep-equal": "^3.1.1" }, "workspaces": { "packages": [ @@ -347,6 +348,7 @@ "@types/moment-timezone": "^0.5.12", "@types/mustache": "^0.8.31", "@types/node": "^10.12.27", + "@types/numeral": "^0.0.26", "@types/opn": "^5.1.0", "@types/pegjs": "^0.10.1", "@types/pngjs": "^3.3.2", diff --git a/packages/elastic-datemath/yarn.lock b/packages/elastic-datemath/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/elastic-datemath/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-babel-code-parser/yarn.lock b/packages/kbn-babel-code-parser/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-babel-code-parser/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-babel-preset/yarn.lock b/packages/kbn-babel-preset/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-babel-preset/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-dev-utils/yarn.lock b/packages/kbn-dev-utils/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-dev-utils/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-es/src/artifact.test.js b/packages/kbn-es/src/artifact.test.js index 985b65c7475634..453eb1a9a7689e 100644 --- a/packages/kbn-es/src/artifact.test.js +++ b/packages/kbn-es/src/artifact.test.js @@ -52,21 +52,22 @@ const createArchive = (params = {}) => { const mockFetch = mock => fetch.mockReturnValue(Promise.resolve(new Response(JSON.stringify(mock)))); -let previousSnapshotManifestValue = null; +const previousEnvVars = {}; +const ENV_VARS_TO_RESET = ['ES_SNAPSHOT_MANIFEST', 'KBN_ES_SNAPSHOT_USE_UNVERIFIED']; beforeAll(() => { - if ('ES_SNAPSHOT_MANIFEST' in process.env) { - previousSnapshotManifestValue = process.env.ES_SNAPSHOT_MANIFEST; - delete process.env.ES_SNAPSHOT_MANIFEST; - } + ENV_VARS_TO_RESET.forEach(key => { + if (key in process.env) { + previousEnvVars[key] = process.env[key]; + delete process.env[key]; + } + }); }); afterAll(() => { - if (previousSnapshotManifestValue !== null) { - process.env.ES_SNAPSHOT_MANIFEST = previousSnapshotManifestValue; - } else { - delete process.env.ES_SNAPSHOT_MANIFEST; - } + Object.keys(previousEnvVars).forEach(key => { + process.env[key] = previousEnvVars[key]; + }); }); beforeEach(() => { diff --git a/packages/kbn-es/yarn.lock b/packages/kbn-es/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-es/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-eslint-import-resolver-kibana/yarn.lock b/packages/kbn-eslint-import-resolver-kibana/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-eslint-import-resolver-kibana/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-eslint-plugin-eslint/yarn.lock b/packages/kbn-eslint-plugin-eslint/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-eslint-plugin-eslint/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-i18n/src/angular/directive.ts b/packages/kbn-i18n/src/angular/directive.ts index 8a4b724ec0629b..5d18a25be71f01 100644 --- a/packages/kbn-i18n/src/angular/directive.ts +++ b/packages/kbn-i18n/src/angular/directive.ts @@ -30,7 +30,13 @@ interface I18nScope extends IScope { const HTML_KEY_PREFIX = 'html_'; const PLACEHOLDER_SEPARATOR = '@I18N@'; -export function i18nDirective( +export const i18nDirective: [string, string, typeof i18nDirectiveFn] = [ + 'i18n', + '$sanitize', + i18nDirectiveFn, +]; + +function i18nDirectiveFn( i18n: I18nServiceType, $sanitize: (html: string) => string ): IDirective { diff --git a/packages/kbn-i18n/src/angular/filter.ts b/packages/kbn-i18n/src/angular/filter.ts index 2f7425a9dd8e0d..cc9da0aa51d301 100644 --- a/packages/kbn-i18n/src/angular/filter.ts +++ b/packages/kbn-i18n/src/angular/filter.ts @@ -19,7 +19,9 @@ import { I18nServiceType } from './provider'; -export function i18nFilter(i18n: I18nServiceType) { +export const i18nFilter: [string, typeof i18nFilterFn] = ['i18n', i18nFilterFn]; + +function i18nFilterFn(i18n: I18nServiceType) { return (id: string, { defaultMessage = '', values = {} } = {}) => { return i18n(id, { values, diff --git a/packages/kbn-i18n/src/loader.ts b/packages/kbn-i18n/src/loader.ts index 2d68079735c032..21f540f588f46f 100644 --- a/packages/kbn-i18n/src/loader.ts +++ b/packages/kbn-i18n/src/loader.ts @@ -17,15 +17,13 @@ * under the License. */ -import { readFile } from 'fs'; +import * as fs from 'fs'; import * as path from 'path'; import { promisify } from 'util'; import { unique } from './core/helper'; import { Translation } from './translation'; -const asyncReadFile = promisify(readFile); - const TRANSLATION_FILE_EXTENSION = '.json'; /** @@ -69,7 +67,8 @@ function getLocaleFromFileName(fullFileName: string) { * @returns */ async function loadFile(pathToFile: string): Promise { - return JSON.parse(await asyncReadFile(pathToFile, 'utf8')); + // doing this at the moment because fs is mocked in a lot of places where this would otherwise fail + return JSON.parse(await promisify(fs.readFile)(pathToFile, 'utf8')); } /** diff --git a/packages/kbn-i18n/yarn.lock b/packages/kbn-i18n/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-i18n/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-interpreter/yarn.lock b/packages/kbn-interpreter/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-interpreter/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-plugin-generator/yarn.lock b/packages/kbn-plugin-generator/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-plugin-generator/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-plugin-helpers/lib/plugin_config.js b/packages/kbn-plugin-helpers/lib/plugin_config.js index 07bbbfedc15da7..60baa7fc976607 100644 --- a/packages/kbn-plugin-helpers/lib/plugin_config.js +++ b/packages/kbn-plugin-helpers/lib/plugin_config.js @@ -32,7 +32,7 @@ module.exports = function(root) { 'yarn.lock', 'tsconfig.json', 'package.json', - 'index.js', + 'index.{js,ts}', '{lib,public,server,webpackShims,translations}/**/*', ]; diff --git a/packages/kbn-plugin-helpers/yarn.lock b/packages/kbn-plugin-helpers/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-plugin-helpers/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-pm/yarn.lock b/packages/kbn-pm/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-pm/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-spec-to-console/yarn.lock b/packages/kbn-spec-to-console/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-spec-to-console/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-storybook/yarn.lock b/packages/kbn-storybook/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-storybook/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-test/yarn.lock b/packages/kbn-test/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-test/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-ui-framework/yarn.lock b/packages/kbn-ui-framework/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-ui-framework/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js index 7a15c3bb742c0a..9a5fb479276f70 100644 --- a/packages/kbn-ui-shared-deps/entry.js +++ b/packages/kbn-ui-shared-deps/entry.js @@ -30,6 +30,9 @@ export const ElasticEui = require('@elastic/eui'); export const ElasticEuiLibServices = require('@elastic/eui/lib/services'); export const ElasticEuiLightTheme = require('@elastic/eui/dist/eui_theme_light.json'); export const ElasticEuiDarkTheme = require('@elastic/eui/dist/eui_theme_dark.json'); +export const KbnI18n = require('@kbn/i18n'); +export const KbnI18nAngular = require('@kbn/i18n/angular'); +export const KbnI18nReact = require('@kbn/i18n/react'); export const Moment = require('moment'); export const MomentTimezone = require('moment-timezone/moment-timezone'); export const React = require('react'); diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js index cef25295b35d74..5f5ac3f1c9c2ff 100644 --- a/packages/kbn-ui-shared-deps/index.js +++ b/packages/kbn-ui-shared-deps/index.js @@ -30,6 +30,9 @@ exports.externals = { '@elastic/eui/lib/services': '__kbnSharedDeps__.ElasticEuiLibServices', '@elastic/eui/dist/eui_theme_light.json': '__kbnSharedDeps__.ElasticEuiLightTheme', '@elastic/eui/dist/eui_theme_dark.json': '__kbnSharedDeps__.ElasticEuiDarkTheme', + '@kbn/i18n': '__kbnSharedDeps__.KbnI18n', + '@kbn/i18n/angular': '__kbnSharedDeps__.KbnI18nAngular', + '@kbn/i18n/react': '__kbnSharedDeps__.KbnI18nReact', jquery: '__kbnSharedDeps__.Jquery', moment: '__kbnSharedDeps__.Moment', 'moment-timezone': '__kbnSharedDeps__.MomentTimezone', diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 488f57b01e1687..47a47449927e49 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -12,6 +12,7 @@ "@elastic/eui": "18.2.1", "@elastic/charts": "^16.1.0", "@kbn/dev-utils": "1.0.0", + "@kbn/i18n": "1.0.0", "@yarnpkg/lockfile": "^1.1.0", "abortcontroller-polyfill": "^1.3.0", "angular": "^1.7.9", diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 36bbc8cc828735..83a41a52aca381 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -21,7 +21,17 @@ import { PromiseType } from 'utility-types'; export { $Values, Required, Optional, Class } from 'utility-types'; /** - * Returns wrapped type of a promise. + * A type that may or may not be a `Promise`. + */ +export type MaybePromise = T | Promise; + +/** + * Converts a type to a `Promise`, unless it is already a `Promise`. Useful when proxying the return value of a possibly async function. + */ +export type ShallowPromise = T extends Promise ? Promise : Promise; + +/** + * Returns wrapped type of a `Promise`. */ export type UnwrapPromise> = PromiseType; @@ -39,11 +49,6 @@ export type UnwrapObservable> = T extends Observab ? U : never; -/** - * Converts a type to a `Promise`, unless it is already a `Promise`. Useful when proxying the return value of a possibly async function. - */ -export type ShallowPromise = T extends Promise ? Promise : Promise; - /** * Ensures T is of type X. */ diff --git a/packages/kbn-utility-types/yarn.lock b/packages/kbn-utility-types/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-utility-types/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/renovate.json5 b/renovate.json5 index 5af62d0acef854..6764ed38ba4cf0 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -657,6 +657,14 @@ '@types/nodemailer', ], }, + { + groupSlug: 'numeral', + groupName: 'numeral related packages', + packageNames: [ + 'numeral', + '@types/numeral', + ], + }, { groupSlug: 'object-hash', groupName: 'object-hash related packages', diff --git a/scripts/check_lockfile_symlinks.js b/scripts/check_lockfile_symlinks.js new file mode 100644 index 00000000000000..b41a354da83f17 --- /dev/null +++ b/scripts/check_lockfile_symlinks.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); +require('../src/dev/run_check_lockfile_symlinks'); diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index f51afd35586bd7..f8699364fa9e28 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1193,10 +1193,11 @@ In server code, `core` can be accessed from either `server.newPlatform` or `kbnS | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | | `server.config()` | [`initializerContext.config.create()`](/docs/development/core/server/kibana-plugin-server.plugininitializercontext.config.md) | Must also define schema. See _[how to configure plugin](#configure-plugin)_ | | `server.route` | [`core.http.createRouter`](/docs/development/core/server/kibana-plugin-server.httpservicesetup.createrouter.md) | [Examples](./MIGRATION_EXAMPLES.md#route-registration) | +| `server.renderApp()` / `server.renderAppWithDefaultConfig()` | [`context.rendering.render()`](/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.render.md) | [Examples](./MIGRATION_EXAMPLES.md#render-html-content) | | `request.getBasePath()` | [`core.http.basePath.get`](/docs/development/core/server/kibana-plugin-server.httpservicesetup.basepath.md) | | | `server.plugins.elasticsearch.getCluster('data')` | [`context.elasticsearch.dataClient`](/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md) | | | `server.plugins.elasticsearch.getCluster('admin')` | [`context.elasticsearch.adminClient`](/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md) | | -| `server.plugins.elasticsearch.createCluster(...)` | [`core.elasticsearch.createClient`](/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.createclient.md) | | +| `server.plugins.elasticsearch.createCluster(...)` | [`core.elasticsearch.createClient`](/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.createclient.md) | | | `server.savedObjects.setScopedSavedObjectsClientFactory` | [`core.savedObjects.setClientFactory`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.setclientfactory.md) | | | `server.savedObjects.addScopedSavedObjectsClientWrapperFactory` | [`core.savedObjects.addClientWrapper`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md) | | | `server.savedObjects.getSavedObjectsRepository` | [`core.savedObjects.createInternalRepository`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.createinternalrepository.md) [`core.savedObjects.createScopedRepository`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.createscopedrepository.md) | | @@ -1230,8 +1231,8 @@ This table shows where these uiExports have moved to in the New Platform. In mos | `docViews` | | | | `embeddableActions` | | Should be an API on the embeddables plugin. | | `embeddableFactories` | | Should be an API on the embeddables plugin. | -| `fieldFormatEditors` | | | -| `fieldFormats` | | | +| `fieldFormatEditors` | | | +| `fieldFormats` | [`plugins.data.fieldFormats`](./src/plugins/data/public/field_formats) | | | `hacks` | n/a | Just run the code in your plugin's `start` method. | | `home` | [`plugins.home.featureCatalogue.register`](./src/plugins/home/public/feature_catalogue) | Must add `home` as a dependency in your kibana.json. | | `indexManagement` | | Should be an API on the indexManagement plugin. | diff --git a/src/core/MIGRATION_EXAMPLES.md b/src/core/MIGRATION_EXAMPLES.md index d7964a53358efc..568980f50117df 100644 --- a/src/core/MIGRATION_EXAMPLES.md +++ b/src/core/MIGRATION_EXAMPLES.md @@ -16,7 +16,9 @@ APIs to their New Platform equivalents. - [Accessing Services](#accessing-services) - [Chrome](#chrome) - [Updating an application navlink](#updating-application-navlink) - + - [Chromeless Applications](#chromeless-applications) + - [Render HTML Content](#render-html-content) + ## Configuration ### Declaring config schema @@ -386,7 +388,7 @@ class Plugin { }), } }, - router.wrapErrors((context, req, res) => { + router.handleLegacyErrors((context, req, res) => { throw Boom.notFound('not there'); // will be converted into proper New Platform error }) ) @@ -518,4 +520,83 @@ export class MyPlugin implements Plugin { }, }); } -``` \ No newline at end of file +``` + +## Chromeless Applications + +In Kibana, a "chromeless" application is one where the primary Kibana UI components +such as header or navigation can be hidden. In the legacy platform these were referred to +as "hidden" applications, and were set via the `hidden` property in a Kibana plugin. +Chromeless applications are also not displayed in the left navbar. + +To mark an application as chromeless, specify `chromeless: false` when registering your application +to hide the chrome UI when the application is mounted: + +```ts +application.register({ + id: 'chromeless', + chromeless: true, + async mount(context, params) { + /* ... */ + }, +}); +``` + +If you wish to render your application at a route that does not follow the `/app/${appId}` pattern, +this can be done via the `appRoute` property. Doing this currently requires you to register a server +route where you can return a bootstrapped HTML page for your application bundle. Instructions on +registering this server route is covered in the next section: [Render HTML Content](#render-html-content). + +```ts +application.register({ + id: 'chromeless', + appRoute: '/chromeless', + chromeless: true, + async mount(context, params) { + /* ... */ + }, +}); +``` + +## Render HTML Content + +You can return a blank HTML page bootstrapped with the core application bundle from an HTTP route handler +via the `rendering` context. You may wish to do this if you are rendering a chromeless application with a +custom application route or have other custom rendering needs. + +```ts +router.get( + { path: '/chromeless', validate: false }, + (context, request, response) => { + const { http, rendering } = context.core; + + return response.ok({ + body: await rendering.render(), // generates an HTML document + headers: { + 'content-security-policy': http.csp.header, + }, + }); + } +); +``` + +You can also specify to exclude user data from the bundle metadata. User data +comprises all UI Settings that are *user provided*, then injected into the page. +You may wish to exclude fetching this data if not authorized or to slim the page +size. + +```ts +router.get( + { path: '/', validate: false }, + (context, request, response) => { + const { http, rendering } = context.core; + + return response.ok({ + body: await rendering.render({ includeUserSettings: false }), + headers: { + 'content-security-policy': http.csp.header, + }, + }); + } +); +``` diff --git a/src/core/PRINCIPLES.md b/src/core/PRINCIPLES.md new file mode 100644 index 00000000000000..fa832a59a3b12d --- /dev/null +++ b/src/core/PRINCIPLES.md @@ -0,0 +1,47 @@ +## Common dictionary +Plugin - a piece of software expressing specific subject of the business unit within the code. + +Platform - functionality required to run all the Kibana plugins. + +## New platform principles +### Explicit business domains separation +The plugins code should be structured on the top level to reflect business units. +```js +// GOOD +src/plugins + - apm + - server + - public + - search + .. +// BAD +src/plugins + - server + - apm + - search +``` +### Explicit dependencies +Each plugin should declare dependencies on the other plugins explicitly. Plugins cannot have circular dependencies. Plugins shouldn't access runtime objects, HTTP endpoints, DOM nodes, etc. created by a third party plugin without declaring a dependency on this plugin. +```json +"requiredPlugins": ["search"], +"optionalPlugins": ["apm"], +``` +### Explicit API declaration +Each plugin has to define an explicit API. Any other API's that has not been declared explicitly as public should be considered private. HTTP endpoints belonging to other plugins are considered private. Plugins should expose a JavaScript client on top of these HTTP endpoints for other plugins to consume. +```js +// GOOD +deps.plugin.getData(); +// BAD. +`GET /api/plugin/data` +``` +### Encapsulated state +Each plugin encapsulates its internal state. It doesn't rely on any kind of global state. Plugins provide an internal state via explicit API, reflecting the dynamic nature of the state (an event bus, observables, getter/setter functions). A plugin can change other plugin state by calling its public API method. +```js +// GOOD +deps.plugin.getData(); +deps.plugin.data$.subscribe(); +deps.plugin.setAddress('...'); +// BAD. +deps.plugin._data; +deps.plugin.data = '...'; +``` diff --git a/src/core/TESTING.md b/src/core/TESTING.md index 6139820d02a14a..467110b3874b8b 100644 --- a/src/core/TESTING.md +++ b/src/core/TESTING.md @@ -247,8 +247,3 @@ _How to test against specific plugin APIs (eg. data plugin)_ ## Plugin Contracts _How to test your plugin's exposed API_ - -Guidelines: -- Plugins should never interact with other plugins' REST API directly -- Plugins should interact with other plugins via JavaScript contracts -- Exposed contracts need to be well tested to ensure breaking changes are detected easily diff --git a/src/core/public/application/application_service.test.ts b/src/core/public/application/application_service.test.ts index 54489fbd182b47..8757f73a1206ca 100644 --- a/src/core/public/application/application_service.test.ts +++ b/src/core/public/application/application_service.test.ts @@ -19,7 +19,7 @@ import { createElement } from 'react'; import { BehaviorSubject, Subject } from 'rxjs'; -import { bufferCount, skip, take, takeUntil } from 'rxjs/operators'; +import { bufferCount, take, takeUntil } from 'rxjs/operators'; import { shallow } from 'enzyme'; import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; @@ -518,6 +518,22 @@ describe('#start()', () => { expect([...availableApps.keys()]).toEqual(['app1', 'legacyApp1']); }); + describe('currentAppId$', () => { + it('emits the legacy app id when in legacy mode', async () => { + setupDeps.injectedMetadata.getLegacyMode.mockReturnValue(true); + setupDeps.injectedMetadata.getLegacyMetadata.mockReturnValue({ + app: { + id: 'legacy', + title: 'Legacy App', + }, + } as any); + await service.setup(setupDeps); + const { currentAppId$ } = await service.start(startDeps); + + expect(await currentAppId$.pipe(take(1)).toPromise()).toEqual('legacy'); + }); + }); + describe('getComponent', () => { it('returns renderable JSX tree', async () => { service.setup(setupDeps); @@ -651,7 +667,7 @@ describe('#start()', () => { const { currentAppId$, navigateToApp } = await service.start(startDeps); const stop$ = new Subject(); - const promise = currentAppId$.pipe(skip(1), bufferCount(4), takeUntil(stop$)).toPromise(); + const promise = currentAppId$.pipe(bufferCount(4), takeUntil(stop$)).toPromise(); await navigateToApp('alpha'); await navigateToApp('beta'); diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx index 4d714c8f9dad2d..511f348e118230 100644 --- a/src/core/public/application/application_service.tsx +++ b/src/core/public/application/application_service.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'; -import { map, shareReplay, takeUntil } from 'rxjs/operators'; +import { map, shareReplay, takeUntil, distinctUntilChanged, filter } from 'rxjs/operators'; import { createBrowserHistory, History } from 'history'; import { InjectedMetadataSetup } from '../injected_metadata'; @@ -114,8 +114,10 @@ export class ApplicationService { history, }: SetupDeps): InternalApplicationSetup { const basename = basePath.get(); - // Only setup history if we're not in legacy mode - if (!injectedMetadata.getLegacyMode()) { + if (injectedMetadata.getLegacyMode()) { + this.currentAppId$.next(injectedMetadata.getLegacyMetadata().app.id); + } else { + // Only setup history if we're not in legacy mode this.history = history || createBrowserHistory({ basename }); } @@ -264,7 +266,11 @@ export class ApplicationService { return { applications$, capabilities, - currentAppId$: this.currentAppId$.pipe(takeUntil(this.stop$)), + currentAppId$: this.currentAppId$.pipe( + filter(appId => appId !== undefined), + distinctUntilChanged(), + takeUntil(this.stop$) + ), registerMountContext: this.mountContext.registerContext, getUrlForApp: (appId, { path }: { path?: string } = {}) => getAppUrl(availableMounters, appId, path), diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx index 4d83ab67810afa..0c5f5a138d58f5 100644 --- a/src/core/public/application/integration_tests/router.test.tsx +++ b/src/core/public/application/integration_tests/router.test.tsx @@ -23,7 +23,7 @@ import { createMemoryHistory, History, createHashHistory } from 'history'; import { AppRouter, AppNotFound } from '../ui'; import { EitherApp, MockedMounterMap, MockedMounterTuple } from '../test_types'; -import { createRenderer, createAppMounter, createLegacyAppMounter } from './utils'; +import { createRenderer, createAppMounter, createLegacyAppMounter, getUnmounter } from './utils'; import { AppStatus } from '../types'; describe('AppContainer', () => { @@ -36,7 +36,6 @@ describe('AppContainer', () => { history.push(path); return update(); }; - const mockMountersToMounters = () => new Map([...mounters].map(([appId, { mounter }]) => [appId, mounter])); const setAppLeaveHandlerMock = () => undefined; @@ -58,7 +57,8 @@ describe('AppContainer', () => { createLegacyAppMounter('legacyApp1', jest.fn()), createAppMounter('app2', '

App 2
'), createLegacyAppMounter('baseApp:legacyApp2', jest.fn()), - createAppMounter('app3', '
App 3
', '/custom/path'), + createAppMounter('app3', '
Chromeless A
', '/chromeless-a/path'), + createAppMounter('app4', '
Chromeless B
', '/chromeless-b/path'), createAppMounter('disabledApp', '
Disabled app
'), createLegacyAppMounter('disabledLegacyApp', jest.fn()), ] as Array>); @@ -75,23 +75,24 @@ describe('AppContainer', () => { }); it('calls mount handler and returned unmount function when navigating between apps', async () => { - const dom1 = await navigate('/app/app1'); const app1 = mounters.get('app1')!; + const app2 = mounters.get('app2')!; + let dom = await navigate('/app/app1'); expect(app1.mounter.mount).toHaveBeenCalled(); - expect(dom1?.html()).toMatchInlineSnapshot(` + expect(dom?.html()).toMatchInlineSnapshot(` "
basename: /app/app1 html: App 1
" `); - const app1Unmount = await app1.mounter.mount.mock.results[0].value; - const dom2 = await navigate('/app/app2'); + const app1Unmount = await getUnmounter(app1); + dom = await navigate('/app/app2'); expect(app1Unmount).toHaveBeenCalled(); - expect(mounters.get('app2')!.mounter.mount).toHaveBeenCalled(); - expect(dom2?.html()).toMatchInlineSnapshot(` + expect(app2.mounter.mount).toHaveBeenCalled(); + expect(dom?.html()).toMatchInlineSnapshot(` "
basename: /app/app2 html:
App 2
@@ -99,6 +100,82 @@ describe('AppContainer', () => { `); }); + it('can navigate between standard application and one with custom appRoute', async () => { + const standardApp = mounters.get('app1')!; + const chromelessApp = mounters.get('app3')!; + let dom = await navigate('/app/app1'); + + expect(standardApp.mounter.mount).toHaveBeenCalled(); + expect(dom?.html()).toMatchInlineSnapshot(` + "
+ basename: /app/app1 + html: App 1 +
" + `); + + const standardAppUnmount = await getUnmounter(standardApp); + dom = await navigate('/chromeless-a/path'); + + expect(standardAppUnmount).toHaveBeenCalled(); + expect(chromelessApp.mounter.mount).toHaveBeenCalled(); + expect(dom?.html()).toMatchInlineSnapshot(` + "
+ basename: /chromeless-a/path + html:
Chromeless A
+
" + `); + + const chromelessAppUnmount = await getUnmounter(standardApp); + dom = await navigate('/app/app1'); + + expect(chromelessAppUnmount).toHaveBeenCalled(); + expect(standardApp.mounter.mount).toHaveBeenCalledTimes(2); + expect(dom?.html()).toMatchInlineSnapshot(` + "
+ basename: /app/app1 + html: App 1 +
" + `); + }); + + it('can navigate between two applications with custom appRoutes', async () => { + const chromelessAppA = mounters.get('app3')!; + const chromelessAppB = mounters.get('app4')!; + let dom = await navigate('/chromeless-a/path'); + + expect(chromelessAppA.mounter.mount).toHaveBeenCalled(); + expect(dom?.html()).toMatchInlineSnapshot(` + "
+ basename: /chromeless-a/path + html:
Chromeless A
+
" + `); + + const chromelessAppAUnmount = await getUnmounter(chromelessAppA); + dom = await navigate('/chromeless-b/path'); + + expect(chromelessAppAUnmount).toHaveBeenCalled(); + expect(chromelessAppB.mounter.mount).toHaveBeenCalled(); + expect(dom?.html()).toMatchInlineSnapshot(` + "
+ basename: /chromeless-b/path + html:
Chromeless B
+
" + `); + + const chromelessAppBUnmount = await getUnmounter(chromelessAppB); + dom = await navigate('/chromeless-a/path'); + + expect(chromelessAppBUnmount).toHaveBeenCalled(); + expect(chromelessAppA.mounter.mount).toHaveBeenCalledTimes(2); + expect(dom?.html()).toMatchInlineSnapshot(` + "
+ basename: /chromeless-a/path + html:
Chromeless A
+
" + `); + }); + it('should not mount when partial route path matches', async () => { mounters.set(...createAppMounter('spaces', '
Custom Space
', '/spaces/fake-login')); mounters.set(...createAppMounter('login', '
Login Page
', '/fake-login')); diff --git a/src/core/public/application/integration_tests/utils.tsx b/src/core/public/application/integration_tests/utils.tsx index 6367d1fa12697e..4f34438fc822a3 100644 --- a/src/core/public/application/integration_tests/utils.tsx +++ b/src/core/public/application/integration_tests/utils.tsx @@ -23,7 +23,7 @@ import { mount } from 'enzyme'; import { I18nProvider } from '@kbn/i18n/react'; import { App, LegacyApp, AppMountParameters } from '../types'; -import { MockedMounter, MockedMounterTuple } from '../test_types'; +import { EitherApp, MockedMounter, MockedMounterTuple, Mountable } from '../test_types'; type Dom = ReturnType | null; type Renderer = () => Dom | Promise; @@ -80,3 +80,7 @@ export const createLegacyAppMounter = ( unmount: jest.fn(), }, ]; + +export function getUnmounter(app: Mountable) { + return app.mounter.mount.mock.results[0].value; +} diff --git a/src/core/public/application/test_types.ts b/src/core/public/application/test_types.ts index 3d992cb950eb42..b822597e510cb9 100644 --- a/src/core/public/application/test_types.ts +++ b/src/core/public/application/test_types.ts @@ -26,18 +26,19 @@ export type ApplicationServiceContract = PublicMethodsOf; export type EitherApp = App | LegacyApp; /** @internal */ export type MockedUnmount = jest.Mocked; + +/** @internal */ +export interface Mountable { + mounter: MockedMounter; + unmount: MockedUnmount; +} + /** @internal */ export type MockedMounter = jest.Mocked>>; /** @internal */ -export type MockedMounterTuple = [ - string, - { mounter: MockedMounter; unmount: MockedUnmount } -]; +export type MockedMounterTuple = [string, Mountable]; /** @internal */ -export type MockedMounterMap = Map< - string, - { mounter: MockedMounter; unmount: MockedUnmount } ->; +export type MockedMounterMap = Map>; /** @internal */ export type MockLifecycle< T extends keyof ApplicationService, diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index 0d955482d2226c..63e542b0127ed1 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -31,6 +31,7 @@ import { PluginOpaqueId } from '../plugins'; import { IUiSettingsClient } from '../ui_settings'; import { RecursiveReadonly } from '../../utils'; import { SavedObjectsStart } from '../saved_objects'; +import { AppCategory } from '../../types'; /** @public */ export interface AppBase { @@ -44,6 +45,13 @@ export interface AppBase { */ title: string; + /** + * The category definition of the product + * See {@link AppCategory} + * See DEFAULT_APP_CATEGORIES for more reference + */ + category?: AppCategory; + /** * The initial status of the application. * Defaulting to `accessible` diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index 6a630608b2c205..66c837d238276c 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -45,7 +45,6 @@ export const AppContainer: FunctionComponent = ({ const [appNotFound, setAppNotFound] = useState(false); const elementRef = useRef(null); const unmountRef: MutableRefObject = useRef(null); - // const appStatus = useObservable(appStatus$); useLayoutEffect(() => { const unmount = () => { diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index abd04722a49f20..9018b219736345 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -29,6 +29,7 @@ import { notificationServiceMock } from '../notifications/notifications_service. import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { ChromeService } from './chrome_service'; import { App } from '../application'; +import { uiSettingsServiceMock } from '../ui_settings/ui_settings_service.mock'; class FakeApp implements App { public title = `${this.id} App`; @@ -51,6 +52,7 @@ function defaultStartDeps(availableApps?: App[]) { http: httpServiceMock.createStartContract(), injectedMetadata: injectedMetadataServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), + uiSettings: uiSettingsServiceMock.createStartContract(), }; if (availableApps) { diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 09ea1afe35766c..6ab9fe158742a6 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -38,7 +38,7 @@ import { LoadingIndicator, HeaderWrapper as Header } from './ui'; import { DocLinksStart } from '../doc_links'; import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu'; import { KIBANA_ASK_ELASTIC_LINK } from './constants'; - +import { IUiSettingsClient } from '../ui_settings'; export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; const IS_COLLAPSED_KEY = 'core.chrome.isCollapsed'; @@ -85,6 +85,7 @@ interface StartDeps { http: HttpStart; injectedMetadata: InjectedMetadataStart; notifications: NotificationsStart; + uiSettings: IUiSettingsClient; } /** @internal */ @@ -139,6 +140,7 @@ export class ChromeService { http, injectedMetadata, notifications, + uiSettings, }: StartDeps): Promise { this.initVisibility(application); @@ -173,7 +175,6 @@ export class ChromeService { getHeaderComponent: () => ( -
), diff --git a/src/core/public/chrome/nav_links/nav_link.ts b/src/core/public/chrome/nav_links/nav_link.ts index 3b16c030ddcc93..4d3a1e9ecd1991 100644 --- a/src/core/public/chrome/nav_links/nav_link.ts +++ b/src/core/public/chrome/nav_links/nav_link.ts @@ -18,6 +18,7 @@ */ import { pick } from '../../../utils'; +import { AppCategory } from '../../'; /** * @public @@ -33,6 +34,11 @@ export interface ChromeNavLink { */ readonly title: string; + /** + * The category the app lives in + */ + readonly category?: AppCategory; + /** * The base route used to open the root of an application. */ diff --git a/src/core/public/chrome/ui/header/__snapshots__/nav_drawer.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/nav_drawer.test.tsx.snap new file mode 100644 index 00000000000000..0ebc44ba67862a --- /dev/null +++ b/src/core/public/chrome/ui/header/__snapshots__/nav_drawer.test.tsx.snap @@ -0,0 +1,5224 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NavDrawer Advanced setting set to grouped renders grouped items 1`] = ` + + + + + + + +`; + +exports[`NavDrawer Advanced setting set to grouped renders individual items if there are less than 7 1`] = ` + + + + + + + +`; + +exports[`NavDrawer Advanced setting set to grouped renders individual items if there is only 1 category 1`] = ` + + + + + + + +`; + +exports[`NavDrawer Advanced setting set to individual renders individual items 1`] = ` + + + + + + + +`; diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index d05a6bb53405c5..c3cefd180b16f6 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -17,141 +17,40 @@ * under the License. */ -import Url from 'url'; - -import React, { Component, createRef } from 'react'; -import * as Rx from 'rxjs'; - import { - // TODO: add type annotations EuiHeader, - EuiHeaderLogo, EuiHeaderSection, EuiHeaderSectionItem, EuiHeaderSectionItemButton, - EuiHorizontalRule, EuiIcon, - EuiImage, // @ts-ignore EuiNavDrawer, // @ts-ignore - EuiNavDrawerGroup, - // @ts-ignore EuiShowFor, } from '@elastic/eui'; - import { i18n } from '@kbn/i18n'; -import { InjectedIntl, injectI18n } from '@kbn/i18n/react'; - -import { HeaderBadge } from './header_badge'; -import { HeaderBreadcrumbs } from './header_breadcrumbs'; -import { HeaderHelpMenu } from './header_help_menu'; -import { HeaderNavControls } from './header_nav_controls'; - +import React, { Component, createRef } from 'react'; +import * as Rx from 'rxjs'; import { ChromeBadge, ChromeBreadcrumb, + ChromeNavControl, ChromeNavLink, ChromeRecentlyAccessedHistoryItem, - ChromeNavControl, } from '../..'; +import { InternalApplicationStart } from '../../../application/types'; import { HttpStart } from '../../../http'; import { ChromeHelpExtension } from '../../chrome_service'; -import { InternalApplicationStart } from '../../../application/types'; - -// Providing a buffer between the limit and the cut off index -// protects from truncating just the last couple (6) characters -const TRUNCATE_LIMIT: number = 64; -const TRUNCATE_AT: number = 58; - -/** - * - * @param {string} url - a relative or root relative url. If a relative path is given then the - * absolute url returned will depend on the current page where this function is called from. For example - * if you are on page "http://www.mysite.com/shopping/kids" and you pass this function "adults", you would get - * back "http://www.mysite.com/shopping/adults". If you passed this function a root relative path, or one that - * starts with a "/", for example "/account/cart", you would get back "http://www.mysite.com/account/cart". - * @return {string} the relative url transformed into an absolute url - */ -function relativeToAbsolute(url: string) { - // convert all link urls to absolute urls - const a = document.createElement('a'); - a.setAttribute('href', url); - return a.href; -} - -function extendRecentlyAccessedHistoryItem( - navLinks: ChromeNavLink[], - recentlyAccessed: ChromeRecentlyAccessedHistoryItem, - basePath: HttpStart['basePath'] -) { - const href = relativeToAbsolute(basePath.prepend(recentlyAccessed.link)); - const navLink = navLinks.find(nl => href.startsWith(nl.subUrlBase || nl.baseUrl)); - - let titleAndAriaLabel = recentlyAccessed.label; - if (navLink) { - const objectTypeForAriaAppendix = navLink.title; - titleAndAriaLabel = i18n.translate('core.ui.recentLinks.linkItem.screenReaderLabel', { - defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}', - values: { - recentlyAccessedItemLinklabel: recentlyAccessed.label, - pageType: objectTypeForAriaAppendix, - }, - }); - } - - return { - ...recentlyAccessed, - href, - euiIconType: navLink ? navLink.euiIconType : undefined, - title: titleAndAriaLabel, - }; -} - -function extendNavLink(navLink: ChromeNavLink) { - if (navLink.legacy) { - return { - ...navLink, - href: navLink.url && !navLink.active ? navLink.url : navLink.baseUrl, - }; - } - - return { - ...navLink, - href: navLink.baseUrl, - }; -} - -function isModifiedEvent(event: MouseEvent) { - return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); -} - -function findClosestAnchor(element: HTMLElement): HTMLAnchorElement | void { - let current = element; - while (current) { - if (current.tagName === 'A') { - return current as HTMLAnchorElement; - } - - if (!current.parentElement || current.parentElement === document.body) { - return undefined; - } - - current = current.parentElement; - } -} - -function truncateRecentItemLabel(label: string): string { - if (label.length > TRUNCATE_LIMIT) { - label = `${label.substring(0, TRUNCATE_AT)}…`; - } - - return label; -} - -export type HeaderProps = Pick>; +import { HeaderBadge } from './header_badge'; +import { NavSetting, OnIsLockedUpdate } from './'; +import { HeaderBreadcrumbs } from './header_breadcrumbs'; +import { HeaderHelpMenu } from './header_help_menu'; +import { HeaderNavControls } from './header_nav_controls'; +import { euiNavLink } from './nav_link'; +import { HeaderLogo } from './header_logo'; +import { NavDrawer } from './nav_drawer'; -interface Props { +export interface HeaderProps { kibanaVersion: string; application: InternalApplicationStart; appTitle$: Rx.Observable; @@ -168,28 +67,29 @@ interface Props { legacyMode: boolean; navControlsLeft$: Rx.Observable; navControlsRight$: Rx.Observable; - intl: InjectedIntl; basePath: HttpStart['basePath']; isLocked?: boolean; - onIsLockedUpdate?: (isLocked: boolean) => void; + navSetting$: Rx.Observable; + onIsLockedUpdate?: OnIsLockedUpdate; } interface State { appTitle: string; - currentAppId?: string; isVisible: boolean; - navLinks: ReadonlyArray>; - recentlyAccessed: ReadonlyArray>; + navLinks: ChromeNavLink[]; + recentlyAccessed: ChromeRecentlyAccessedHistoryItem[]; forceNavigation: boolean; navControlsLeft: readonly ChromeNavControl[]; navControlsRight: readonly ChromeNavControl[]; + navSetting: NavSetting; + currentAppId: string | undefined; } -class HeaderUI extends Component { +export class Header extends Component { private subscription?: Rx.Subscription; private navDrawerRef = createRef(); - constructor(props: Props) { + constructor(props: HeaderProps) { super(props); this.state = { @@ -200,6 +100,8 @@ class HeaderUI extends Component { forceNavigation: false, navControlsLeft: [], navControlsRight: [], + navSetting: 'grouped', + currentAppId: '', }; } @@ -214,7 +116,8 @@ class HeaderUI extends Component { Rx.combineLatest( this.props.navControlsLeft$, this.props.navControlsRight$, - this.props.application.currentAppId$ + this.props.application.currentAppId$, + this.props.navSetting$ ) ).subscribe({ next: ([ @@ -223,18 +126,17 @@ class HeaderUI extends Component { forceNavigation, navLinks, recentlyAccessed, - [navControlsLeft, navControlsRight, currentAppId], + [navControlsLeft, navControlsRight, currentAppId, navSetting], ]) => { this.setState({ appTitle, isVisible, forceNavigation, - navLinks: navLinks.map(extendNavLink), - recentlyAccessed: recentlyAccessed.map(ra => - extendRecentlyAccessedHistoryItem(navLinks, ra, this.props.basePath) - ), + navLinks: navLinks.filter(navLink => !navLink.hidden), + recentlyAccessed, navControlsLeft, navControlsRight, + navSetting, currentAppId, }); }, @@ -247,26 +149,12 @@ class HeaderUI extends Component { } } - public renderLogo() { - const { homeHref, intl } = this.props; - return ( - - ); - } - public renderMenuTrigger() { return ( this.navDrawerRef.current.toggleOpen()} > @@ -275,98 +163,29 @@ class HeaderUI extends Component { } public render() { + const { appTitle, isVisible, navControlsLeft, navControlsRight } = this.state; const { - application, badge$, - basePath, breadcrumbs$, helpExtension$, helpSupportUrl$, - intl, - isLocked, kibanaDocLink, kibanaVersion, - onIsLockedUpdate, - legacyMode, } = this.props; - const { - appTitle, - currentAppId, - isVisible, - navControlsLeft, - navControlsRight, - navLinks, - recentlyAccessed, - } = this.state; + const navLinks = this.state.navLinks.map(link => + euiNavLink( + link, + this.props.legacyMode, + this.state.currentAppId, + this.props.basePath, + this.props.application.navigateToApp + ) + ); if (!isVisible) { return null; } - const navLinksArray = navLinks - .filter(navLink => !navLink.hidden) - .map(navLink => ({ - key: navLink.id, - label: navLink.tooltip ?? navLink.title, - - // Use href and onClick to support "open in new tab" and SPA navigation in the same link - href: navLink.href, - onClick: (event: MouseEvent) => { - if ( - !legacyMode && // ignore when in legacy mode - !navLink.legacy && // ignore links to legacy apps - !event.defaultPrevented && // onClick prevented default - event.button === 0 && // ignore everything but left clicks - !isModifiedEvent(event) // ignore clicks with modifier keys - ) { - event.preventDefault(); - application.navigateToApp(navLink.id); - } - }, - - // Legacy apps use `active` property, NP apps should match the current app - isActive: navLink.active || currentAppId === navLink.id, - isDisabled: navLink.disabled, - - iconType: navLink.euiIconType, - icon: - !navLink.euiIconType && navLink.icon ? ( - - ) : ( - undefined - ), - 'data-test-subj': 'navDrawerAppsMenuLink', - })); - - const recentLinksArray = [ - { - label: intl.formatMessage({ - id: 'core.ui.chrome.sideGlobalNav.viewRecentItemsLabel', - defaultMessage: 'Recently viewed', - }), - iconType: 'clock', - isDisabled: recentlyAccessed.length > 0 ? false : true, - flyoutMenu: { - title: intl.formatMessage({ - id: 'core.ui.chrome.sideGlobalNav.viewRecentItemsFlyoutTitle', - defaultMessage: 'Recent items', - }), - listItems: recentlyAccessed.map(item => ({ - label: truncateRecentItemLabel(item.label), - title: item.title, - 'aria-label': item.title, - href: item.href, - iconType: item.euiIconType, - })), - }, - }, - ]; - return (
@@ -375,7 +194,13 @@ class HeaderUI extends Component { {this.renderMenuTrigger()} - {this.renderLogo()} + + + @@ -399,75 +224,17 @@ class HeaderUI extends Component { - - - - - - + />
); } - - private onNavClick = (event: React.MouseEvent) => { - const anchor = findClosestAnchor((event as any).nativeEvent.target); - if (!anchor) { - return; - } - - const navLink = this.state.navLinks.find(item => item.href === anchor.href); - if (navLink && navLink.disabled) { - event.preventDefault(); - return; - } - - if ( - !this.state.forceNavigation || - event.isDefaultPrevented() || - event.altKey || - event.metaKey || - event.ctrlKey - ) { - return; - } - - const toParsed = Url.parse(anchor.href); - const fromParsed = Url.parse(document.location.href); - const sameProto = toParsed.protocol === fromParsed.protocol; - const sameHost = toParsed.host === fromParsed.host; - const samePath = toParsed.path === fromParsed.path; - - if (sameProto && sameHost && samePath) { - if (toParsed.hash) { - document.location.reload(); - } - - // event.preventDefault() keeps the browser from seeing the new url as an update - // and even setting window.location does not mimic that behavior, so instead - // we use stopPropagation() to prevent angular from seeing the click and - // starting a digest cycle/attempting to handle it in the router. - event.stopPropagation(); - } - }; } - -export const Header = injectI18n(HeaderUI); diff --git a/src/core/public/chrome/ui/header/header_logo.tsx b/src/core/public/chrome/ui/header/header_logo.tsx new file mode 100644 index 00000000000000..793b8646dabf78 --- /dev/null +++ b/src/core/public/chrome/ui/header/header_logo.tsx @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Url from 'url'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiHeaderLogo } from '@elastic/eui'; +import { NavLink } from './nav_link'; + +function findClosestAnchor(element: HTMLElement): HTMLAnchorElement | void { + let current = element; + while (current) { + if (current.tagName === 'A') { + return current as HTMLAnchorElement; + } + + if (!current.parentElement || current.parentElement === document.body) { + return undefined; + } + + current = current.parentElement; + } +} + +function onClick( + event: React.MouseEvent, + forceNavigation: boolean, + navLinks: NavLink[] +) { + const anchor = findClosestAnchor((event as any).nativeEvent.target); + if (!anchor) { + return; + } + + const navLink = navLinks.find(item => item.href === anchor.href); + if (navLink && navLink.isDisabled) { + event.preventDefault(); + return; + } + + if ( + !forceNavigation || + event.isDefaultPrevented() || + event.altKey || + event.metaKey || + event.ctrlKey + ) { + return; + } + + const toParsed = Url.parse(anchor.href); + const fromParsed = Url.parse(document.location.href); + const sameProto = toParsed.protocol === fromParsed.protocol; + const sameHost = toParsed.host === fromParsed.host; + const samePath = toParsed.path === fromParsed.path; + + if (sameProto && sameHost && samePath) { + if (toParsed.hash) { + document.location.reload(); + } + + // event.preventDefault() keeps the browser from seeing the new url as an update + // and even setting window.location does not mimic that behavior, so instead + // we use stopPropagation() to prevent angular from seeing the click and + // starting a digest cycle/attempting to handle it in the router. + event.stopPropagation(); + } +} + +interface Props { + href: string; + navLinks: NavLink[]; + forceNavigation: boolean; +} + +export function HeaderLogo({ href, forceNavigation, navLinks }: Props) { + return ( + onClick(e, forceNavigation, navLinks)} + href={href} + aria-label={i18n.translate('core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel', { + defaultMessage: 'Go to home page', + })} + /> + ); +} diff --git a/src/core/public/chrome/ui/header/index.ts b/src/core/public/chrome/ui/header/index.ts index 6d59fc6d9433b8..b396c94b3f2a3e 100644 --- a/src/core/public/chrome/ui/header/index.ts +++ b/src/core/public/chrome/ui/header/index.ts @@ -26,3 +26,5 @@ export { ChromeHelpExtensionMenuDocumentationLink, ChromeHelpExtensionMenuGitHubLink, } from './header_help_menu'; +export type NavSetting = 'grouped' | 'individual'; +export type OnIsLockedUpdate = (isLocked: boolean) => void; diff --git a/src/core/public/chrome/ui/header/nav_drawer.test.tsx b/src/core/public/chrome/ui/header/nav_drawer.test.tsx new file mode 100644 index 00000000000000..7272935b93a520 --- /dev/null +++ b/src/core/public/chrome/ui/header/nav_drawer.test.tsx @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { cloneDeep } from 'lodash'; +import { mount } from 'enzyme'; +import React from 'react'; +import { NavSetting } from './'; +import { ChromeNavLink } from '../../../'; +import { AppCategory } from 'src/core/types'; +import { DEFAULT_APP_CATEGORIES } from '../../../../utils'; +import { NavDrawer } from './nav_drawer'; +import { euiNavLink } from './nav_link'; + +const { analyze, management, observability, security } = DEFAULT_APP_CATEGORIES; +const mockIBasePath = { + get: () => '/app', + prepend: () => '/app', + remove: () => '/app', +}; + +const getMockProps = (chromeNavLinks: ChromeNavLink[], navSetting: NavSetting = 'grouped') => ({ + navSetting, + navLinks: chromeNavLinks.map(link => + euiNavLink(link, true, undefined, mockIBasePath, () => Promise.resolve()) + ), + chromeNavLinks, + recentlyAccessedItems: [], + basePath: mockIBasePath, +}); + +const makeLink = (id: string, order: number, category?: AppCategory) => ({ + id, + category, + order, + title: id, + baseUrl: `http://localhost:5601/app/${id}`, + legacy: true, +}); + +const getMockChromeNavLink = () => + cloneDeep([ + makeLink('discover', 100, analyze), + makeLink('siem', 500, security), + makeLink('metrics', 600, observability), + makeLink('monitoring', 800, management), + makeLink('visualize', 200, analyze), + makeLink('dashboard', 300, analyze), + makeLink('canvas', 400, { label: 'customCategory' }), + makeLink('logs', 700, observability), + ]); + +describe('NavDrawer', () => { + describe('Advanced setting set to individual', () => { + it('renders individual items', () => { + const component = mount( + + ); + expect(component).toMatchSnapshot(); + }); + }); + describe('Advanced setting set to grouped', () => { + it('renders individual items if there are less than 7', () => { + const links = getMockChromeNavLink().slice(0, 5); + const component = mount(); + expect(component).toMatchSnapshot(); + }); + it('renders individual items if there is only 1 category', () => { + // management doesn't count as a category + const navLinks = [ + makeLink('discover', 100, analyze), + makeLink('siem', 500, analyze), + makeLink('metrics', 600, analyze), + makeLink('monitoring', 800, analyze), + makeLink('visualize', 200, analyze), + makeLink('dashboard', 300, management), + makeLink('canvas', 400, management), + makeLink('logs', 700, management), + ]; + const component = mount(); + expect(component).toMatchSnapshot(); + }); + it('renders grouped items', () => { + const component = mount(); + expect(component).toMatchSnapshot(); + }); + }); +}); diff --git a/src/core/public/chrome/ui/header/nav_drawer.tsx b/src/core/public/chrome/ui/header/nav_drawer.tsx new file mode 100644 index 00000000000000..dbb68d5dd3901e --- /dev/null +++ b/src/core/public/chrome/ui/header/nav_drawer.tsx @@ -0,0 +1,170 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { groupBy, sortBy } from 'lodash'; +import { i18n } from '@kbn/i18n'; +// @ts-ignore +import { EuiNavDrawer, EuiHorizontalRule, EuiNavDrawerGroup } from '@elastic/eui'; +import { NavSetting, OnIsLockedUpdate } from './'; +import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../../..'; +import { AppCategory } from '../../../../types'; +import { HttpStart } from '../../../http'; +import { NavLink } from './nav_link'; +import { RecentLinks } from './recent_links'; + +function getAllCategories(allCategorizedLinks: Record) { + const allCategories = {} as Record; + + for (const [key, value] of Object.entries(allCategorizedLinks)) { + allCategories[key] = value[0].category; + } + + return allCategories; +} + +function getOrderedCategories( + mainCategories: Record, + categoryDictionary: ReturnType +) { + return sortBy( + Object.keys(mainCategories), + categoryName => categoryDictionary[categoryName]?.order + ); +} + +export interface Props { + navSetting: NavSetting; + isLocked?: boolean; + onIsLockedUpdate?: OnIsLockedUpdate; + navLinks: NavLink[]; + chromeNavLinks: ChromeNavLink[]; + recentlyAccessedItems: ChromeRecentlyAccessedHistoryItem[]; + basePath: HttpStart['basePath']; +} + +function navDrawerRenderer( + { + navSetting, + isLocked, + onIsLockedUpdate, + navLinks, + chromeNavLinks, + recentlyAccessedItems, + basePath, + }: Props, + ref: React.Ref +) { + const disableGroupedNavSetting = navSetting === 'individual'; + const groupedNavLinks = groupBy(navLinks, link => link?.category?.label); + const { undefined: unknowns, ...allCategorizedLinks } = groupedNavLinks; + const { Management: management, ...mainCategories } = allCategorizedLinks; + const categoryDictionary = getAllCategories(allCategorizedLinks); + const orderedCategories = getOrderedCategories(mainCategories, categoryDictionary); + const showUngroupedNav = + disableGroupedNavSetting || navLinks.length < 7 || Object.keys(mainCategories).length === 1; + + return ( + + {RecentLinks({ + recentlyAccessedItems, + navLinks: chromeNavLinks, + basePath, + })} + + {showUngroupedNav ? ( + + ) : ( + <> + { + const category = categoryDictionary[categoryName]!; + const links = mainCategories[categoryName]; + + if (links.length === 1) { + return { + ...links[0], + label: category.label, + iconType: category.euiIconType || links[0].iconType, + }; + } + + return { + 'data-test-subj': 'navDrawerCategory', + iconType: category.euiIconType, + label: category.label, + flyoutMenu: { + title: category.label, + listItems: sortBy(links, 'order').map(link => { + link['data-test-subj'] = 'navDrawerFlyoutLink'; + return link; + }), + }, + }; + }), + ...sortBy(unknowns, 'order'), + ]} + /> + + { + link['data-test-subj'] = 'navDrawerFlyoutLink'; + return link; + }), + }, + }, + ]} + /> + + )} + + ); +} + +export const NavDrawer = React.forwardRef(navDrawerRenderer); diff --git a/src/core/public/chrome/ui/header/nav_link.tsx b/src/core/public/chrome/ui/header/nav_link.tsx new file mode 100644 index 00000000000000..52b59c53b658c0 --- /dev/null +++ b/src/core/public/chrome/ui/header/nav_link.tsx @@ -0,0 +1,87 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiImage } from '@elastic/eui'; +import { ChromeNavLink, CoreStart } from '../../../'; +import { HttpStart } from '../../../http'; + +function isModifiedEvent(event: MouseEvent) { + return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); +} + +function LinkIcon({ url }: { url: string }) { + return ; +} + +export type NavLink = ReturnType; + +export function euiNavLink( + navLink: ChromeNavLink, + legacyMode: boolean, + currentAppId: string | undefined, + basePath: HttpStart['basePath'], + navigateToApp: CoreStart['application']['navigateToApp'] +) { + const { + legacy, + url, + active, + baseUrl, + id, + title, + disabled, + euiIconType, + icon, + category, + order, + tooltip, + } = navLink; + let href = navLink.baseUrl; + + if (legacy) { + href = url && !active ? url : baseUrl; + } + + return { + category, + key: id, + label: tooltip ?? title, + href, // Use href and onClick to support "open in new tab" and SPA navigation in the same link + onClick(event: MouseEvent) { + if ( + !legacyMode && // ignore when in legacy mode + !legacy && // ignore links to legacy apps + !event.defaultPrevented && // onClick prevented default + event.button === 0 && // ignore everything but left clicks + !isModifiedEvent(event) // ignore clicks with modifier keys + ) { + event.preventDefault(); + navigateToApp(navLink.id); + } + }, + // Legacy apps use `active` property, NP apps should match the current app + isActive: active || currentAppId === id, + isDisabled: disabled, + iconType: euiIconType, + icon: !euiIconType && icon ? : undefined, + order, + 'data-test-subj': 'navDrawerAppsMenuLink', + }; +} diff --git a/src/core/public/chrome/ui/header/recent_links.tsx b/src/core/public/chrome/ui/header/recent_links.tsx new file mode 100644 index 00000000000000..a947ab1c450563 --- /dev/null +++ b/src/core/public/chrome/ui/header/recent_links.tsx @@ -0,0 +1,113 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +// @ts-ignore +import { EuiNavDrawerGroup } from '@elastic/eui'; +import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../../..'; +import { HttpStart } from '../../../http'; + +// Providing a buffer between the limit and the cut off index +// protects from truncating just the last couple (6) characters +const TRUNCATE_LIMIT: number = 64; +const TRUNCATE_AT: number = 58; + +export function truncateRecentItemLabel(label: string): string { + if (label.length > TRUNCATE_LIMIT) { + label = `${label.substring(0, TRUNCATE_AT)}…`; + } + + return label; +} + +/** + * @param {string} url - a relative or root relative url. If a relative path is given then the + * absolute url returned will depend on the current page where this function is called from. For example + * if you are on page "http://www.mysite.com/shopping/kids" and you pass this function "adults", you would get + * back "http://www.mysite.com/shopping/adults". If you passed this function a root relative path, or one that + * starts with a "/", for example "/account/cart", you would get back "http://www.mysite.com/account/cart". + * @return {string} the relative url transformed into an absolute url + */ +function relativeToAbsolute(url: string) { + const a = document.createElement('a'); + a.setAttribute('href', url); + return a.href; +} + +function prepareForEUI( + recentlyAccessed: ChromeRecentlyAccessedHistoryItem[], + navLinks: ChromeNavLink[], + basePath: HttpStart['basePath'] +) { + return recentlyAccessed.map(({ link, label }) => { + const href = relativeToAbsolute(basePath.prepend(link)); + const navLink = navLinks.find(nl => href.startsWith(nl.baseUrl ?? nl.subUrlBase)); + let titleAndAriaLabel = label; + + if (navLink) { + titleAndAriaLabel = i18n.translate('core.ui.recentLinks.linkItem.screenReaderLabel', { + defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}', + values: { + recentlyAccessedItemLinklabel: label, + pageType: navLink.title, + }, + }); + } + + return { + href, + label: truncateRecentItemLabel(label), + title: titleAndAriaLabel, + 'aria-label': titleAndAriaLabel, + iconType: navLink?.euiIconType, + }; + }); +} + +interface Props { + recentlyAccessedItems: ChromeRecentlyAccessedHistoryItem[]; + navLinks: ChromeNavLink[]; + basePath: HttpStart['basePath']; +} + +export function RecentLinks({ recentlyAccessedItems, navLinks, basePath }: Props) { + return ( + + ); +} diff --git a/src/core/public/core_system.test.ts b/src/core/public/core_system.test.ts index 1ee41fe64418ec..94fa74f4bd861f 100644 --- a/src/core/public/core_system.test.ts +++ b/src/core/public/core_system.test.ts @@ -429,15 +429,14 @@ describe('Notifications targetDomElement', () => { rootDomElement, }); - let targetDomElementParentInStart: HTMLElement | null; + let targetDomElementInStart: HTMLElement | null; MockNotificationsService.start.mockImplementation(({ targetDomElement }): any => { - expect(targetDomElement.parentElement).not.toBeNull(); - targetDomElementParentInStart = targetDomElement.parentElement; + targetDomElementInStart = targetDomElement; }); // Starting the core system should pass the targetDomElement as a child of the rootDomElement await core.setup(); await core.start(); - expect(targetDomElementParentInStart!).toBe(rootDomElement); + expect(targetDomElementInStart!.parentElement).toBe(rootDomElement); }); }); diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 5b31c740518e4a..5fb12ec1549521 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -214,6 +214,7 @@ export class CoreSystem { const http = await this.http.start({ injectedMetadata, fatalErrors: this.fatalErrorsSetup! }); const savedObjects = await this.savedObjects.start({ http }); const i18n = await this.i18n.start(); + const fatalErrors = await this.fatalErrors.start(); await this.integrations.start({ uiSettings }); const coreUiTargetDomElement = document.createElement('div'); @@ -221,13 +222,6 @@ export class CoreSystem { const notificationsTargetDomElement = document.createElement('div'); const overlayTargetDomElement = document.createElement('div'); - // ensure the rootDomElement is empty - this.rootDomElement.textContent = ''; - this.rootDomElement.classList.add('coreSystemRootDomElement'); - this.rootDomElement.appendChild(coreUiTargetDomElement); - this.rootDomElement.appendChild(notificationsTargetDomElement); - this.rootDomElement.appendChild(overlayTargetDomElement); - const overlays = this.overlay.start({ i18n, targetDomElement: overlayTargetDomElement, @@ -245,6 +239,7 @@ export class CoreSystem { http, injectedMetadata, notifications, + uiSettings, }); application.registerMountContext(this.coreContext.coreId, 'core', () => ({ @@ -271,9 +266,18 @@ export class CoreSystem { notifications, overlays, uiSettings, + fatalErrors, }; const plugins = await this.plugins.start(core); + + // ensure the rootDomElement is empty + this.rootDomElement.textContent = ''; + this.rootDomElement.classList.add('coreSystemRootDomElement'); + this.rootDomElement.appendChild(coreUiTargetDomElement); + this.rootDomElement.appendChild(notificationsTargetDomElement); + this.rootDomElement.appendChild(overlayTargetDomElement); + const rendering = this.rendering.start({ application, chrome, diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 1046f7a17dc518..3521d7ef9c66eb 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -214,5 +214,6 @@ export interface DocLinksStart { readonly date: { readonly dateMath: string; }; + readonly management: Record; }; } diff --git a/src/core/public/fatal_errors/fatal_errors_service.mock.ts b/src/core/public/fatal_errors/fatal_errors_service.mock.ts index dd7702a7ee7dd9..6d9876f787fa97 100644 --- a/src/core/public/fatal_errors/fatal_errors_service.mock.ts +++ b/src/core/public/fatal_errors/fatal_errors_service.mock.ts @@ -26,18 +26,22 @@ const createSetupContractMock = () => { return setupContract; }; +const createStartContractMock = createSetupContractMock; type FatalErrorsServiceContract = PublicMethodsOf; const createMock = () => { const mocked: jest.Mocked = { setup: jest.fn(), + start: jest.fn(), }; mocked.setup.mockReturnValue(createSetupContractMock()); + mocked.start.mockReturnValue(createStartContractMock()); return mocked; }; export const fatalErrorsServiceMock = { create: createMock, createSetupContract: createSetupContractMock, + createStartContract: createStartContractMock, }; diff --git a/src/core/public/fatal_errors/fatal_errors_service.tsx b/src/core/public/fatal_errors/fatal_errors_service.tsx index 5c6a7bb322ae1f..309f07859ef264 100644 --- a/src/core/public/fatal_errors/fatal_errors_service.tsx +++ b/src/core/public/fatal_errors/fatal_errors_service.tsx @@ -54,9 +54,18 @@ export interface FatalErrorsSetup { get$: () => Rx.Observable; } +/** + * FatalErrors stop the Kibana Public Core and displays a fatal error screen + * with details about the Kibana build and the error. + * + * @public + */ +export type FatalErrorsStart = FatalErrorsSetup; + /** @interal */ export class FatalErrorsService { private readonly errorInfo$ = new Rx.ReplaySubject(); + private fatalErrors?: FatalErrorsSetup; /** * @@ -82,7 +91,7 @@ export class FatalErrorsService { }, }); - const fatalErrorsSetup: FatalErrorsSetup = { + this.fatalErrors = { add: (error, source?) => { const errorInfo = getErrorInfo(error, source); @@ -101,9 +110,17 @@ export class FatalErrorsService { }, }; - this.setupGlobalErrorHandlers(fatalErrorsSetup); + this.setupGlobalErrorHandlers(this.fatalErrors!); - return fatalErrorsSetup; + return this.fatalErrors!; + } + + public start() { + const { fatalErrors } = this; + if (!fatalErrors) { + throw new Error('FatalErrorsService#setup() must be invoked before start.'); + } + return fatalErrors; } private renderError(injectedMetadata: InjectedMetadataSetup, i18n: I18nStart) { diff --git a/src/core/public/fatal_errors/index.ts b/src/core/public/fatal_errors/index.ts index e37a36152cf91b..c8ea1c0bccd227 100644 --- a/src/core/public/fatal_errors/index.ts +++ b/src/core/public/fatal_errors/index.ts @@ -17,5 +17,5 @@ * under the License. */ -export { FatalErrorsSetup, FatalErrorsService } from './fatal_errors_service'; +export { FatalErrorsSetup, FatalErrorsStart, FatalErrorsService } from './fatal_errors_service'; export { FatalErrorInfo } from './get_error_info'; diff --git a/src/core/public/http/fetch.test.ts b/src/core/public/http/fetch.test.ts index adb3d696a962fd..a99b7607d71491 100644 --- a/src/core/public/http/fetch.test.ts +++ b/src/core/public/http/fetch.test.ts @@ -24,7 +24,7 @@ import { join } from 'path'; import { Fetch } from './fetch'; import { BasePath } from './base_path'; -import { IHttpResponse } from './types'; +import { HttpResponse, HttpFetchOptionsWithPath } from './types'; function delay(duration: number) { return new Promise(r => setTimeout(r, duration)); @@ -40,6 +40,19 @@ describe('Fetch', () => { }); describe('http requests', () => { + it('should fail with invalid arguments', async () => { + fetchMock.get('*', {}); + await expect( + fetchInstance.fetch( + // @ts-ignore + { path: '/', headers: { hello: 'world' } }, + { headers: { hello: 'mars' } } + ) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Invalid fetch arguments, must either be (string, object) or (object, undefined), received (object, object)"` + ); + }); + it('should use supplied request method', async () => { fetchMock.post('*', {}); await fetchInstance.fetch('/my/path', { method: 'POST' }); @@ -56,6 +69,15 @@ describe('Fetch', () => { }); }); + it('should not set Content-Type if undefined', async () => { + fetchMock.get('*', {}); + await fetchInstance.fetch('/my/path', { headers: { 'Content-Type': undefined } }); + + expect(fetchMock.lastOptions()!.headers).toMatchObject({ + 'kbn-version': 'VERSION', + }); + }); + it('should use supplied pathname and querystring', async () => { fetchMock.get('*', {}); await fetchInstance.fetch('/my/path', { query: { a: 'b' } }); @@ -69,13 +91,106 @@ describe('Fetch', () => { headers: { myHeader: 'foo' }, }); - expect(fetchMock.lastOptions()!.headers).toEqual({ + expect(fetchMock.lastOptions()!.headers).toMatchObject({ 'content-type': 'application/json', 'kbn-version': 'VERSION', myheader: 'foo', }); }); + it('should not allow overwriting of kbn-version header', async () => { + fetchMock.get('*', {}); + await expect( + fetchInstance.fetch('/my/path', { + headers: { myHeader: 'foo', 'kbn-version': 'CUSTOM!' }, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Invalid fetch headers, headers beginning with \\"kbn-\\" are not allowed: [kbn-version]"` + ); + }); + + it('should not set kbn-system-request header by default', async () => { + fetchMock.get('*', {}); + await fetchInstance.fetch('/my/path', { + headers: { myHeader: 'foo' }, + }); + + expect(fetchMock.lastOptions()!.headers['kbn-system-request']).toBeUndefined(); + }); + + it('should not set kbn-system-request header when asSystemRequest: false', async () => { + fetchMock.get('*', {}); + await fetchInstance.fetch('/my/path', { + headers: { myHeader: 'foo' }, + asSystemRequest: false, + }); + + expect(fetchMock.lastOptions()!.headers['kbn-system-request']).toBeUndefined(); + }); + + it('should set kbn-system-request header when asSystemRequest: true', async () => { + fetchMock.get('*', {}); + await fetchInstance.fetch('/my/path', { + headers: { myHeader: 'foo' }, + asSystemRequest: true, + }); + + expect(fetchMock.lastOptions()!.headers).toMatchObject({ + 'kbn-system-request': 'true', + myheader: 'foo', + }); + }); + + it('should not allow overwriting of kbn-system-request when asSystemRequest: true', async () => { + fetchMock.get('*', {}); + await expect( + fetchInstance.fetch('/my/path', { + headers: { myHeader: 'foo', 'kbn-system-request': 'ANOTHER!' }, + asSystemRequest: true, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Invalid fetch headers, headers beginning with \\"kbn-\\" are not allowed: [kbn-system-request]"` + ); + }); + + it('should not allow overwriting of kbn-system-request when asSystemRequest: false', async () => { + fetchMock.get('*', {}); + await expect( + fetchInstance.fetch('/my/path', { + headers: { myHeader: 'foo', 'kbn-system-request': 'ANOTHER!' }, + asSystemRequest: false, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Invalid fetch headers, headers beginning with \\"kbn-\\" are not allowed: [kbn-system-request]"` + ); + }); + + // Deprecated header used by legacy platform pre-7.7. Remove in 8.x. + it('should not allow overwriting of kbn-system-api when asSystemRequest: true', async () => { + fetchMock.get('*', {}); + await expect( + fetchInstance.fetch('/my/path', { + headers: { myHeader: 'foo', 'kbn-system-api': 'ANOTHER!' }, + asSystemRequest: true, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Invalid fetch headers, headers beginning with \\"kbn-\\" are not allowed: [kbn-system-api]"` + ); + }); + + // Deprecated header used by legacy platform pre-7.7. Remove in 8.x. + it('should not allow overwriting of kbn-system-api when asSystemRequest: false', async () => { + fetchMock.get('*', {}); + await expect( + fetchInstance.fetch('/my/path', { + headers: { myHeader: 'foo', 'kbn-system-api': 'ANOTHER!' }, + asSystemRequest: false, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Invalid fetch headers, headers beginning with \\"kbn-\\" are not allowed: [kbn-system-api]"` + ); + }); + it('should return response', async () => { fetchMock.get('*', { foo: 'bar' }); const json = await fetchInstance.fetch('/my/path'); @@ -121,11 +236,35 @@ describe('Fetch', () => { const response = await fetchInstance.fetch('/my/path', { asResponse: true }); + expect(response.fetchOptions).toMatchObject({ + path: '/my/path', + asResponse: true, + }); expect(response.request).toBeInstanceOf(Request); expect(response.response).toBeInstanceOf(Response); expect(response.body).toEqual({ foo: 'bar' }); }); + it('should expose asSystemRequest: true on detailed response object when asResponse = true', async () => { + fetchMock.get('*', { foo: 'bar' }); + + const response = await fetchInstance.fetch('/my/path', { + asResponse: true, + asSystemRequest: true, + }); + expect(response.fetchOptions.asSystemRequest).toBe(true); + }); + + it('should expose asSystemRequest: false on detailed response object when asResponse = true', async () => { + fetchMock.get('*', { foo: 'bar' }); + + const response = await fetchInstance.fetch('/my/path', { + asResponse: true, + asSystemRequest: false, + }); + expect(response.fetchOptions.asSystemRequest).toBe(false); + }); + it('should reject on network error', async () => { expect.assertions(1); fetchMock.get('*', { status: 500 }); @@ -245,13 +384,18 @@ describe('Fetch', () => { it('should be able to manipulate request instance', async () => { fetchInstance.intercept({ - request(request) { - request.headers.set('Content-Type', 'CustomContentType'); + request(options) { + return { + headers: { + ...options.headers, + 'Content-Type': 'CustomContentType', + }, + }; }, }); fetchInstance.intercept({ - request(request) { - return new Request('/my/route', request); + request() { + return { path: '/my/route' }; }, }); @@ -262,7 +406,7 @@ describe('Fetch', () => { expect(fetchMock.lastOptions()!.headers).toMatchObject({ 'content-type': 'CustomContentType', }); - expect(fetchMock.lastUrl()).toBe('/my/route'); + expect(fetchMock.lastUrl()).toBe('http://localhost/myBase/my/route'); }); it('should call interceptors in correct order', async () => { @@ -402,8 +546,8 @@ describe('Fetch', () => { fetchInstance.intercept({ request: unusedSpy, - requestError({ request }) { - return new Request('/my/route', request); + requestError() { + return { path: '/my/route' }; }, response: usedSpy, }); @@ -423,16 +567,16 @@ describe('Fetch', () => { it('should accumulate request information', async () => { const routes = ['alpha', 'beta', 'gamma']; - const createRequest = jest.fn( - (request: Request) => new Request(`/api/${routes.shift()}`, request) - ); + const createRequest = jest.fn((options: HttpFetchOptionsWithPath) => ({ + path: `/api/${routes.shift()}`, + })); fetchInstance.intercept({ request: createRequest, }); fetchInstance.intercept({ requestError(httpErrorRequest) { - return httpErrorRequest.request; + return httpErrorRequest.fetchOptions; }, }); fetchInstance.intercept({ @@ -450,15 +594,15 @@ describe('Fetch', () => { await expect(fetchInstance.fetch('/my/route')).resolves.toEqual({ foo: 'bar' }); expect(fetchMock.called()).toBe(true); expect(routes.length).toBe(0); - expect(createRequest.mock.calls[0][0].url).toContain('/my/route'); - expect(createRequest.mock.calls[1][0].url).toContain('/api/alpha'); - expect(createRequest.mock.calls[2][0].url).toContain('/api/beta'); + expect(createRequest.mock.calls[0][0].path).toContain('/my/route'); + expect(createRequest.mock.calls[1][0].path).toContain('/api/alpha'); + expect(createRequest.mock.calls[2][0].path).toContain('/api/beta'); expect(fetchMock.lastCall()!.request.url).toContain('/api/gamma'); }); it('should accumulate response information', async () => { const bodies = ['alpha', 'beta', 'gamma']; - const createResponse = jest.fn((httpResponse: IHttpResponse) => ({ + const createResponse = jest.fn((httpResponse: HttpResponse) => ({ body: bodies.shift(), })); @@ -550,7 +694,7 @@ describe('Fetch', () => { fetchInstance.intercept({ requestError(httpErrorRequest) { - return httpErrorRequest.request; + return httpErrorRequest.fetchOptions; }, response: usedSpy, }); diff --git a/src/core/public/http/fetch.ts b/src/core/public/http/fetch.ts index b86f1f5c08029b..1043b50dff9584 100644 --- a/src/core/public/http/fetch.ts +++ b/src/core/public/http/fetch.ts @@ -20,10 +20,16 @@ import { merge } from 'lodash'; import { format } from 'url'; -import { IBasePath, HttpInterceptor, HttpHandler, HttpFetchOptions, IHttpResponse } from './types'; +import { + IBasePath, + HttpInterceptor, + HttpHandler, + HttpFetchOptions, + HttpResponse, + HttpFetchOptionsWithPath, +} from './types'; import { HttpFetchError } from './http_fetch_error'; import { HttpInterceptController } from './http_intercept_controller'; -import { HttpResponse } from './response'; import { interceptRequest, interceptResponse } from './intercept'; import { HttpInterceptHaltError } from './http_intercept_halt_error'; @@ -60,29 +66,30 @@ export class Fetch { public readonly put = this.shorthand('PUT'); public fetch: HttpHandler = async ( - path: string, - options: HttpFetchOptions = {} + pathOrOptions: string | HttpFetchOptionsWithPath, + options?: HttpFetchOptions ) => { - const initialRequest = this.createRequest(path, options); + const optionsWithPath = validateFetchArguments(pathOrOptions, options); const controller = new HttpInterceptController(); // We wrap the interception in a separate promise to ensure that when // a halt is called we do not resolve or reject, halting handling of the promise. - return new Promise>(async (resolve, reject) => { + return new Promise>(async (resolve, reject) => { try { - const interceptedRequest = await interceptRequest( - initialRequest, + const interceptedOptions = await interceptRequest( + optionsWithPath, this.interceptors, controller ); - const initialResponse = this.fetchResponse(interceptedRequest); + const initialResponse = this.fetchResponse(interceptedOptions); const interceptedResponse = await interceptResponse( + interceptedOptions, initialResponse, this.interceptors, controller ); - if (options.asResponse) { + if (optionsWithPath.asResponse) { resolve(interceptedResponse); } else { resolve(interceptedResponse.body); @@ -95,45 +102,55 @@ export class Fetch { }); }; - private createRequest(path: string, options?: HttpFetchOptions): Request { + private createRequest(options: HttpFetchOptionsWithPath): Request { // Merge and destructure options out that are not applicable to the Fetch API. - const { query, prependBasePath: shouldPrependBasePath, asResponse, ...fetchOptions } = merge( + const { + query, + prependBasePath: shouldPrependBasePath, + asResponse, + asSystemRequest, + ...fetchOptions + } = merge( { method: 'GET', credentials: 'same-origin', prependBasePath: true, + }, + options, + { headers: { - 'kbn-version': this.params.kibanaVersion, 'Content-Type': 'application/json', + ...options.headers, + 'kbn-version': this.params.kibanaVersion, }, - }, - options || {} + } ); const url = format({ - pathname: shouldPrependBasePath ? this.params.basePath.prepend(path) : path, + pathname: shouldPrependBasePath ? this.params.basePath.prepend(options.path) : options.path, query, }); - if ( - options && - options.headers && - 'Content-Type' in options.headers && - options.headers['Content-Type'] === undefined - ) { - delete fetchOptions.headers['Content-Type']; + // Make sure the system request header is only present if `asSystemRequest` is true. + if (asSystemRequest) { + fetchOptions.headers['kbn-system-request'] = 'true'; } return new Request(url, fetchOptions); } - private async fetchResponse(request: Request) { + private async fetchResponse(fetchOptions: HttpFetchOptionsWithPath): Promise> { + const request = this.createRequest(fetchOptions); let response: Response; let body = null; try { response = await window.fetch(request); } catch (err) { - throw new HttpFetchError(err.message, request); + if (err.name === 'AbortError') { + throw err; + } else { + throw new HttpFetchError(err.message, request); + } } const contentType = response.headers.get('Content-Type') || ''; @@ -160,11 +177,46 @@ export class Fetch { throw new HttpFetchError(response.statusText, request, response, body); } - return new HttpResponse({ request, response, body }); + return { fetchOptions, request, response, body }; } - private shorthand(method: string) { - return (path: string, options: HttpFetchOptions = {}) => - this.fetch(path, { ...options, method }); + private shorthand(method: string): HttpHandler { + return (pathOrOptions: string | HttpFetchOptionsWithPath, options?: HttpFetchOptions) => { + const optionsWithPath = validateFetchArguments(pathOrOptions, options); + return this.fetch({ ...optionsWithPath, method }); + }; } } + +/** + * Ensure that the overloaded arguments to `HttpHandler` are valid. + */ +const validateFetchArguments = ( + pathOrOptions: string | HttpFetchOptionsWithPath, + options?: HttpFetchOptions +): HttpFetchOptionsWithPath => { + let fullOptions: HttpFetchOptionsWithPath; + + if (typeof pathOrOptions === 'string' && (typeof options === 'object' || options === undefined)) { + fullOptions = { ...options, path: pathOrOptions }; + } else if (typeof pathOrOptions === 'object' && options === undefined) { + fullOptions = pathOrOptions; + } else { + throw new Error( + `Invalid fetch arguments, must either be (string, object) or (object, undefined), received (${typeof pathOrOptions}, ${typeof options})` + ); + } + + const invalidHeaders = Object.keys(fullOptions.headers ?? {}).filter(headerName => + headerName.startsWith('kbn-') + ); + if (invalidHeaders.length) { + throw new Error( + `Invalid fetch headers, headers beginning with "kbn-" are not allowed: [${invalidHeaders.join( + ',' + )}]` + ); + } + + return fullOptions; +}; diff --git a/src/core/public/http/intercept.ts b/src/core/public/http/intercept.ts index e2a16565c61c43..bacc8748d26808 100644 --- a/src/core/public/http/intercept.ts +++ b/src/core/public/http/intercept.ts @@ -19,28 +19,31 @@ import { HttpInterceptController } from './http_intercept_controller'; import { HttpInterceptHaltError } from './http_intercept_halt_error'; -import { HttpInterceptor, IHttpResponse } from './types'; -import { HttpResponse } from './response'; +import { HttpInterceptor, HttpResponse, HttpFetchOptionsWithPath } from './types'; export async function interceptRequest( - request: Request, + options: HttpFetchOptionsWithPath, interceptors: ReadonlySet, controller: HttpInterceptController -): Promise { - let next = request; +): Promise { + let current: HttpFetchOptionsWithPath; return [...interceptors].reduceRight( (promise, interceptor) => promise.then( - async (current: Request) => { - next = current; + async fetchOptions => { + current = fetchOptions; checkHalt(controller); if (!interceptor.request) { - return current; + return fetchOptions; } - return (await interceptor.request(current, controller)) || current; + const overrides = await interceptor.request(current, controller); + return { + ...current, + ...overrides, + }; }, async error => { checkHalt(controller, error); @@ -49,26 +52,33 @@ export async function interceptRequest( throw error; } - const nextRequest = await interceptor.requestError({ error, request: next }, controller); + const overrides = await interceptor.requestError( + { error, fetchOptions: current }, + controller + ); - if (!nextRequest) { + if (!overrides) { throw error; } - next = nextRequest; - return next; + current = { + ...current, + ...overrides, + }; + return current; } ), - Promise.resolve(request) + Promise.resolve(options) ); } export async function interceptResponse( - responsePromise: Promise, + fetchOptions: HttpFetchOptionsWithPath, + responsePromise: Promise, interceptors: ReadonlySet, controller: HttpInterceptController -): Promise { - let current: IHttpResponse; +): Promise { + let current: HttpResponse; return await [...interceptors].reduce( (promise, interceptor) => @@ -83,10 +93,10 @@ export async function interceptResponse( const interceptorOverrides = (await interceptor.response(httpResponse, controller)) || {}; - return new HttpResponse({ + return { ...httpResponse, ...interceptorOverrides, - }); + }; }, async error => { const request = error.request || (current && current.request); @@ -101,6 +111,7 @@ export async function interceptResponse( const next = await interceptor.responseError( { error, + fetchOptions, request, response: error.response || (current && current.response), body: error.body || (current && current.body), @@ -114,7 +125,7 @@ export async function interceptResponse( throw error; } - return new HttpResponse({ ...next, request }); + return { ...next, request, fetchOptions }; } catch (err) { checkHalt(controller, err); throw err; diff --git a/src/core/public/http/response.ts b/src/core/public/http/response.ts deleted file mode 100644 index 706e7caaca9768..00000000000000 --- a/src/core/public/http/response.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IHttpResponse } from './types'; - -export class HttpResponse implements IHttpResponse { - public readonly request: Request; - public readonly response?: Response; - public readonly body?: TResponseBody; - - constructor({ - request, - response, - body, - }: { - request: Request; - response?: Response; - body?: TResponseBody; - }) { - this.request = request; - this.response = response; - this.body = body; - } -} diff --git a/src/core/public/http/types.ts b/src/core/public/http/types.ts index 27ffddc79cf653..c38b9da4429438 100644 --- a/src/core/public/http/types.ts +++ b/src/core/public/http/types.ts @@ -18,6 +18,7 @@ */ import { Observable } from 'rxjs'; +import { MaybePromise } from '@kbn/utility-types'; /** @public */ export interface HttpSetup { @@ -110,7 +111,11 @@ export interface IAnonymousPaths { register(path: string): void; } -/** @public */ +/** + * Headers to append to the request. Any headers that begin with `kbn-` are considered private to Core and will cause + * {@link HttpHandler} to throw an error. + * @public + */ export interface HttpHeadersInit { [name: string]: any; } @@ -217,30 +222,54 @@ export interface HttpFetchOptions extends HttpRequestInit { headers?: HttpHeadersInit; /** - * When `true` the return type of {@link HttpHandler} will be an {@link IHttpResponse} with detailed request and + * Whether or not the request should include the "system request" header to differentiate an end user request from + * Kibana internal request. + * Can be read on the server-side using KibanaRequest#isSystemRequest. Defaults to `false`. + */ + asSystemRequest?: boolean; + + /** + * When `true` the return type of {@link HttpHandler} will be an {@link HttpResponse} with detailed request and * response information. When `false`, the return type will just be the parsed response body. Defaults to `false`. */ asResponse?: boolean; } +/** + * Similar to {@link HttpFetchOptions} but with the URL path included. + * @public + */ +export interface HttpFetchOptionsWithPath extends HttpFetchOptions { + /* + * The path on the Kibana server to send the request to. Should not include the basePath. + */ + path: string; +} + /** * A function for making an HTTP requests to Kibana's backend. See {@link HttpFetchOptions} for options and - * {@link IHttpResponse} for the response. + * {@link HttpResponse} for the response. * * @param path the path on the Kibana server to send the request to. Should not include the basePath. * @param options {@link HttpFetchOptions} - * @returns a Promise that resolves to a {@link IHttpResponse} + * @returns a Promise that resolves to a {@link HttpResponse} * @public */ export interface HttpHandler { (path: string, options: HttpFetchOptions & { asResponse: true }): Promise< - IHttpResponse + HttpResponse + >; + (options: HttpFetchOptionsWithPath & { asResponse: true }): Promise< + HttpResponse >; (path: string, options?: HttpFetchOptions): Promise; + (options: HttpFetchOptionsWithPath): Promise; } /** @public */ -export interface IHttpResponse { +export interface HttpResponse { + /** The original {@link HttpFetchOptionsWithPath} used to send this request. */ + readonly fetchOptions: Readonly; /** Raw request sent to Kibana server. */ readonly request: Readonly; /** Raw response received, may be undefined if there was an error. */ @@ -276,12 +305,13 @@ export interface IHttpFetchError extends Error { } /** @public */ -export interface HttpErrorResponse extends IHttpResponse { +export interface HttpInterceptorResponseError extends HttpResponse { + request: Readonly; error: Error | IHttpFetchError; } /** @public */ -export interface HttpErrorRequest { - request: Request; +export interface HttpInterceptorRequestError { + fetchOptions: Readonly; error: Error; } @@ -298,39 +328,39 @@ export interface HttpInterceptor { * @param controller {@link IHttpInterceptController} */ request?( - request: Request, + fetchOptions: Readonly, controller: IHttpInterceptController - ): Promise | Request | void; + ): MaybePromise> | void; /** * Define an interceptor to be executed if a request interceptor throws an error or returns a rejected Promise. - * @param httpErrorRequest {@link HttpErrorRequest} + * @param httpErrorRequest {@link HttpInterceptorRequestError} * @param controller {@link IHttpInterceptController} */ requestError?( - httpErrorRequest: HttpErrorRequest, + httpErrorRequest: HttpInterceptorRequestError, controller: IHttpInterceptController - ): Promise | Request | void; + ): MaybePromise> | void; /** * Define an interceptor to be executed after a response is received. - * @param httpResponse {@link IHttpResponse} + * @param httpResponse {@link HttpResponse} * @param controller {@link IHttpInterceptController} */ response?( - httpResponse: IHttpResponse, + httpResponse: HttpResponse, controller: IHttpInterceptController - ): Promise | IHttpResponseInterceptorOverrides | void; + ): MaybePromise | void; /** * Define an interceptor to be executed if a response interceptor throws an error or returns a rejected Promise. - * @param httpErrorResponse {@link HttpErrorResponse} + * @param httpErrorResponse {@link HttpInterceptorResponseError} * @param controller {@link IHttpInterceptController} */ responseError?( - httpErrorResponse: HttpErrorResponse, + httpErrorResponse: HttpInterceptorResponseError, controller: IHttpInterceptController - ): Promise | IHttpResponseInterceptorOverrides | void; + ): MaybePromise | void; } /** diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 5b17eccc37f8b8..6d756e36d7379a 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -55,7 +55,7 @@ import { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, } from './chrome'; -import { FatalErrorsSetup, FatalErrorInfo } from './fatal_errors'; +import { FatalErrorsSetup, FatalErrorsStart, FatalErrorInfo } from './fatal_errors'; import { HttpSetup, HttpStart } from './http'; import { I18nStart } from './i18n'; import { InjectedMetadataSetup, InjectedMetadataStart, LegacyNavLink } from './injected_metadata'; @@ -77,7 +77,17 @@ import { } from './context'; export { CoreContext, CoreSystem } from './core_system'; -export { RecursiveReadonly } from '../utils'; +export { RecursiveReadonly, DEFAULT_APP_CATEGORIES } from '../utils'; +export { + AppCategory, + UiSettingsParams, + UserProvidedValues, + UiSettingsType, + ImageValidation, + StringValidation, + StringValidationRegex, + StringValidationRegexString, +} from '../types'; export { ApplicationSetup, @@ -133,11 +143,12 @@ export { HttpHeadersInit, HttpRequestInit, HttpFetchOptions, + HttpFetchOptionsWithPath, HttpFetchQuery, - HttpErrorResponse, - HttpErrorRequest, + HttpInterceptorResponseError, + HttpInterceptorRequestError, HttpInterceptor, - IHttpResponse, + HttpResponse, HttpHandler, IBasePath, IAnonymousPaths, @@ -232,6 +243,8 @@ export interface CoreStart { overlays: OverlayStart; /** {@link IUiSettingsClient} */ uiSettings: IUiSettingsClient; + /** {@link FatalErrorsStart} */ + fatalErrors: FatalErrorsStart; /** * exposed temporarily until https://github.com/elastic/kibana/issues/41990 done * use *only* to retrieve config values. There is no way to set injected values @@ -302,6 +315,7 @@ export { DocLinksStart, FatalErrorInfo, FatalErrorsSetup, + FatalErrorsStart, HttpSetup, HttpStart, I18nStart, diff --git a/src/core/public/injected_metadata/injected_metadata_service.mock.ts b/src/core/public/injected_metadata/injected_metadata_service.mock.ts index 9dfe0191166697..3c06f40d976db6 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.mock.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.mock.ts @@ -35,6 +35,10 @@ const createSetupContractMock = () => { setupContract.getKibanaVersion.mockReturnValue('kibanaVersion'); setupContract.getLegacyMode.mockReturnValue(true); setupContract.getLegacyMetadata.mockReturnValue({ + app: { + id: 'foo', + title: 'Foo App', + }, nav: [], uiSettings: { defaults: { legacyInjectedUiSettingDefaults: true }, diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index 0bde1b68e1876a..64a8b8a855fb46 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -26,10 +26,12 @@ import { UserProvidedValues, } from '../../server/types'; import { deepFreeze } from '../../utils/'; +import { AppCategory } from '../'; /** @public */ export interface LegacyNavLink { id: string; + category?: AppCategory; title: string; order: number; url: string; @@ -52,6 +54,7 @@ export interface InjectedMetadataParams { buildNumber: number; branch: string; basePath: string; + category?: AppCategory; csp: { warnLegacyBrowsers: boolean; }; @@ -65,7 +68,10 @@ export interface InjectedMetadataParams { uiPlugins: InjectedPluginMetadata[]; legacyMode: boolean; legacyMetadata: { - app: unknown; + app: { + id: string; + title: string; + }; bundleId: string; nav: LegacyNavLink[]; version: string; @@ -75,6 +81,7 @@ export interface InjectedMetadataParams { basePath: string; serverName: string; devMode: boolean; + category?: AppCategory; uiSettings: { defaults: Record; user?: Record; @@ -167,7 +174,10 @@ export interface InjectedMetadataSetup { /** Indicates whether or not we are rendering a known legacy app. */ getLegacyMode: () => boolean; getLegacyMetadata: () => { - app: unknown; + app: { + id: string; + title: string; + }; bundleId: string; nav: LegacyNavLink[]; version: string; diff --git a/src/core/public/legacy/legacy_service.test.ts b/src/core/public/legacy/legacy_service.test.ts index 9dd24f9e4a7a3c..d08c8b52e39c9b 100644 --- a/src/core/public/legacy/legacy_service.test.ts +++ b/src/core/public/legacy/legacy_service.test.ts @@ -98,6 +98,7 @@ const notificationsStart = notificationServiceMock.createStartContract(); const overlayStart = overlayServiceMock.createStartContract(); const uiSettingsStart = uiSettingsServiceMock.createStartContract(); const savedObjectsStart = savedObjectsMock.createStartContract(); +const fatalErrorsStart = fatalErrorsServiceMock.createStartContract(); const mockStorage = { getItem: jest.fn() } as any; const defaultStartDeps = { @@ -112,6 +113,7 @@ const defaultStartDeps = { overlays: overlayStart, uiSettings: uiSettingsStart, savedObjects: savedObjectsStart, + fatalErrors: fatalErrorsStart, }, lastSubUrlStorage: mockStorage, targetDomElement: document.createElement('div'), diff --git a/src/core/public/legacy/legacy_service.ts b/src/core/public/legacy/legacy_service.ts index f906aff1759e2e..cc3210771eecc2 100644 --- a/src/core/public/legacy/legacy_service.ts +++ b/src/core/public/legacy/legacy_service.ts @@ -74,6 +74,7 @@ export class LegacyPlatformService { appUrl: navLink.url, subUrlBase: navLink.subUrlBase, linkToLastSubUrl: navLink.linkToLastSubUrl, + category: navLink.category, }) ); diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index 43c8aa6f1d6b96..ce90d49065ad4e 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -74,6 +74,7 @@ function createCoreStartMock({ basePath = '' } = {}) { injectedMetadata: { getInjectedVar: injectedMetadataServiceMock.createStartContract().getInjectedVar, }, + fatalErrors: fatalErrorsServiceMock.createStartContract(), }; return mock; diff --git a/src/core/public/plugins/plugin_context.ts b/src/core/public/plugins/plugin_context.ts index f146c2452868b4..48100cba4f26e0 100644 --- a/src/core/public/plugins/plugin_context.ts +++ b/src/core/public/plugins/plugin_context.ts @@ -151,5 +151,6 @@ export function createPluginStartContext< injectedMetadata: { getInjectedVar: deps.injectedMetadata.getInjectedVar, }, + fatalErrors: deps.fatalErrors, }; } diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index cafc7e5887e385..dbbcda8d60e128 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -111,6 +111,7 @@ describe('PluginsService', () => { overlays: overlayServiceMock.createStartContract(), uiSettings: uiSettingsServiceMock.createStartContract(), savedObjects: savedObjectsMock.createStartContract(), + fatalErrors: fatalErrorsServiceMock.createStartContract(), }; mockStartContext = { ...mockStartDeps, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index abd39e864bd302..5e36638516e569 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -9,6 +9,7 @@ import { EuiButtonEmptyProps } from '@elastic/eui'; import { EuiGlobalToastListToast } from '@elastic/eui'; import { ExclusiveUnion } from '@elastic/eui'; import { IconType } from '@elastic/eui'; +import { MaybePromise } from '@kbn/utility-types'; import { Observable } from 'rxjs'; import React from 'react'; import * as Rx from 'rxjs'; @@ -26,6 +27,7 @@ export interface App extends AppBase { // @public (undocumented) export interface AppBase { capabilities?: Partial; + category?: AppCategory; chromeless?: boolean; euiIconType?: string; icon?: string; @@ -40,6 +42,14 @@ export interface AppBase { updater$?: Observable; } +// @public +export interface AppCategory { + ariaLabel?: string; + euiIconType?: string; + label: string; + order?: number; +} + // @public export type AppLeaveAction = AppLeaveDefaultAction | AppLeaveConfirmAction; @@ -251,6 +261,7 @@ export interface ChromeNavLink { // @deprecated readonly active?: boolean; readonly baseUrl: string; + readonly category?: AppCategory; // @deprecated readonly disabled?: boolean; readonly euiIconType?: string; @@ -377,6 +388,8 @@ export interface CoreStart { // (undocumented) docLinks: DocLinksStart; // (undocumented) + fatalErrors: FatalErrorsStart; + // (undocumented) http: HttpStart; // (undocumented) i18n: I18nStart; @@ -408,6 +421,26 @@ export class CoreSystem { stop(): void; } +// @internal (undocumented) +export const DEFAULT_APP_CATEGORIES: Readonly<{ + analyze: { + label: string; + order: number; + }; + observability: { + label: string; + order: number; + }; + security: { + label: string; + order: number; + }; + management: { + label: string; + euiIconType: string; + }; +}>; + // @public (undocumented) export interface DocLinksStart { // (undocumented) @@ -499,6 +532,7 @@ export interface DocLinksStart { readonly date: { readonly dateMath: string; }; + readonly management: Record; }; } @@ -532,6 +566,9 @@ export interface FatalErrorsSetup { get$: () => Rx.Observable; } +// @public +export type FatalErrorsStart = FatalErrorsSetup; + // @public export type HandlerContextType> = T extends HandlerFunction ? U : never; @@ -541,28 +578,21 @@ export type HandlerFunction = (context: T, ...args: any[]) => // @public export type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never; -// @public (undocumented) -export interface HttpErrorRequest { - // (undocumented) - error: Error; - // (undocumented) - request: Request; -} - -// @public (undocumented) -export interface HttpErrorResponse extends IHttpResponse { - // (undocumented) - error: Error | IHttpFetchError; -} - // @public export interface HttpFetchOptions extends HttpRequestInit { asResponse?: boolean; + asSystemRequest?: boolean; headers?: HttpHeadersInit; prependBasePath?: boolean; query?: HttpFetchQuery; } +// @public +export interface HttpFetchOptionsWithPath extends HttpFetchOptions { + // (undocumented) + path: string; +} + // @public (undocumented) export interface HttpFetchQuery { // (undocumented) @@ -574,12 +604,18 @@ export interface HttpHandler { // (undocumented) (path: string, options: HttpFetchOptions & { asResponse: true; - }): Promise>; + }): Promise>; + // (undocumented) + (options: HttpFetchOptionsWithPath & { + asResponse: true; + }): Promise>; // (undocumented) (path: string, options?: HttpFetchOptions): Promise; + // (undocumented) + (options: HttpFetchOptionsWithPath): Promise; } -// @public (undocumented) +// @public export interface HttpHeadersInit { // (undocumented) [name: string]: any; @@ -587,10 +623,26 @@ export interface HttpHeadersInit { // @public export interface HttpInterceptor { - request?(request: Request, controller: IHttpInterceptController): Promise | Request | void; - requestError?(httpErrorRequest: HttpErrorRequest, controller: IHttpInterceptController): Promise | Request | void; - response?(httpResponse: IHttpResponse, controller: IHttpInterceptController): Promise | IHttpResponseInterceptorOverrides | void; - responseError?(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptController): Promise | IHttpResponseInterceptorOverrides | void; + request?(fetchOptions: Readonly, controller: IHttpInterceptController): MaybePromise> | void; + requestError?(httpErrorRequest: HttpInterceptorRequestError, controller: IHttpInterceptController): MaybePromise> | void; + response?(httpResponse: HttpResponse, controller: IHttpInterceptController): MaybePromise | void; + responseError?(httpErrorResponse: HttpInterceptorResponseError, controller: IHttpInterceptController): MaybePromise | void; +} + +// @public (undocumented) +export interface HttpInterceptorRequestError { + // (undocumented) + error: Error; + // (undocumented) + fetchOptions: Readonly; +} + +// @public (undocumented) +export interface HttpInterceptorResponseError extends HttpResponse { + // (undocumented) + error: Error | IHttpFetchError; + // (undocumented) + request: Readonly; } // @public @@ -611,6 +663,14 @@ export interface HttpRequestInit { window?: null; } +// @public (undocumented) +export interface HttpResponse { + readonly body?: TResponseBody; + readonly fetchOptions: Readonly; + readonly request: Readonly; + readonly response?: Readonly; +} + // @public (undocumented) export interface HttpSetup { addLoadingCountSource(countSource$: Observable): void; @@ -682,19 +742,21 @@ export interface IHttpInterceptController { halted: boolean; } -// @public (undocumented) -export interface IHttpResponse { - readonly body?: TResponseBody; - readonly request: Readonly; - readonly response?: Readonly; -} - // @public export interface IHttpResponseInterceptorOverrides { readonly body?: TResponseBody; readonly response?: Readonly; } +// @public (undocumented) +export interface ImageValidation { + // (undocumented) + maxSize: { + length: number; + description: string; + }; +} + // @public export type IToasts = Pick; @@ -741,6 +803,8 @@ export interface LegacyCoreStart extends CoreStart { // @public (undocumented) export interface LegacyNavLink { + // (undocumented) + category?: AppCategory; // (undocumented) euiIconType?: string; // (undocumented) @@ -1129,6 +1193,25 @@ export class SimpleSavedObject { _version?: SavedObject['version']; } +// @public +export type StringValidation = StringValidationRegex | StringValidationRegexString; + +// @public +export interface StringValidationRegex { + // (undocumented) + message: string; + // (undocumented) + regex: RegExp; +} + +// @public +export interface StringValidationRegexString { + // (undocumented) + message: string; + // (undocumented) + regexString: string; +} + // Warning: (ae-missing-release-tag) "Toast" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1170,14 +1253,42 @@ export type ToastsSetup = IToasts; // @public (undocumented) export type ToastsStart = IToasts; +// @public +export interface UiSettingsParams { + category?: string[]; + // Warning: (ae-forgotten-export) The symbol "DeprecationSettings" needs to be exported by the entry point index.d.ts + deprecation?: DeprecationSettings; + description?: string; + name?: string; + optionLabels?: Record; + options?: string[]; + readonly?: boolean; + requiresPageReload?: boolean; + type?: UiSettingsType; + // (undocumented) + validation?: ImageValidation | StringValidation; + value?: SavedObjectAttribute; +} + // @public (undocumented) export interface UiSettingsState { // (undocumented) [key: string]: UiSettingsParams_2 & UserProvidedValues_2; } +// @public +export type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string' | 'array' | 'image'; + // @public export type UnmountCallback = () => void; +// @public +export interface UserProvidedValues { + // (undocumented) + isOverridden?: boolean; + // (undocumented) + userValue?: T; +} + ``` diff --git a/src/core/public/saved_objects/saved_objects_client.test.ts b/src/core/public/saved_objects/saved_objects_client.test.ts index e633e00965c6ab..0c34a16c68e99d 100644 --- a/src/core/public/saved_objects/saved_objects_client.test.ts +++ b/src/core/public/saved_objects/saved_objects_client.test.ts @@ -448,23 +448,4 @@ describe('SavedObjectsClient', () => { `); }); }); - - it('maintains backwards compatibility by transforming http.fetch errors to be compatible with kfetch errors', () => { - const err = { - response: { ok: false, redirected: false, status: 409, statusText: 'Conflict' }, - body: 'response body', - }; - http.fetch.mockRejectedValue(err); - return expect(savedObjectsClient.get(doc.type, doc.id)).rejects.toMatchInlineSnapshot(` - Object { - "body": "response body", - "res": Object { - "ok": false, - "redirected": false, - "status": 409, - "statusText": "Conflict", - }, - } - `); - }); }); diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index dab98ee66cdb10..ccb23793a85349 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -465,11 +465,7 @@ export class SavedObjectsClient { * uses `{response: {status: number}}`. */ private savedObjectsFetch(path: string, { method, query, body }: HttpFetchOptions) { - return this.http.fetch(path, { method, query, body }).catch(err => { - const kfetchError = Object.assign(err, { res: err.response }); - delete kfetchError.response; - return Promise.reject(kfetchError); - }); + return this.http.fetch(path, { method, query, body }); } } diff --git a/src/core/public/types.ts b/src/core/public/types.ts index 5abbb3c55813ac..267a9e9f7e0145 100644 --- a/src/core/public/types.ts +++ b/src/core/public/types.ts @@ -17,6 +17,14 @@ * under the License. */ +export { + UiSettingsParams, + UserProvidedValues, + UiSettingsType, + ImageValidation, + StringValidationRegex, +} from '../../core/types'; + /** * A function that should mount DOM content inside the provided container element * and return a handler to unmount it. diff --git a/src/core/server/elasticsearch/elasticsearch_service.ts b/src/core/server/elasticsearch/elasticsearch_service.ts index aba246ce66fb50..de111e1cb8b9b9 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.ts @@ -75,7 +75,7 @@ export class ElasticsearchService implements CoreService = {}) => { const finalConfig = merge({}, config, clientConfig); - return this.createClusterClient(type, finalConfig, deps.http.auth.getAuthHeaders); + return this.createClusterClient(type, finalConfig, deps.http.getAuthHeaders); }, }; } diff --git a/src/core/server/elasticsearch/retry_call_cluster.ts b/src/core/server/elasticsearch/retry_call_cluster.ts index 89d7b88b1675a0..bd72ecf7264616 100644 --- a/src/core/server/elasticsearch/retry_call_cluster.ts +++ b/src/core/server/elasticsearch/retry_call_cluster.ts @@ -22,6 +22,7 @@ import { defer, throwError, iif, timer } from 'rxjs'; import * as legacyElasticsearch from 'elasticsearch'; import { CallAPIOptions } from '.'; +import { APICaller } from './api_types'; import { Logger } from '../logging'; const esErrors = legacyElasticsearch.errors; @@ -34,15 +35,11 @@ const esErrors = legacyElasticsearch.errors; * different error is received. * * @param apiCaller + * @param log + * @param delay */ - -// TODO: Replace with APICaller from './scoped_cluster_client' once #46668 is merged export function migrationsRetryCallCluster( - apiCaller: ( - endpoint: string, - clientParams: Record, - options?: CallAPIOptions - ) => Promise, + apiCaller: APICaller, log: Logger, delay: number = 2500 ) { diff --git a/src/core/server/http/auth_state_storage.ts b/src/core/server/http/auth_state_storage.ts index 059dc7f3803514..10c8ccca324017 100644 --- a/src/core/server/http/auth_state_storage.ts +++ b/src/core/server/http/auth_state_storage.ts @@ -38,16 +38,16 @@ export enum AuthStatus { } /** - * Get authentication state for a request. Returned by `auth` interceptor. + * Gets authentication state for a request. Returned by `auth` interceptor. * @param request {@link KibanaRequest} - an incoming request. * @public */ -export type GetAuthState = ( +export type GetAuthState = ( request: KibanaRequest | LegacyRequest -) => { status: AuthStatus; state: unknown }; +) => { status: AuthStatus; state: T }; /** - * Return authentication status for a request. + * Returns authentication status for a request. * @param request {@link KibanaRequest} - an incoming request. * @public */ @@ -60,9 +60,9 @@ export class AuthStateStorage { public set = (request: KibanaRequest | LegacyRequest, state: unknown) => { this.storage.set(ensureRawRequest(request), state); }; - public get: GetAuthState = request => { + public get = (request: KibanaRequest | LegacyRequest) => { const key = ensureRawRequest(request); - const state = this.storage.get(key); + const state = this.storage.get(key) as T; const status: AuthStatus = this.storage.has(key) ? AuthStatus.authenticated : this.canBeAuthenticated() diff --git a/src/core/server/http/http_server.test.ts b/src/core/server/http/http_server.test.ts index df7b4b5af4267b..f8ef49b0f6d18b 100644 --- a/src/core/server/http/http_server.test.ts +++ b/src/core/server/http/http_server.test.ts @@ -1067,130 +1067,6 @@ describe('setup contract', () => { }); }); - describe('#auth.isAuthenticated()', () => { - it('returns true if has been authorized', async () => { - const { registerAuth, registerRouter, server: innerServer, auth } = await server.setup( - config - ); - - const router = new Router('', logger, enhanceWithContext); - router.get({ path: '/', validate: false }, (context, req, res) => - res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) - ); - registerRouter(router); - - await registerAuth((req, res, toolkit) => toolkit.authenticated()); - - await server.start(); - await supertest(innerServer.listener) - .get('/') - .expect(200, { isAuthenticated: true }); - }); - - it('returns false if has not been authorized', async () => { - const { registerAuth, registerRouter, server: innerServer, auth } = await server.setup( - config - ); - - const router = new Router('', logger, enhanceWithContext); - router.get( - { path: '/', validate: false, options: { authRequired: false } }, - (context, req, res) => res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) - ); - registerRouter(router); - - await registerAuth((req, res, toolkit) => toolkit.authenticated()); - - await server.start(); - await supertest(innerServer.listener) - .get('/') - .expect(200, { isAuthenticated: false }); - }); - - it('returns false if no authorization mechanism has been registered', async () => { - const { registerRouter, server: innerServer, auth } = await server.setup(config); - - const router = new Router('', logger, enhanceWithContext); - router.get( - { path: '/', validate: false, options: { authRequired: false } }, - (context, req, res) => res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) - ); - registerRouter(router); - - await server.start(); - await supertest(innerServer.listener) - .get('/') - .expect(200, { isAuthenticated: false }); - }); - }); - - describe('#auth.get()', () => { - it('returns authenticated status and allow associate auth state with request', async () => { - const user = { id: '42' }; - const { - createCookieSessionStorageFactory, - registerRouter, - registerAuth, - server: innerServer, - auth, - } = await server.setup(config); - const sessionStorageFactory = await createCookieSessionStorageFactory(cookieOptions); - registerAuth((req, res, toolkit) => { - sessionStorageFactory.asScoped(req).set({ value: user, expires: Date.now() + 1000 }); - return toolkit.authenticated({ state: user }); - }); - - const router = new Router('', logger, enhanceWithContext); - router.get({ path: '/', validate: false }, (context, req, res) => - res.ok({ body: auth.get(req) }) - ); - registerRouter(router); - await server.start(); - - await supertest(innerServer.listener) - .get('/') - .expect(200, { state: user, status: 'authenticated' }); - }); - - it('returns correct authentication unknown status', async () => { - const { registerRouter, server: innerServer, auth } = await server.setup(config); - - const router = new Router('', logger, enhanceWithContext); - router.get({ path: '/', validate: false }, (context, req, res) => - res.ok({ body: auth.get(req) }) - ); - - registerRouter(router); - await server.start(); - await supertest(innerServer.listener) - .get('/') - .expect(200, { status: 'unknown' }); - }); - - it('returns correct unauthenticated status', async () => { - const authenticate = jest.fn(); - - const { registerRouter, registerAuth, server: innerServer, auth } = await server.setup( - config - ); - await registerAuth(authenticate); - const router = new Router('', logger, enhanceWithContext); - router.get( - { path: '/', validate: false, options: { authRequired: false } }, - (context, req, res) => res.ok({ body: auth.get(req) }) - ); - - registerRouter(router); - await server.start(); - - await supertest(innerServer.listener) - .get('/') - .expect(200, { status: 'unauthenticated' }); - - expect(authenticate).not.toHaveBeenCalled(); - }); - }); - describe('#isTlsEnabled', () => { it('returns "true" if TLS enabled', async () => { const { isTlsEnabled } = await server.setup(configWithSSL); diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index 6b978b71c6f2b0..fdc272041ce354 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -32,7 +32,7 @@ import { SessionStorageCookieOptions, createCookieSessionStorageFactory, } from './cookie_session_storage'; -import { AuthStateStorage, GetAuthState, IsAuthenticated } from './auth_state_storage'; +import { IsAuthenticated, AuthStateStorage, GetAuthState } from './auth_state_storage'; import { AuthHeadersStorage, GetAuthHeaders } from './auth_headers_storage'; import { BasePath } from './base_path_service'; import { HttpServiceSetup } from './types'; @@ -53,10 +53,10 @@ export interface HttpServerSetup { registerOnPostAuth: HttpServiceSetup['registerOnPostAuth']; registerOnPreResponse: HttpServiceSetup['registerOnPreResponse']; isTlsEnabled: HttpServiceSetup['isTlsEnabled']; + getAuthHeaders: GetAuthHeaders; auth: { get: GetAuthState; isAuthenticated: IsAuthenticated; - getAuthHeaders: GetAuthHeaders; }; } @@ -120,8 +120,8 @@ export class HttpServer { auth: { get: this.authState.get, isAuthenticated: this.authState.isAuthenticated, - getAuthHeaders: this.authRequestHeaders.get, }, + getAuthHeaders: this.authRequestHeaders.get, isTlsEnabled: config.ssl.enabled, // Return server instance with the connection options so that we can properly // bridge core and the "legacy" Kibana internally. Once this bridge isn't diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index 6db1ca80ab4370..2b2d98d937e859 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -23,6 +23,7 @@ import { mockRouter } from './router/router.mock'; import { configMock } from '../config/config.mock'; import { InternalHttpServiceSetup } from './types'; import { HttpService } from './http_service'; +import { AuthStatus } from './auth_state_storage'; import { OnPreAuthToolkit } from './lifecycle/on_pre_auth'; import { AuthToolkit } from './lifecycle/auth'; import { sessionStorageMock } from './cookie_session_storage.mocks'; @@ -30,6 +31,7 @@ import { OnPostAuthToolkit } from './lifecycle/on_post_auth'; import { OnPreResponseToolkit } from './lifecycle/on_pre_response'; type BasePathMocked = jest.Mocked; +type AuthMocked = jest.Mocked; export type HttpServiceSetupMock = jest.Mocked & { basePath: BasePathMocked; }; @@ -42,6 +44,16 @@ const createBasePathMock = (serverBasePath = '/mock-server-basepath'): BasePathM remove: jest.fn(), }); +const createAuthMock = () => { + const mock: AuthMocked = { + get: jest.fn(), + isAuthenticated: jest.fn(), + }; + mock.get.mockReturnValue({ status: AuthStatus.authenticated, state: {} }); + mock.isAuthenticated.mockReturnValue(true); + return mock; +}; + const createSetupContractMock = () => { const setupContract: HttpServiceSetupMock = { // we can mock other hapi server methods when we need it @@ -62,17 +74,15 @@ const createSetupContractMock = () => { createRouter: jest.fn().mockImplementation(() => mockRouter.create({})), basePath: createBasePathMock(), csp: CspConfig.DEFAULT, - auth: { - get: jest.fn(), - isAuthenticated: jest.fn(), - getAuthHeaders: jest.fn(), - }, + auth: createAuthMock(), + getAuthHeaders: jest.fn(), isTlsEnabled: false, }; setupContract.createCookieSessionStorageFactory.mockResolvedValue( sessionStorageMock.createFactory() ); setupContract.createRouter.mockImplementation(() => mockRouter.create()); + setupContract.getAuthHeaders.mockReturnValue({ authorization: 'authorization-header' }); return setupContract; }; @@ -107,6 +117,7 @@ const createOnPreResponseToolkitMock = (): jest.Mocked => export const httpServiceMock = { create: createHttpServiceMock, createBasePath: createBasePathMock, + createAuth: createAuthMock, createSetupContract: createSetupContractMock, createOnPreAuthToolkit: createOnPreAuthToolkitMock, createOnPostAuthToolkit: createOnPostAuthToolkitMock, diff --git a/src/core/server/http/index.ts b/src/core/server/http/index.ts index 55ba813484268e..d31afe1670e419 100644 --- a/src/core/server/http/index.ts +++ b/src/core/server/http/index.ts @@ -29,6 +29,7 @@ export { HttpResponsePayload, ErrorHttpResponseOptions, KibanaRequest, + KibanaRequestEvents, KibanaRequestRoute, KibanaRequestRouteOptions, IKibanaResponse, diff --git a/src/core/server/http/integration_tests/core_services.test.ts b/src/core/server/http/integration_tests/core_services.test.ts index 65c4f1432721de..65b8ba551cf916 100644 --- a/src/core/server/http/integration_tests/core_services.test.ts +++ b/src/core/server/http/integration_tests/core_services.test.ts @@ -32,17 +32,132 @@ interface StorageData { expires: number; } +const cookieOptions = { + name: 'sid', + encryptionKey: 'something_at_least_32_characters', + validate: () => ({ isValid: true }), + isSecure: false, +}; + describe('http service', () => { + describe('auth', () => { + let root: ReturnType; + beforeEach(async () => { + root = kbnTestServer.createRoot(); + }, 30000); + + afterEach(async () => { + await root.shutdown(); + }); + describe('#isAuthenticated()', () => { + it('returns true if has been authorized', async () => { + const { http } = await root.setup(); + const { registerAuth, createRouter, auth } = http; + + await registerAuth((req, res, toolkit) => toolkit.authenticated()); + + const router = createRouter(''); + router.get({ path: '/is-auth', validate: false }, (context, req, res) => + res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) + ); + + await root.start(); + await kbnTestServer.request.get(root, '/is-auth').expect(200, { isAuthenticated: true }); + }); + + it('returns false if has not been authorized', async () => { + const { http } = await root.setup(); + const { registerAuth, createRouter, auth } = http; + + await registerAuth((req, res, toolkit) => toolkit.authenticated()); + + const router = createRouter(''); + router.get( + { path: '/is-auth', validate: false, options: { authRequired: false } }, + (context, req, res) => res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) + ); + + await root.start(); + await kbnTestServer.request.get(root, '/is-auth').expect(200, { isAuthenticated: false }); + }); + + it('returns false if no authorization mechanism has been registered', async () => { + const { http } = await root.setup(); + const { createRouter, auth } = http; + + const router = createRouter(''); + router.get( + { path: '/is-auth', validate: false, options: { authRequired: false } }, + (context, req, res) => res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) + ); + + await root.start(); + await kbnTestServer.request.get(root, '/is-auth').expect(200, { isAuthenticated: false }); + }); + }); + describe('#get()', () => { + it('returns authenticated status and allow associate auth state with request', async () => { + const user = { id: '42' }; + + const { http } = await root.setup(); + const { createCookieSessionStorageFactory, createRouter, registerAuth, auth } = http; + const sessionStorageFactory = await createCookieSessionStorageFactory(cookieOptions); + registerAuth((req, res, toolkit) => { + sessionStorageFactory.asScoped(req).set({ value: user }); + return toolkit.authenticated({ state: user }); + }); + + const router = createRouter(''); + router.get({ path: '/get-auth', validate: false }, (context, req, res) => + res.ok({ body: auth.get<{ id: string }>(req) }) + ); + + await root.start(); + + await kbnTestServer.request + .get(root, '/get-auth') + .expect(200, { state: user, status: 'authenticated' }); + }); + + it('returns correct authentication unknown status', async () => { + const { http } = await root.setup(); + const { createRouter, auth } = http; + + const router = createRouter(''); + router.get({ path: '/get-auth', validate: false }, (context, req, res) => + res.ok({ body: auth.get(req) }) + ); + + await root.start(); + await kbnTestServer.request.get(root, '/get-auth').expect(200, { status: 'unknown' }); + }); + + it('returns correct unauthenticated status', async () => { + const authenticate = jest.fn(); + + const { http } = await root.setup(); + const { createRouter, registerAuth, auth } = http; + await registerAuth(authenticate); + const router = createRouter(''); + router.get( + { path: '/get-auth', validate: false, options: { authRequired: false } }, + (context, req, res) => res.ok({ body: auth.get(req) }) + ); + + await root.start(); + + await kbnTestServer.request + .get(root, '/get-auth') + .expect(200, { status: 'unauthenticated' }); + + expect(authenticate).not.toHaveBeenCalled(); + }); + }); + }); + describe('legacy server', () => { describe('#registerAuth()', () => { const sessionDurationMs = 1000; - const cookieOptions = { - name: 'sid', - encryptionKey: 'something_at_least_32_characters', - validate: () => ({ isValid: true }), - isSecure: false, - path: '/', - }; let root: ReturnType; beforeEach(async () => { diff --git a/src/core/server/http/integration_tests/request.test.ts b/src/core/server/http/integration_tests/request.test.ts new file mode 100644 index 00000000000000..bc1bbc881315ab --- /dev/null +++ b/src/core/server/http/integration_tests/request.test.ts @@ -0,0 +1,127 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import supertest from 'supertest'; + +import { HttpService } from '../http_service'; + +import { contextServiceMock } from '../../context/context_service.mock'; +import { loggingServiceMock } from '../../logging/logging_service.mock'; +import { createHttpServer } from '../test_utils'; + +let server: HttpService; + +let logger: ReturnType; +const contextSetup = contextServiceMock.createSetupContract(); + +const setupDeps = { + context: contextSetup, +}; + +beforeEach(() => { + logger = loggingServiceMock.create(); + + server = createHttpServer({ logger }); +}); + +afterEach(async () => { + await server.stop(); +}); + +const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); +describe('KibanaRequest', () => { + describe('events', () => { + describe('aborted$', () => { + it('emits once and completes when request aborted', async done => { + expect.assertions(1); + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + + const nextSpy = jest.fn(); + router.get({ path: '/', validate: false }, async (context, request, res) => { + request.events.aborted$.subscribe({ + next: nextSpy, + complete: () => { + expect(nextSpy).toHaveBeenCalledTimes(1); + done(); + }, + }); + + // prevents the server to respond + await delay(30000); + return res.ok({ body: 'ok' }); + }); + + await server.start(); + + const incomingRequest = supertest(innerServer.listener) + .get('/') + // end required to send request + .end(); + + setTimeout(() => incomingRequest.abort(), 50); + }); + + it('completes & does not emit when request handled', async () => { + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + + const nextSpy = jest.fn(); + const completeSpy = jest.fn(); + router.get({ path: '/', validate: false }, async (context, request, res) => { + request.events.aborted$.subscribe({ + next: nextSpy, + complete: completeSpy, + }); + + return res.ok({ body: 'ok' }); + }); + + await server.start(); + + await supertest(innerServer.listener).get('/'); + + expect(nextSpy).toHaveBeenCalledTimes(0); + expect(completeSpy).toHaveBeenCalledTimes(1); + }); + + it('completes & does not emit when request rejected', async () => { + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + + const nextSpy = jest.fn(); + const completeSpy = jest.fn(); + router.get({ path: '/', validate: false }, async (context, request, res) => { + request.events.aborted$.subscribe({ + next: nextSpy, + complete: completeSpy, + }); + + return res.badRequest(); + }); + + await server.start(); + + await supertest(innerServer.listener).get('/'); + + expect(nextSpy).toHaveBeenCalledTimes(0); + expect(completeSpy).toHaveBeenCalledTimes(1); + }); + }); + }); +}); diff --git a/src/core/server/http/router/index.ts b/src/core/server/http/router/index.ts index 084d30d6944744..32663d1513f36b 100644 --- a/src/core/server/http/router/index.ts +++ b/src/core/server/http/router/index.ts @@ -21,6 +21,7 @@ export { Headers, filterHeaders, ResponseHeaders, KnownHeaders } from './headers export { Router, RequestHandler, IRouter, RouteRegistrar } from './router'; export { KibanaRequest, + KibanaRequestEvents, KibanaRequestRoute, KibanaRequestRouteOptions, isRealRequest, diff --git a/src/core/server/http/router/request.test.ts b/src/core/server/http/router/request.test.ts index 51162a2c258e91..032027c2344858 100644 --- a/src/core/server/http/router/request.test.ts +++ b/src/core/server/http/router/request.test.ts @@ -66,6 +66,57 @@ describe('KibanaRequest', () => { }); }); + describe('isSytemApi property', () => { + it('is false when no kbn-system-request header is set', () => { + const request = httpServerMock.createRawRequest({ + headers: { custom: 'one' }, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.isSystemRequest).toBe(false); + }); + + it('is true when kbn-system-request header is set to true', () => { + const request = httpServerMock.createRawRequest({ + headers: { custom: 'one', 'kbn-system-request': 'true' }, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.isSystemRequest).toBe(true); + }); + + it('is false when kbn-system-request header is set to false', () => { + const request = httpServerMock.createRawRequest({ + headers: { custom: 'one', 'kbn-system-request': 'false' }, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.isSystemRequest).toBe(false); + }); + + // Remove support for kbn-system-api header in 8.x. Only used by legacy platform. + it('is false when no kbn-system-api header is set', () => { + const request = httpServerMock.createRawRequest({ + headers: { custom: 'one' }, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.isSystemRequest).toBe(false); + }); + + it('is true when kbn-system-api header is set to true', () => { + const request = httpServerMock.createRawRequest({ + headers: { custom: 'one', 'kbn-system-api': 'true' }, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.isSystemRequest).toBe(true); + }); + + it('is false when kbn-system-api header is set to false', () => { + const request = httpServerMock.createRawRequest({ + headers: { custom: 'one', 'kbn-system-api': 'false' }, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.isSystemRequest).toBe(false); + }); + }); + describe('RouteSchema type inferring', () => { it('should work with config-schema', () => { const body = Buffer.from('body!'); diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index 47b001700b0154..703571ba53c0a3 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -19,6 +19,8 @@ import { Url } from 'url'; import { Request } from 'hapi'; +import { Observable, fromEvent, merge } from 'rxjs'; +import { shareReplay, first, takeUntil } from 'rxjs/operators'; import { deepFreeze, RecursiveReadonly } from '../../../utils'; import { Headers } from './headers'; @@ -46,6 +48,17 @@ export interface KibanaRequestRoute { options: KibanaRequestRouteOptions; } +/** + * Request events. + * @public + * */ +export interface KibanaRequestEvents { + /** + * Observable that emits once if and when the request has been aborted. + */ + aborted$: Observable; +} + /** * @deprecated * `hapi` request object, supported during migration process only for backward compatibility. @@ -114,8 +127,16 @@ export class KibanaRequest< * This property will contain a `filtered` copy of request headers. */ public readonly headers: Headers; + /** + * Whether or not the request is a "system request" rather than an application-level request. + * Can be set on the client using the `HttpFetchOptions#asSystemRequest` option. + */ + public readonly isSystemRequest: boolean; + /** {@link IKibanaSocket} */ public readonly socket: IKibanaSocket; + /** Request events {@link KibanaRequestEvents} */ + public readonly events: KibanaRequestEvents; /** @internal */ protected readonly [requestSymbol]: Request; @@ -131,6 +152,10 @@ export class KibanaRequest< ) { this.url = request.url; this.headers = deepFreeze({ ...request.headers }); + this.isSystemRequest = + request.headers['kbn-system-request'] === 'true' || + // Remove support for `kbn-system-api` in 8.x. Used only by legacy platform. + request.headers['kbn-system-api'] === 'true'; // prevent Symbol exposure via Object.getOwnPropertySymbols() Object.defineProperty(this, requestSymbol, { @@ -138,12 +163,22 @@ export class KibanaRequest< enumerable: false, }); - this.route = deepFreeze(this.getRouteInfo()); + this.route = deepFreeze(this.getRouteInfo(request)); this.socket = new KibanaSocket(request.raw.req.socket); + this.events = this.getEvents(request); + } + + private getEvents(request: Request): KibanaRequestEvents { + const finish$ = merge( + fromEvent(request.raw.req, 'end'), // all data consumed + fromEvent(request.raw.req, 'close') // connection was closed + ).pipe(shareReplay(1), first()); + return { + aborted$: fromEvent(request.raw.req, 'aborted').pipe(first(), takeUntil(finish$)), + } as const; } - private getRouteInfo(): KibanaRequestRoute { - const request = this[requestSymbol]; + private getRouteInfo(request: Request): KibanaRequestRoute { const method = request.method as Method; const { parse, maxBytes, allow, output } = request.route.settings.payload || {}; diff --git a/src/core/server/http/types.ts b/src/core/server/http/types.ts index 9c8bfc073a5248..01b852c26ec934 100644 --- a/src/core/server/http/types.ts +++ b/src/core/server/http/types.ts @@ -18,6 +18,8 @@ */ import { IContextProvider, IContextContainer } from '../context'; import { ICspConfig } from '../csp'; +import { GetAuthState, IsAuthenticated } from './auth_state_storage'; +import { GetAuthHeaders } from './auth_headers_storage'; import { RequestHandler, IRouter } from './router'; import { HttpServerSetup } from './http_server'; import { SessionStorageCookieOptions } from './cookie_session_storage'; @@ -183,6 +185,19 @@ export interface HttpServiceSetup { */ basePath: IBasePath; + auth: { + /** + * Gets authentication state for a request. Returned by `auth` interceptor. + * {@link GetAuthState} + */ + get: GetAuthState; + /** + * Returns authentication status for a request. + * {@link IsAuthenticated} + */ + isAuthenticated: IsAuthenticated; + }; + /** * The CSP config used for Kibana. */ @@ -245,6 +260,7 @@ export interface InternalHttpServiceSetup auth: HttpServerSetup['auth']; server: HttpServerSetup['server']; createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter; + getAuthHeaders: GetAuthHeaders; registerRouteHandlerContext: ( pluginOpaqueId: PluginOpaqueId, contextName: T, diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 3f67b9a656bb79..91f38c9f2ddbe9 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -109,6 +109,7 @@ export { IKibanaSocket, IsAuthenticated, KibanaRequest, + KibanaRequestEvents, KibanaRequestRoute, KibanaRequestRouteOptions, IKibanaResponse, @@ -179,6 +180,7 @@ export { SavedObjectsClientWrapperFactory, SavedObjectsClientWrapperOptions, SavedObjectsClientFactory, + SavedObjectsClientFactoryProvider, SavedObjectsCreateOptions, SavedObjectsErrorHelpers, SavedObjectsExportOptions, @@ -194,6 +196,7 @@ export { SavedObjectsImportUnsupportedTypeError, SavedObjectsMigrationLogger, SavedObjectsRawDoc, + SavedObjectsRepositoryFactory, SavedObjectsResolveImportErrorsOptions, SavedObjectsSchema, SavedObjectsSerializer, @@ -219,6 +222,8 @@ export { ImageValidation, DeprecationSettings, StringValidation, + StringValidationRegex, + StringValidationRegexString, } from './ui_settings'; export { RecursiveReadonly } from '../utils'; diff --git a/src/core/server/legacy/config/get_unused_config_keys.ts b/src/core/server/legacy/config/get_unused_config_keys.ts index e425082ba126dc..20c9776f63c581 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.ts @@ -20,7 +20,8 @@ import { difference, get, set } from 'lodash'; // @ts-ignore import { getTransform } from '../../../../legacy/deprecation/index'; -import { unset, getFlattenedObject } from '../../../../legacy/utils'; +import { unset } from '../../../../legacy/utils'; +import { getFlattenedObject } from '../../../utils'; import { hasConfigPathIntersection } from '../../config'; import { LegacyPluginSpec, LegacyConfig, LegacyVars } from '../types'; diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index 07cc9330330545..d0e0453564f943 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -258,7 +258,11 @@ export class LegacyService implements CoreService { ) { const coreStart: CoreStart = { capabilities: startDeps.core.capabilities, - savedObjects: { getScopedClient: startDeps.core.savedObjects.getScopedClient }, + savedObjects: { + getScopedClient: startDeps.core.savedObjects.getScopedClient, + createScopedRepository: startDeps.core.savedObjects.createScopedRepository, + createInternalRepository: startDeps.core.savedObjects.createInternalRepository, + }, uiSettings: { asScopedToClient: startDeps.core.uiSettings.asScopedToClient }, }; @@ -282,14 +286,16 @@ export class LegacyService implements CoreService { registerOnPostAuth: setupDeps.core.http.registerOnPostAuth, registerOnPreResponse: setupDeps.core.http.registerOnPreResponse, basePath: setupDeps.core.http.basePath, + auth: { + get: setupDeps.core.http.auth.get, + isAuthenticated: setupDeps.core.http.auth.isAuthenticated, + }, csp: setupDeps.core.http.csp, isTlsEnabled: setupDeps.core.http.isTlsEnabled, }, savedObjects: { - setClientFactory: setupDeps.core.savedObjects.setClientFactory, + setClientFactoryProvider: setupDeps.core.savedObjects.setClientFactoryProvider, addClientWrapper: setupDeps.core.savedObjects.addClientWrapper, - createInternalRepository: setupDeps.core.savedObjects.createInternalRepository, - createScopedRepository: setupDeps.core.savedObjects.createScopedRepository, }, uiSettings: { register: setupDeps.core.uiSettings.register, diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts index 9867274d224bd0..a19133c30659b0 100644 --- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts +++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts @@ -65,6 +65,7 @@ function getUiAppsNavLinks({ uiAppSpecs = [] }: LegacyUiExports, pluginSpecs: Le return { id, + category: spec.category, title: spec.title, order: typeof spec.order === 'number' ? spec.order : 0, icon: spec.icon, @@ -79,6 +80,7 @@ function getNavLinks(uiExports: LegacyUiExports, pluginSpecs: LegacyPluginSpec[] return (uiExports.navLinkSpecs || []) .map(spec => ({ id: spec.id, + category: spec.category, title: spec.title, order: typeof spec.order === 'number' ? spec.order : 0, url: spec.url, diff --git a/src/core/server/legacy/types.ts b/src/core/server/legacy/types.ts index 40b8244a318903..d51058ca561c6b 100644 --- a/src/core/server/legacy/types.ts +++ b/src/core/server/legacy/types.ts @@ -139,7 +139,7 @@ export type LegacyNavLinkSpec = Record & ChromeNavLink; */ export type LegacyAppSpec = Pick< ChromeNavLink, - 'title' | 'order' | 'icon' | 'euiIconType' | 'url' | 'linkToLastSubUrl' | 'hidden' + 'title' | 'order' | 'icon' | 'euiIconType' | 'url' | 'linkToLastSubUrl' | 'hidden' | 'category' > & { pluginId?: string; id?: string; listed?: boolean }; /** diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index c0a8973d98a548..50ce507520d048 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -101,6 +101,10 @@ function createCoreSetupMock() { isTlsEnabled: httpService.isTlsEnabled, createRouter: jest.fn(), registerRouteHandlerContext: jest.fn(), + auth: { + get: httpService.auth.get, + isAuthenticated: httpService.auth.isAuthenticated, + }, }; httpMock.createRouter.mockImplementation(() => httpService.createRouter('')); diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index f266172cb4bd9e..30e5209b2fc6a1 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -161,14 +161,13 @@ export function createPluginSetupContext( registerOnPostAuth: deps.http.registerOnPostAuth, registerOnPreResponse: deps.http.registerOnPreResponse, basePath: deps.http.basePath, + auth: { get: deps.http.auth.get, isAuthenticated: deps.http.auth.isAuthenticated }, csp: deps.http.csp, isTlsEnabled: deps.http.isTlsEnabled, }, savedObjects: { - setClientFactory: deps.savedObjects.setClientFactory, + setClientFactoryProvider: deps.savedObjects.setClientFactoryProvider, addClientWrapper: deps.savedObjects.addClientWrapper, - createInternalRepository: deps.savedObjects.createInternalRepository, - createScopedRepository: deps.savedObjects.createScopedRepository, }, uiSettings: { register: deps.uiSettings.register, @@ -203,6 +202,8 @@ export function createPluginStartContext( }, savedObjects: { getScopedClient: deps.savedObjects.getScopedClient, + createInternalRepository: deps.savedObjects.createInternalRepository, + createScopedRepository: deps.savedObjects.createScopedRepository, }, uiSettings: { asScopedToClient: deps.uiSettings.asScopedToClient, diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts index 1100c18bcc72fa..181025d73817dc 100644 --- a/src/core/server/saved_objects/index.ts +++ b/src/core/server/saved_objects/index.ts @@ -41,6 +41,7 @@ export { SavedObjectsServiceStart, SavedObjectsServiceSetup, InternalSavedObjectsServiceSetup, + SavedObjectsRepositoryFactory, } from './saved_objects_service'; export { 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 b2596146a02d47..a15d1f5b864b7d 100644 --- a/src/core/server/saved_objects/saved_objects_service.mock.ts +++ b/src/core/server/saved_objects/saved_objects_service.mock.ts @@ -33,29 +33,27 @@ const createStartContractMock = () => { const startContract: jest.Mocked = { clientProvider: savedObjectsClientProviderMock.create(), getScopedClient: jest.fn(), + createInternalRepository: jest.fn(), + createScopedRepository: jest.fn(), migrator: mockKibanaMigrator.create(), }; + startContract.getScopedClient.mockReturnValue(savedObjectsClientMock.create()); + startContract.createInternalRepository.mockReturnValue(savedObjectsRepositoryMock.create()); + startContract.createScopedRepository.mockReturnValue(savedObjectsRepositoryMock.create()); + return startContract; }; const createSetupContractMock = () => { const setupContract: jest.Mocked = { - getScopedClient: jest.fn(), - setClientFactory: jest.fn(), + setClientFactoryProvider: jest.fn(), addClientWrapper: jest.fn(), - createInternalRepository: jest.fn(), - createScopedRepository: jest.fn(), }; - - setupContract.getScopedClient.mockReturnValue(savedObjectsClientMock.create()); - setupContract.createInternalRepository.mockReturnValue(savedObjectsRepositoryMock.create()); - setupContract.createScopedRepository.mockReturnValue(savedObjectsRepositoryMock.create()); - return setupContract; }; -const createsavedObjectsServiceMock = () => { +const createSavedObjectsServiceMock = () => { const mocked: jest.Mocked = { setup: jest.fn(), start: jest.fn(), @@ -69,7 +67,7 @@ const createsavedObjectsServiceMock = () => { }; export const savedObjectsServiceMock = { - create: createsavedObjectsServiceMock, + create: createSavedObjectsServiceMock, createSetupContract: createSetupContractMock, createStartContract: createStartContractMock, }; diff --git a/src/core/server/saved_objects/saved_objects_service.test.mocks.ts b/src/core/server/saved_objects/saved_objects_service.test.mocks.ts new file mode 100644 index 00000000000000..a9ad0778d4757d --- /dev/null +++ b/src/core/server/saved_objects/saved_objects_service.test.mocks.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { mockKibanaMigrator } from './migrations/kibana/kibana_migrator.mock'; +import { savedObjectsClientProviderMock } from './service/lib/scoped_client_provider.mock'; + +export const migratorInstanceMock = mockKibanaMigrator.create(); +export const KibanaMigratorMock = jest.fn().mockImplementation(() => migratorInstanceMock); +jest.doMock('./migrations/kibana/kibana_migrator', () => ({ + KibanaMigrator: KibanaMigratorMock, +})); + +export const clientProviderInstanceMock = savedObjectsClientProviderMock.create(); +jest.doMock('./service/lib/scoped_client_provider', () => ({ + SavedObjectsClientProvider: jest.fn().mockImplementation(() => clientProviderInstanceMock), +})); diff --git a/src/core/server/saved_objects/saved_objects_service.test.ts b/src/core/server/saved_objects/saved_objects_service.test.ts index deb6f98e17b7b7..6668d57045a957 100644 --- a/src/core/server/saved_objects/saved_objects_service.test.ts +++ b/src/core/server/saved_objects/saved_objects_service.test.ts @@ -17,95 +17,149 @@ * under the License. */ -jest.mock('./migrations/kibana/kibana_migrator'); +import { + KibanaMigratorMock, + migratorInstanceMock, + clientProviderInstanceMock, +} from './saved_objects_service.test.mocks'; -import { SavedObjectsService, SavedObjectsSetupDeps } from './saved_objects_service'; +import { SavedObjectsService } from './saved_objects_service'; import { mockCoreContext } from '../core_context.mock'; -// @ts-ignore Typescript doesn't know about the jest mock -import { KibanaMigrator, mockKibanaMigratorInstance } from './migrations/kibana/kibana_migrator'; import * as legacyElasticsearch from 'elasticsearch'; import { Env } from '../config'; import { configServiceMock } from '../mocks'; - -afterEach(() => { - jest.clearAllMocks(); -}); +import { elasticsearchServiceMock } from '../elasticsearch/elasticsearch_service.mock'; +import { legacyServiceMock } from '../legacy/legacy_service.mock'; +import { SavedObjectsClientFactoryProvider } from './service/lib'; describe('SavedObjectsService', () => { + const createSetupDeps = () => { + return { + elasticsearch: elasticsearchServiceMock.createInternalSetup(), + legacyPlugins: legacyServiceMock.createDiscoverPlugins(), + }; + }; + + afterEach(() => { + jest.clearAllMocks(); + }); + describe('#setup()', () => { + describe('#setClientFactoryProvider', () => { + it('registers the factory to the clientProvider', async () => { + const coreContext = mockCoreContext.create(); + const soService = new SavedObjectsService(coreContext); + const setup = await soService.setup(createSetupDeps()); + + const factory = jest.fn(); + const factoryProvider: SavedObjectsClientFactoryProvider = () => factory; + + setup.setClientFactoryProvider(factoryProvider); + + await soService.start({}); + + expect(clientProviderInstanceMock.setClientFactory).toHaveBeenCalledWith(factory); + }); + it('throws if a factory is already registered', async () => { + const coreContext = mockCoreContext.create(); + const soService = new SavedObjectsService(coreContext); + const setup = await soService.setup(createSetupDeps()); + + const firstFactory = () => jest.fn(); + const secondFactory = () => jest.fn(); + + setup.setClientFactoryProvider(firstFactory); + + expect(() => { + setup.setClientFactoryProvider(secondFactory); + }).toThrowErrorMatchingInlineSnapshot( + `"custom client factory is already set, and can only be set once"` + ); + }); + }); + + describe('#addClientWrapper', () => { + it('registers the wrapper to the clientProvider', async () => { + const coreContext = mockCoreContext.create(); + const soService = new SavedObjectsService(coreContext); + const setup = await soService.setup(createSetupDeps()); + + const wrapperA = jest.fn(); + const wrapperB = jest.fn(); + + setup.addClientWrapper(1, 'A', wrapperA); + setup.addClientWrapper(2, 'B', wrapperB); + + await soService.start({}); + + expect(clientProviderInstanceMock.addClientWrapperFactory).toHaveBeenCalledTimes(2); + expect(clientProviderInstanceMock.addClientWrapperFactory).toHaveBeenCalledWith( + 1, + 'A', + wrapperA + ); + expect(clientProviderInstanceMock.addClientWrapperFactory).toHaveBeenCalledWith( + 2, + 'B', + wrapperB + ); + }); + }); + }); + + describe('#start()', () => { it('creates a KibanaMigrator which retries NoConnections errors from callAsInternalUser', async () => { const coreContext = mockCoreContext.create(); - let i = 0; - const clusterClient = { - callAsInternalUser: jest - .fn() - .mockImplementation(() => - i++ <= 2 - ? Promise.reject(new legacyElasticsearch.errors.NoConnections()) - : Promise.resolve('success') - ), - }; const soService = new SavedObjectsService(coreContext); - const coreSetup = ({ - elasticsearch: { adminClient: clusterClient }, - legacyPlugins: { uiExports: { savedObjectMappings: [] }, pluginExtendedConfig: {} }, - } as unknown) as SavedObjectsSetupDeps; + const coreSetup = createSetupDeps(); + + let i = 0; + coreSetup.elasticsearch.adminClient.callAsInternalUser = jest + .fn() + .mockImplementation(() => + i++ <= 2 + ? Promise.reject(new legacyElasticsearch.errors.NoConnections()) + : Promise.resolve('success') + ); - await soService.setup(coreSetup, 1); + await soService.setup(coreSetup); + await soService.start({}, 1); - return expect((KibanaMigrator as jest.Mock).mock.calls[0][0].callCluster()).resolves.toMatch( - 'success' - ); + return expect(KibanaMigratorMock.mock.calls[0][0].callCluster()).resolves.toMatch('success'); }); - }); - describe('#start()', () => { it('skips KibanaMigrator migrations when --optimize=true', async () => { const coreContext = mockCoreContext.create({ env: ({ cliArgs: { optimize: true }, packageInfo: { version: 'x.x.x' } } as unknown) as Env, }); const soService = new SavedObjectsService(coreContext); - const coreSetup = ({ - elasticsearch: { adminClient: { callAsInternalUser: jest.fn() } }, - legacyPlugins: { uiExports: {}, pluginExtendedConfig: {} }, - } as unknown) as SavedObjectsSetupDeps; - await soService.setup(coreSetup); + await soService.setup(createSetupDeps()); await soService.start({}); - expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledWith(true); + expect(migratorInstanceMock.runMigrations).toHaveBeenCalledWith(true); }); it('skips KibanaMigrator migrations when migrations.skip=true', async () => { const configService = configServiceMock.create({ atPath: { skip: true } }); const coreContext = mockCoreContext.create({ configService }); const soService = new SavedObjectsService(coreContext); - const coreSetup = ({ - elasticsearch: { adminClient: { callAsInternalUser: jest.fn() } }, - legacyPlugins: { uiExports: {}, pluginExtendedConfig: {} }, - } as unknown) as SavedObjectsSetupDeps; - - await soService.setup(coreSetup); + await soService.setup(createSetupDeps()); await soService.start({}); - expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledWith(true); + expect(migratorInstanceMock.runMigrations).toHaveBeenCalledWith(true); }); it('resolves with KibanaMigrator after waiting for migrations to complete', async () => { const configService = configServiceMock.create({ atPath: { skip: false } }); const coreContext = mockCoreContext.create({ configService }); const soService = new SavedObjectsService(coreContext); - const coreSetup = ({ - elasticsearch: { adminClient: { callAsInternalUser: jest.fn() } }, - legacyPlugins: { uiExports: {}, pluginExtendedConfig: {} }, - } as unknown) as SavedObjectsSetupDeps; - - await soService.setup(coreSetup); - expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledTimes(0); + await soService.setup(createSetupDeps()); + expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(0); const startContract = await soService.start({}); - expect(startContract.migrator).toBe(mockKibanaMigratorInstance); - expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledWith(false); - expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledTimes(1); + expect(startContract.migrator).toBe(migratorInstanceMock); + expect(migratorInstanceMock.runMigrations).toHaveBeenCalledWith(false); + expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(1); }); }); }); diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index 69ca8306ca4da8..b08033a19242b0 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -37,13 +37,17 @@ import { KibanaRequest } from '../http'; import { SavedObjectsClientContract } from './types'; import { ISavedObjectsRepository, SavedObjectsRepository } from './service/lib/repository'; import { - SavedObjectsClientFactory, + SavedObjectsClientFactoryProvider, SavedObjectsClientWrapperFactory, } from './service/lib/scoped_client_provider'; -import { Logger } from '..'; +import { Logger } from '../logging'; +import { SavedObjectsMapping } from './mappings'; +import { MigrationDefinition } from './migrations/core/document_migrator'; +import { SavedObjectsSchemaDefinition } from './schema'; +import { PropertyValidators } from './validation'; /** - * Saved Objects is Kibana's data persisentence mechanism allowing plugins to + * Saved Objects is Kibana's data persistence mechanism allowing plugins to * use Elasticsearch for storing and querying state. The * SavedObjectsServiceSetup API exposes methods for creating and registering * Saved Object client wrappers. @@ -66,11 +70,11 @@ import { Logger } from '..'; * constructor. * * @example - * import {SavedObjectsClient, CoreSetup} from 'src/core/server'; + * import { SavedObjectsClient, CoreSetup } from 'src/core/server'; * * export class Plugin() { * setup: (core: CoreSetup) => { - * core.savedObjects.setClientFactory(({request: KibanaRequest}) => { + * core.savedObjects.setClientFactory(({ request: KibanaRequest }) => { * return new SavedObjectsClient(core.savedObjects.scopedRepository(request)); * }) * } @@ -80,61 +84,25 @@ import { Logger } from '..'; */ export interface SavedObjectsServiceSetup { /** - * Set a default factory for creating Saved Objects clients. Only one client - * factory can be set, subsequent calls to this method will fail. + * Set the default {@link SavedObjectsClientFactoryProvider | factory provider} for creating Saved Objects clients. + * Only one provider can be set, subsequent calls to this method will fail. */ - setClientFactory: (customClientFactory: SavedObjectsClientFactory) => void; + setClientFactoryProvider: (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void; /** - * Add a client wrapper with the given priority. + * Add a {@link SavedObjectsClientWrapperFactory | client wrapper factory} with the given priority. */ addClientWrapper: ( priority: number, id: string, - factory: SavedObjectsClientWrapperFactory + factory: SavedObjectsClientWrapperFactory ) => void; - - /** - * Creates a {@link ISavedObjectsRepository | Saved Objects repository} that - * uses the credentials from the passed in request to authenticate with - * Elasticsearch. - * - * @remarks - * The repository should only be used for creating and registering a client - * factory or client wrapper. Using the repository directly for interacting - * with Saved Objects is an anti-pattern. Use the Saved Objects client from - * the - * {@link SavedObjectsServiceStart | SavedObjectsServiceStart#getScopedClient } - * method or the {@link RequestHandlerContext | route handler context} - * instead. - */ - createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; - - /** - * Creates a {@link ISavedObjectsRepository | Saved Objects repository} that - * uses the internal Kibana user for authenticating with Elasticsearch. - * - * @remarks - * The repository should only be used for creating and registering a client - * factory or client wrapper. Using the repository directly for interacting - * with Saved Objects is an anti-pattern. Use the Saved Objects client from - * the - * {@link SavedObjectsServiceStart | SavedObjectsServiceStart#getScopedClient } - * method or the {@link RequestHandlerContext | route handler context} - * instead. - */ - createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; } /** * @internal */ -export interface InternalSavedObjectsServiceSetup extends SavedObjectsServiceSetup { - getScopedClient: ( - req: KibanaRequest, - options?: SavedObjectsClientProviderOptions - ) => SavedObjectsClientContract; -} +export type InternalSavedObjectsServiceSetup = SavedObjectsServiceSetup; /** * Saved Objects is Kibana's data persisentence mechanism allowing plugins to @@ -158,6 +126,26 @@ export interface SavedObjectsServiceStart { req: KibanaRequest, options?: SavedObjectsClientProviderOptions ) => SavedObjectsClientContract; + /** + * Creates a {@link ISavedObjectsRepository | Saved Objects repository} that + * uses the credentials from the passed in request to authenticate with + * Elasticsearch. + * + * @param req - The request to create the scoped repository from. + * @param extraTypes - A list of additional hidden types the repository should have access to. + * + * @remarks + * Prefer using `getScopedClient`. This should only be used when using methods + * not exposed on {@link SavedObjectsClientContract} + */ + createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; + /** + * Creates a {@link ISavedObjectsRepository | Saved Objects repository} that + * uses the internal Kibana user for authenticating with Elasticsearch. + * + * @param extraTypes - A list of additional hidden types the repository should have access to. + */ + createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; } export interface InternalSavedObjectsServiceStart extends SavedObjectsServiceStart { @@ -171,130 +159,200 @@ export interface InternalSavedObjectsServiceStart extends SavedObjectsServiceSta clientProvider: ISavedObjectsClientProvider; } +/** + * Factory provided when invoking a {@link SavedObjectsClientFactoryProvider | client factory provider} + * See {@link SavedObjectsServiceSetup.setClientFactoryProvider} + * + * @public + */ +export interface SavedObjectsRepositoryFactory { + /** + * Creates a {@link ISavedObjectsRepository | Saved Objects repository} that + * uses the credentials from the passed in request to authenticate with + * Elasticsearch. + * + * @param extraTypes - A list of additional hidden types the repository should have access to. + */ + createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; + /** + * Creates a {@link ISavedObjectsRepository | Saved Objects repository} that + * uses the internal Kibana user for authenticating with Elasticsearch. + * + * @param extraTypes - A list of additional hidden types the repository should have access to. + */ + createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; +} + /** @internal */ export interface SavedObjectsSetupDeps { legacyPlugins: LegacyServiceDiscoverPlugins; elasticsearch: InternalElasticsearchServiceSetup; } +interface WrappedClientFactoryWrapper { + priority: number; + id: string; + factory: SavedObjectsClientWrapperFactory; +} + /** @internal */ // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SavedObjectsStartDeps {} export class SavedObjectsService implements CoreService { - private migrator: KibanaMigrator | undefined; private logger: Logger; - private clientProvider: ISavedObjectsClientProvider | undefined; + + private setupDeps?: SavedObjectsSetupDeps; + private clientFactoryProvider?: SavedObjectsClientFactoryProvider; + private clientFactoryWrappers: WrappedClientFactoryWrapper[] = []; + + private mappings: SavedObjectsMapping[] = []; + private migrations: MigrationDefinition = {}; + private schemas: SavedObjectsSchemaDefinition = {}; + private validations: PropertyValidators = {}; constructor(private readonly coreContext: CoreContext) { this.logger = coreContext.logger.get('savedobjects-service'); } - public async setup( - setupDeps: SavedObjectsSetupDeps, - migrationsRetryDelay?: number - ): Promise { + public async setup(setupDeps: SavedObjectsSetupDeps): Promise { this.logger.debug('Setting up SavedObjects service'); + this.setupDeps = setupDeps; + const { savedObjectSchemas: savedObjectsSchemasDefinition, savedObjectMappings, savedObjectMigrations, savedObjectValidations, } = setupDeps.legacyPlugins.uiExports; + this.mappings = savedObjectMappings; + this.migrations = savedObjectMigrations; + this.schemas = savedObjectsSchemasDefinition; + this.validations = savedObjectValidations; - const savedObjectSchemas = new SavedObjectsSchema(savedObjectsSchemasDefinition); + return { + setClientFactoryProvider: provider => { + if (this.clientFactoryProvider) { + throw new Error('custom client factory is already set, and can only be set once'); + } + this.clientFactoryProvider = provider; + }, + addClientWrapper: (priority, id, factory) => { + this.clientFactoryWrappers.push({ + priority, + id, + factory, + }); + }, + }; + } + + public async start( + core: SavedObjectsStartDeps, + migrationsRetryDelay?: number + ): Promise { + if (!this.setupDeps) { + throw new Error('#setup() needs to be run first'); + } + + this.logger.debug('Starting SavedObjects service'); const kibanaConfig = await this.coreContext.configService .atPath('kibana') .pipe(first()) .toPromise(); - const savedObjectsConfig = await this.coreContext.configService .atPath('migrations') .pipe(first()) .toPromise(); + const adminClient = this.setupDeps!.elasticsearch.adminClient; + const migrator = this.createMigrator(kibanaConfig, savedObjectsConfig, migrationsRetryDelay); - const adminClient = setupDeps.elasticsearch.adminClient; + /** + * Note: We want to ensure that migrations have completed before + * continuing with further Core start steps that might use SavedObjects + * such as running the legacy server, legacy plugins and allowing incoming + * HTTP requests. + * + * However, our build system optimize step and some tests depend on the + * HTTP server running without an Elasticsearch server being available. + * So, when the `migrations.skip` is true, we skip migrations altogether. + */ + const cliArgs = this.coreContext.env.cliArgs; + const skipMigrations = cliArgs.optimize || savedObjectsConfig.skip; - const migrator = (this.migrator = new KibanaMigrator({ - savedObjectSchemas, - savedObjectMappings, - savedObjectMigrations, - savedObjectValidations, - logger: this.coreContext.logger.get('migrations'), - kibanaVersion: this.coreContext.env.packageInfo.version, - config: setupDeps.legacyPlugins.pluginExtendedConfig, - savedObjectsConfig, - kibanaConfig, - callCluster: migrationsRetryCallCluster( - adminClient.callAsInternalUser, - this.coreContext.logger.get('migrations'), - migrationsRetryDelay - ), - })); + this.logger.debug('Starting saved objects migration'); + await migrator.runMigrations(skipMigrations); + this.logger.debug('Saved objects migration completed'); - const createSORepository = (callCluster: APICaller, extraTypes: string[] = []) => { + const createRepository = (callCluster: APICaller, extraTypes: string[] = []) => { return SavedObjectsRepository.createRepository( migrator, - savedObjectSchemas, - setupDeps.legacyPlugins.pluginExtendedConfig, + new SavedObjectsSchema(this.schemas), + this.setupDeps!.legacyPlugins.pluginExtendedConfig, kibanaConfig.index, callCluster, extraTypes ); }; - this.clientProvider = new SavedObjectsClientProvider({ + const repositoryFactory: SavedObjectsRepositoryFactory = { + createInternalRepository: (extraTypes?: string[]) => + createRepository(adminClient.callAsInternalUser, extraTypes), + createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => + createRepository(adminClient.asScoped(req).callAsCurrentUser, extraTypes), + }; + + const clientProvider = new SavedObjectsClientProvider({ defaultClientFactory({ request }) { - const repository = createSORepository(adminClient.asScoped(request).callAsCurrentUser); + const repository = repositoryFactory.createScopedRepository(request); return new SavedObjectsClient(repository); }, }); + if (this.clientFactoryProvider) { + const clientFactory = this.clientFactoryProvider(repositoryFactory); + clientProvider.setClientFactory(clientFactory); + } + this.clientFactoryWrappers.forEach(({ id, factory, priority }) => { + clientProvider.addClientWrapperFactory(priority, id, factory); + }); return { - getScopedClient: this.clientProvider.getClient.bind(this.clientProvider), - setClientFactory: this.clientProvider.setClientFactory.bind(this.clientProvider), - addClientWrapper: this.clientProvider.addClientWrapperFactory.bind(this.clientProvider), - createInternalRepository: (extraTypes?: string[]) => - createSORepository(adminClient.callAsInternalUser, extraTypes), - createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => - createSORepository(adminClient.asScoped(req).callAsCurrentUser, extraTypes), + migrator, + clientProvider, + getScopedClient: clientProvider.getClient.bind(clientProvider), + createScopedRepository: repositoryFactory.createScopedRepository, + createInternalRepository: repositoryFactory.createInternalRepository, }; } - public async start(core: SavedObjectsStartDeps): Promise { - if (!this.clientProvider) { - throw new Error('#setup() needs to be run first'); - } - - this.logger.debug('Starting SavedObjects service'); + public async stop() {} - /** - * Note: We want to ensure that migrations have completed before - * continuing with further Core startup steps that might use SavedObjects - * such as running the legacy server, legacy plugins and allowing incoming - * HTTP requests. - * - * However, our build system optimize step and some tests depend on the - * HTTP server running without an Elasticsearch server being available. - * So, when the `migrations.skip` is true, we skip migrations altogether. - */ - const cliArgs = this.coreContext.env.cliArgs; - const savedObjectsConfig = await this.coreContext.configService - .atPath('migrations') - .pipe(first()) - .toPromise(); - const skipMigrations = cliArgs.optimize || savedObjectsConfig.skip; - await this.migrator!.runMigrations(skipMigrations); + private createMigrator( + kibanaConfig: KibanaConfigType, + savedObjectsConfig: SavedObjectsConfigType, + migrationsRetryDelay?: number + ): KibanaMigrator { + const savedObjectSchemas = new SavedObjectsSchema(this.schemas); + const adminClient = this.setupDeps!.elasticsearch.adminClient; - return { - migrator: this.migrator!, - clientProvider: this.clientProvider, - getScopedClient: this.clientProvider.getClient.bind(this.clientProvider), - }; + return new KibanaMigrator({ + savedObjectSchemas, + savedObjectMappings: this.mappings, + savedObjectMigrations: this.migrations, + savedObjectValidations: this.validations, + logger: this.coreContext.logger.get('migrations'), + kibanaVersion: this.coreContext.env.packageInfo.version, + config: this.setupDeps!.legacyPlugins.pluginExtendedConfig, + savedObjectsConfig, + kibanaConfig, + callCluster: migrationsRetryCallCluster( + adminClient.callAsInternalUser, + this.coreContext.logger.get('migrations'), + migrationsRetryDelay + ), + }); } - - public async stop() {} } diff --git a/src/core/server/saved_objects/service/index.ts b/src/core/server/saved_objects/service/index.ts index f50ee1759dad7c..9f625b4732e264 100644 --- a/src/core/server/saved_objects/service/index.ts +++ b/src/core/server/saved_objects/service/index.ts @@ -29,13 +29,11 @@ import { SavedObjectsResolveImportErrorsOptions } from '../import/types'; * @internal * @deprecated */ -export interface SavedObjectsLegacyService { +export interface SavedObjectsLegacyService { // ATTENTION: these types are incomplete - addScopedSavedObjectsClientWrapperFactory: SavedObjectsClientProvider< - Request - >['addClientWrapperFactory']; - setScopedSavedObjectsClientFactory: SavedObjectsClientProvider['setClientFactory']; - getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient']; + addScopedSavedObjectsClientWrapperFactory: SavedObjectsClientProvider['addClientWrapperFactory']; + setScopedSavedObjectsClientFactory: SavedObjectsClientProvider['setClientFactory']; + getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient']; SavedObjectsClient: typeof SavedObjectsClient; types: string[]; schema: SavedObjectsSchema; @@ -59,6 +57,7 @@ export { SavedObjectsClientWrapperOptions, SavedObjectsErrorHelpers, SavedObjectsClientFactory, + SavedObjectsClientFactoryProvider, } from './lib'; export * from './saved_objects_client'; diff --git a/src/core/server/saved_objects/service/lib/index.ts b/src/core/server/saved_objects/service/lib/index.ts index c26128acc5050f..e103120388e354 100644 --- a/src/core/server/saved_objects/service/lib/index.ts +++ b/src/core/server/saved_objects/service/lib/index.ts @@ -26,6 +26,7 @@ export { SavedObjectsClientProvider, SavedObjectsClientProviderOptions, SavedObjectsClientFactory, + SavedObjectsClientFactoryProvider, } from './scoped_client_provider'; export { SavedObjectsErrorHelpers } from './errors'; diff --git a/src/core/server/saved_objects/service/lib/scoped_client_provider.ts b/src/core/server/saved_objects/service/lib/scoped_client_provider.ts index 42f75e25171264..8aadc4f57317c6 100644 --- a/src/core/server/saved_objects/service/lib/scoped_client_provider.ts +++ b/src/core/server/saved_objects/service/lib/scoped_client_provider.ts @@ -18,34 +18,44 @@ */ import { PriorityCollection } from './priority_collection'; import { SavedObjectsClientContract } from '../../types'; +import { SavedObjectsRepositoryFactory } from '../../saved_objects_service'; +import { KibanaRequest } from '../../../http'; /** * Options passed to each SavedObjectsClientWrapperFactory to aid in creating the wrapper instance. * @public */ -export interface SavedObjectsClientWrapperOptions { +export interface SavedObjectsClientWrapperOptions { client: SavedObjectsClientContract; - request: Request; + request: KibanaRequest; } /** * Describes the factory used to create instances of Saved Objects Client Wrappers. * @public */ -export type SavedObjectsClientWrapperFactory = ( - options: SavedObjectsClientWrapperOptions +export type SavedObjectsClientWrapperFactory = ( + options: SavedObjectsClientWrapperOptions ) => SavedObjectsClientContract; /** * Describes the factory used to create instances of the Saved Objects Client. * @public */ -export type SavedObjectsClientFactory = ({ +export type SavedObjectsClientFactory = ({ request, }: { - request: Request; + request: KibanaRequest; }) => SavedObjectsClientContract; +/** + * Provider to invoke to retrieve a {@link SavedObjectsClientFactory}. + * @public + */ +export type SavedObjectsClientFactoryProvider = ( + repositoryFactory: SavedObjectsRepositoryFactory +) => SavedObjectsClientFactory; + /** * Options to control the creation of the Saved Objects Client. * @public @@ -57,8 +67,8 @@ export interface SavedObjectsClientProviderOptions { /** * @internal */ -export type ISavedObjectsClientProvider = Pick< - SavedObjectsClientProvider, +export type ISavedObjectsClientProvider = Pick< + SavedObjectsClientProvider, keyof SavedObjectsClientProvider >; @@ -67,26 +77,22 @@ export type ISavedObjectsClientProvider = Pick< * * @internal */ -export class SavedObjectsClientProvider { +export class SavedObjectsClientProvider { private readonly _wrapperFactories = new PriorityCollection<{ id: string; - factory: SavedObjectsClientWrapperFactory; + factory: SavedObjectsClientWrapperFactory; }>(); - private _clientFactory: SavedObjectsClientFactory; - private readonly _originalClientFactory: SavedObjectsClientFactory; - - constructor({ - defaultClientFactory, - }: { - defaultClientFactory: SavedObjectsClientFactory; - }) { + private _clientFactory: SavedObjectsClientFactory; + private readonly _originalClientFactory: SavedObjectsClientFactory; + + constructor({ defaultClientFactory }: { defaultClientFactory: SavedObjectsClientFactory }) { this._originalClientFactory = this._clientFactory = defaultClientFactory; } addClientWrapperFactory( priority: number, id: string, - factory: SavedObjectsClientWrapperFactory + factory: SavedObjectsClientWrapperFactory ): void { if (this._wrapperFactories.has(entry => entry.id === id)) { throw new Error(`wrapper factory with id ${id} is already defined`); @@ -95,7 +101,7 @@ export class SavedObjectsClientProvider { this._wrapperFactories.add(priority, { id, factory }); } - setClientFactory(customClientFactory: SavedObjectsClientFactory) { + setClientFactory(customClientFactory: SavedObjectsClientFactory) { if (this._clientFactory !== this._originalClientFactory) { throw new Error(`custom client factory is already set, unable to replace the current one`); } @@ -104,7 +110,7 @@ export class SavedObjectsClientProvider { } getClient( - request: Request, + request: KibanaRequest, options: SavedObjectsClientProviderOptions = {} ): SavedObjectsClientContract { const client = this._clientFactory({ diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index dfce4a4c8ab189..a3fe2b937635bf 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -33,6 +33,13 @@ export { SavedObjectsImportRetry, } from './import/types'; +import { SavedObjectAttributes } from '../../types'; +export { + SavedObjectAttributes, + SavedObjectAttribute, + SavedObjectAttributeSingle, +} from '../../types'; + /** * Information about the migrations that have been applied to this SavedObject. * When Kibana starts up, KibanaMigrator detects outdated documents and @@ -52,36 +59,6 @@ export interface SavedObjectsMigrationVersion { [pluginName: string]: string; } -/** - * Don't use this type, it's simply a helper type for {@link SavedObjectAttribute} - * - * @public - */ -export type SavedObjectAttributeSingle = - | string - | number - | boolean - | null - | undefined - | SavedObjectAttributes; - -/** - * Type definition for a Saved Object attribute value - * - * @public - */ -export type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttributeSingle[]; - -/** - * The data for a Saved Object is stored as an object in the `attributes` - * property. - * - * @public - */ -export interface SavedObjectAttributes { - [key: string]: SavedObjectAttribute; -} - /** * * @public diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 6e41a4aefba302..e4ea06769007a1 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -706,9 +706,9 @@ export interface FakeRequest { export type GetAuthHeaders = (request: KibanaRequest | LegacyRequest) => AuthHeaders | undefined; // @public -export type GetAuthState = (request: KibanaRequest | LegacyRequest) => { +export type GetAuthState = (request: KibanaRequest | LegacyRequest) => { status: AuthStatus; - state: unknown; + state: T; }; // @public @@ -738,6 +738,11 @@ export type HttpResponsePayload = undefined | string | Record | Buf // @public export interface HttpServiceSetup { + // (undocumented) + auth: { + get: GetAuthState; + isAuthenticated: IsAuthenticated; + }; basePath: IBasePath; createCookieSessionStorageFactory: (cookieOptions: SessionStorageCookieOptions) => Promise>; createRouter: () => IRouter; @@ -802,8 +807,6 @@ export interface IKibanaSocket { getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate | null; } -// Warning: (ae-missing-release-tag) "ImageValidation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface ImageValidation { // (undocumented) @@ -879,11 +882,13 @@ export class KibanaRequest(req: Request, routeSchemas?: RouteValidator | RouteValidatorFullConfig, withoutSecretHeaders?: boolean): KibanaRequest; readonly headers: Headers; + readonly isSystemRequest: boolean; // (undocumented) readonly params: Params; // (undocumented) @@ -894,6 +899,11 @@ export class KibanaRequest; +} + // @public export interface KibanaRequestRoute { // (undocumented) @@ -1491,10 +1501,13 @@ export class SavedObjectsClient { export type SavedObjectsClientContract = Pick; // @public -export type SavedObjectsClientFactory = ({ request, }: { - request: Request; +export type SavedObjectsClientFactory = ({ request, }: { + request: KibanaRequest; }) => SavedObjectsClientContract; +// @public +export type SavedObjectsClientFactoryProvider = (repositoryFactory: SavedObjectsRepositoryFactory) => SavedObjectsClientFactory; + // @public export interface SavedObjectsClientProviderOptions { // (undocumented) @@ -1502,14 +1515,14 @@ export interface SavedObjectsClientProviderOptions { } // @public -export type SavedObjectsClientWrapperFactory = (options: SavedObjectsClientWrapperOptions) => SavedObjectsClientContract; +export type SavedObjectsClientWrapperFactory = (options: SavedObjectsClientWrapperOptions) => SavedObjectsClientContract; // @public -export interface SavedObjectsClientWrapperOptions { +export interface SavedObjectsClientWrapperOptions { // (undocumented) client: SavedObjectsClientContract; // (undocumented) - request: Request; + request: KibanaRequest; } // @public (undocumented) @@ -1745,15 +1758,15 @@ export interface SavedObjectsIncrementCounterOptions extends SavedObjectsBaseOpt } // @internal @deprecated (undocumented) -export interface SavedObjectsLegacyService { +export interface SavedObjectsLegacyService { // Warning: (ae-forgotten-export) The symbol "SavedObjectsClientProvider" needs to be exported by the entry point index.d.ts // // (undocumented) - addScopedSavedObjectsClientWrapperFactory: SavedObjectsClientProvider['addClientWrapperFactory']; + addScopedSavedObjectsClientWrapperFactory: SavedObjectsClientProvider['addClientWrapperFactory']; // (undocumented) getSavedObjectsRepository(...rest: any[]): any; // (undocumented) - getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient']; + getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient']; // (undocumented) importExport: { objectLimit: number; @@ -1766,7 +1779,7 @@ export interface SavedObjectsLegacyService { // (undocumented) schema: SavedObjectsSchema; // (undocumented) - setScopedSavedObjectsClientFactory: SavedObjectsClientProvider['setClientFactory']; + setScopedSavedObjectsClientFactory: SavedObjectsClientProvider['setClientFactory']; // (undocumented) types: string[]; } @@ -1829,6 +1842,12 @@ export class SavedObjectsRepository { update(type: string, id: string, attributes: Partial, options?: SavedObjectsUpdateOptions): Promise>; } +// @public +export interface SavedObjectsRepositoryFactory { + createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; + createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; +} + // @public export interface SavedObjectsResolveImportErrorsOptions { // (undocumented) @@ -1871,14 +1890,14 @@ export class SavedObjectsSerializer { // @public export interface SavedObjectsServiceSetup { - addClientWrapper: (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void; - createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; - createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; - setClientFactory: (customClientFactory: SavedObjectsClientFactory) => void; + addClientWrapper: (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void; + setClientFactoryProvider: (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void; } // @public export interface SavedObjectsServiceStart { + createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; + createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; getScopedClient: (req: KibanaRequest, options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; } @@ -1941,10 +1960,19 @@ export type SharedGlobalConfig = RecursiveReadonly_2<{ path: Pick; }>; -// Warning: (ae-missing-release-tag) "StringValidation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface StringValidation { +// @public +export type StringValidation = StringValidationRegex | StringValidationRegexString; + +// @public +export interface StringValidationRegex { + // (undocumented) + message: string; + // (undocumented) + regex: RegExp; +} + +// @public +export interface StringValidationRegexString { // (undocumented) message: string; // (undocumented) @@ -1978,7 +2006,7 @@ export interface UiSettingsServiceStart { } // @public -export type UiSettingsType = 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string'; +export type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string' | 'array' | 'image'; // @public export interface UserProvidedValues { diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 89a5bdc4802fd9..96adb3bbcd2104 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -47,7 +47,7 @@ import { config as uiSettingsConfig } from './ui_settings'; import { mapToObject } from '../utils'; import { ContextService } from './context'; import { RequestHandlerContext } from '.'; -import { InternalCoreSetup } from './internal_types'; +import { InternalCoreSetup, InternalCoreStart } from './internal_types'; import { CapabilitiesService } from './capabilities'; import { UuidService } from './uuid'; @@ -68,6 +68,8 @@ export class Server { private readonly uiSettings: UiSettingsService; private readonly uuid: UuidService; + private coreStart?: InternalCoreStart; + constructor( rawConfigProvider: RawConfigurationProvider, public readonly env: Env, @@ -174,21 +176,24 @@ export class Server { uiSettings: uiSettingsStart, }); - const coreStart = { + this.coreStart = { capabilities: capabilitiesStart, savedObjects: savedObjectsStart, uiSettings: uiSettingsStart, - plugins: pluginsStart, }; + await this.legacy.start({ - core: coreStart, + core: { + ...this.coreStart, + plugins: pluginsStart, + }, plugins: mapToObject(pluginsStart.contracts), }); await this.http.start(); await this.rendering.start(); - return coreStart; + return this.coreStart; } public async stop() { @@ -215,7 +220,7 @@ export class Server { coreId, 'core', async (context, req, res): Promise => { - const savedObjectsClient = coreSetup.savedObjects.getScopedClient(req); + const savedObjectsClient = this.coreStart!.savedObjects.getScopedClient(req); const uiSettingsClient = coreSetup.uiSettings.asScopedToClient(savedObjectsClient); return { diff --git a/src/core/server/ui_settings/create_or_upgrade_saved_config/integration_tests/create_or_upgrade.test.ts b/src/core/server/ui_settings/create_or_upgrade_saved_config/integration_tests/create_or_upgrade.test.ts index f7dbf992e87286..218de8e7acb3ae 100644 --- a/src/core/server/ui_settings/create_or_upgrade_saved_config/integration_tests/create_or_upgrade.test.ts +++ b/src/core/server/ui_settings/create_or_upgrade_saved_config/integration_tests/create_or_upgrade.test.ts @@ -27,6 +27,7 @@ import { } from '../../../../../test_utils/kbn_server'; import { createOrUpgradeSavedConfig } from '../create_or_upgrade_saved_config'; import { loggingServiceMock } from '../../../logging/logging_service.mock'; +import { httpServerMock } from '../../../http/http_server.mocks'; const logger = loggingServiceMock.create().get(); describe('createOrUpgradeSavedConfig()', () => { @@ -48,7 +49,9 @@ describe('createOrUpgradeSavedConfig()', () => { kbnServer = kbn.kbnServer; const savedObjects = kbnServer.server.savedObjects; - savedObjectsClient = savedObjects.getScopedSavedObjectsClient({}); + savedObjectsClient = savedObjects.getScopedSavedObjectsClient( + httpServerMock.createKibanaRequest() + ); await savedObjectsClient.bulkCreate([ { diff --git a/src/core/server/ui_settings/index.ts b/src/core/server/ui_settings/index.ts index 39eb0046010b38..ddb66df3ffcbe1 100644 --- a/src/core/server/ui_settings/index.ts +++ b/src/core/server/ui_settings/index.ts @@ -34,4 +34,6 @@ export { ImageValidation, DeprecationSettings, StringValidation, + StringValidationRegex, + StringValidationRegexString, } from './types'; diff --git a/src/core/server/ui_settings/integration_tests/lib/servers.ts b/src/core/server/ui_settings/integration_tests/lib/servers.ts index 1abe6dc2d06838..57448541d68c58 100644 --- a/src/core/server/ui_settings/integration_tests/lib/servers.ts +++ b/src/core/server/ui_settings/integration_tests/lib/servers.ts @@ -26,6 +26,7 @@ import { TestUtils, } from '../../../../../test_utils/kbn_server'; import { APICaller } from '../../../elasticsearch/'; +import { httpServerMock } from '../../../http/http_server.mocks'; let servers: TestUtils; let esServer: TestElasticsearchUtils; @@ -83,7 +84,9 @@ export function getServices() { const callCluster = esServer.es.getCallCluster(); const savedObjects = kbnServer.server.savedObjects; - const savedObjectsClient = savedObjects.getScopedSavedObjectsClient({}); + const savedObjectsClient = savedObjects.getScopedSavedObjectsClient( + httpServerMock.createKibanaRequest() + ); const uiSettings = kbnServer.server.uiSettingsServiceFactory({ savedObjectsClient, diff --git a/src/core/server/ui_settings/types.ts b/src/core/server/ui_settings/types.ts index a74a31bbbd671a..f3eb1f5a6859cc 100644 --- a/src/core/server/ui_settings/types.ts +++ b/src/core/server/ui_settings/types.ts @@ -16,7 +16,19 @@ * specific language governing permissions and limitations * under the License. */ -import { SavedObjectsClientContract, SavedObjectAttribute } from '../saved_objects/types'; +import { SavedObjectsClientContract } from '../saved_objects/types'; +import { UiSettingsParams, UserProvidedValues } from '../../types'; +export { + UiSettingsParams, + StringValidationRegexString, + StringValidationRegex, + StringValidation, + DeprecationSettings, + ImageValidation, + UiSettingsType, + UserProvidedValues, +} from '../../types'; + /** * Server-side client that provides access to the advanced settings stored in elasticsearch. * The settings provide control over the behavior of the Kibana application. @@ -64,76 +76,6 @@ export interface IUiSettingsClient { isOverridden: (key: string) => boolean; } -/** - * Describes the values explicitly set by user. - * @public - * */ -export interface UserProvidedValues { - userValue?: T; - isOverridden?: boolean; -} - -/** - * UiSettings deprecation field options. - * @public - * */ -export interface DeprecationSettings { - /** Deprecation message */ - message: string; - /** Key to documentation links */ - docLinksKey: string; -} - -/** - * UI element type to represent the settings. - * @public - * */ -export type UiSettingsType = 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string'; - -/** - * UiSettings parameters defined by the plugins. - * @public - * */ -export interface UiSettingsParams { - /** title in the UI */ - name?: string; - /** default value to fall back to if a user doesn't provide any */ - value?: SavedObjectAttribute; - /** description provided to a user in UI */ - description?: string; - /** used to group the configured setting in the UI */ - category?: string[]; - /** array of permitted values for this setting */ - options?: string[]; - /** text labels for 'select' type UI element */ - optionLabels?: Record; - /** a flag indicating whether new value applying requires page reloading */ - requiresPageReload?: boolean; - /** a flag indicating that value cannot be changed */ - readonly?: boolean; - /** defines a type of UI element {@link UiSettingsType} */ - type?: UiSettingsType; - /** optional deprecation information. Used to generate a deprecation warning. */ - deprecation?: DeprecationSettings; - /* - * Allows defining a custom validation applicable to value change on the client. - * @deprecated - */ - validation?: ImageValidation | StringValidation; -} - -export interface StringValidation { - regexString: string; - message: string; -} - -export interface ImageValidation { - maxSize: { - length: number; - description: string; - }; -} - /** @internal */ export interface InternalUiSettingsServiceSetup { /** diff --git a/src/core/types/app_category.ts b/src/core/types/app_category.ts new file mode 100644 index 00000000000000..83a3693f009b6c --- /dev/null +++ b/src/core/types/app_category.ts @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** @public */ + +/** + * A category definition for nav links to know where to sort them in the left hand nav + * @public + */ +export interface AppCategory { + /** + * Label used for cateogry name. + * Also used as aria-label if one isn't set. + */ + label: string; + + /** + * If the visual label isn't appropriate for screen readers, + * can override it here + */ + ariaLabel?: string; + + /** + * The order that categories will be sorted in + * Prefer large steps between categories to allow for further editing + * (Default categories are in steps of 1000) + */ + order?: number; + + /** + * Define an icon to be used for the category + * If the category is only 1 item, and no icon is defined, will default to the product icon + * Defaults to initials if no icon is defined + */ + euiIconType?: string; +} diff --git a/src/core/types/index.ts b/src/core/types/index.ts index d01b514c770a77..346b4cfce70c1a 100644 --- a/src/core/types/index.ts +++ b/src/core/types/index.ts @@ -23,3 +23,6 @@ */ export * from './core_service'; export * from './capabilities'; +export * from './app_category'; +export * from './ui_settings'; +export * from './saved_objects'; diff --git a/src/core/types/saved_objects.ts b/src/core/types/saved_objects.ts new file mode 100644 index 00000000000000..73eb2db11d62fb --- /dev/null +++ b/src/core/types/saved_objects.ts @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Don't use this type, it's simply a helper type for {@link SavedObjectAttribute} + * + * @public + */ +export type SavedObjectAttributeSingle = + | string + | number + | boolean + | null + | undefined + | SavedObjectAttributes; + +/** + * Type definition for a Saved Object attribute value + * + * @public + */ +export type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttributeSingle[]; + +/** + * The data for a Saved Object is stored as an object in the `attributes` + * property. + * + * @public + */ +export interface SavedObjectAttributes { + [key: string]: SavedObjectAttribute; +} diff --git a/src/core/types/ui_settings.ts b/src/core/types/ui_settings.ts new file mode 100644 index 00000000000000..eccd3f9616af07 --- /dev/null +++ b/src/core/types/ui_settings.ts @@ -0,0 +1,121 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObjectAttribute } from './saved_objects'; + +/** + * UI element type to represent the settings. + * @public + * */ +export type UiSettingsType = + | 'undefined' // I don't know why malformed UiSettings objects exist + | 'json' + | 'markdown' + | 'number' + | 'select' + | 'boolean' + | 'string' + | 'array' + | 'image'; + +/** + * UiSettings deprecation field options. + * @public + * */ +export interface DeprecationSettings { + /** Deprecation message */ + message: string; + /** Key to documentation links */ + docLinksKey: string; +} + +/** + * UiSettings parameters defined by the plugins. + * @public + * */ +export interface UiSettingsParams { + /** title in the UI */ + name?: string; + /** default value to fall back to if a user doesn't provide any */ + value?: SavedObjectAttribute; + /** description provided to a user in UI */ + description?: string; + /** used to group the configured setting in the UI */ + category?: string[]; + /** array of permitted values for this setting */ + options?: string[]; + /** text labels for 'select' type UI element */ + optionLabels?: Record; + /** a flag indicating whether new value applying requires page reloading */ + requiresPageReload?: boolean; + /** a flag indicating that value cannot be changed */ + readonly?: boolean; + /** defines a type of UI element {@link UiSettingsType} */ + type?: UiSettingsType; + /** optional deprecation information. Used to generate a deprecation warning. */ + deprecation?: DeprecationSettings; + /* + * Allows defining a custom validation applicable to value change on the client. + * @deprecated + */ + validation?: ImageValidation | StringValidation; +} + +/** + * Allows regex objects or a regex string + * @public + * */ +export type StringValidation = StringValidationRegex | StringValidationRegexString; + +/** + * StringValidation with regex object + * @public + * */ +export interface StringValidationRegex { + regex: RegExp; + message: string; +} + +/** + * StringValidation as regex string + * @public + * */ +export interface StringValidationRegexString { + regexString: string; + message: string; +} + +/** + * @public + * */ +export interface ImageValidation { + maxSize: { + length: number; + description: string; + }; +} + +/** + * Describes the values explicitly set by user. + * @public + * */ +export interface UserProvidedValues { + userValue?: T; + isOverridden?: boolean; +} diff --git a/src/core/utils/default_app_categories.ts b/src/core/utils/default_app_categories.ts new file mode 100644 index 00000000000000..3e3cc2fef2a229 --- /dev/null +++ b/src/core/utils/default_app_categories.ts @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +/** @internal */ +export const DEFAULT_APP_CATEGORIES = Object.freeze({ + analyze: { + label: i18n.translate('core.ui.analyzeNavList.label', { + defaultMessage: 'Analyze', + }), + order: 1000, + }, + observability: { + label: i18n.translate('core.ui.observabilityNavList.label', { + defaultMessage: 'Observability', + }), + order: 2000, + }, + security: { + label: i18n.translate('core.ui.securityNavList.label', { + defaultMessage: 'Security', + }), + order: 3000, + }, + management: { + label: i18n.translate('core.ui.managementNavList.label', { + defaultMessage: 'Management', + }), + euiIconType: 'managementApp', + }, +}); diff --git a/src/legacy/utils/get_flattened_object.test.ts b/src/core/utils/get_flattened_object.test.ts similarity index 100% rename from src/legacy/utils/get_flattened_object.test.ts rename to src/core/utils/get_flattened_object.test.ts diff --git a/src/legacy/utils/get_flattened_object.ts b/src/core/utils/get_flattened_object.ts similarity index 100% rename from src/legacy/utils/get_flattened_object.ts rename to src/core/utils/get_flattened_object.ts diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts index 7c8ed481c0a7d0..e35356343cfe24 100644 --- a/src/core/utils/index.ts +++ b/src/core/utils/index.ts @@ -28,3 +28,5 @@ export * from './pick'; export * from './promise'; export * from './url'; export * from './unset'; +export * from './get_flattened_object'; +export * from './default_app_categories'; diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker index 31a5a4c13a4be2..7a82ca0b1609c0 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker @@ -59,7 +59,6 @@ kibana_vars=( path.data pid.file regionmap - regionmap.includeElasticMapsService server.basePath server.customResponseHeaders server.defaultRoute @@ -94,6 +93,7 @@ kibana_vars=( timelion.enabled vega.enableExternalUrls xpack.apm.enabled + xpack.apm.serviceMapEnabled xpack.apm.ui.enabled xpack.apm.ui.maxTraceItems apm_oss.apmAgentConfigurationIndex diff --git a/src/dev/build/tasks/os_packages/docker_generator/run.js b/src/dev/build/tasks/os_packages/docker_generator/run.js index 7424b6f01b82b4..b6dab43887f14b 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/run.js +++ b/src/dev/build/tasks/os_packages/docker_generator/run.js @@ -42,6 +42,7 @@ export async function runDockerGenerator(config, log, build, ubi = false) { const versionTag = config.getBuildVersion(); const artifactTarball = `kibana${imageFlavor}-${versionTag}-linux-x86_64.tar.gz`; const artifactsDir = config.resolveFromTarget('.'); + const dockerBuildDate = new Date().toISOString(); // That would produce oss, default and default-ubi7 const dockerBuildDir = config.resolveFromRepo( 'build', @@ -62,6 +63,7 @@ export async function runDockerGenerator(config, log, build, ubi = false) { dockerOutputDir, baseOSImage, ubiImageFlavor, + dockerBuildDate, }; // Verify if we have the needed kibana target in order diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.js b/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.js index 25ae71856c12d0..6ad34c439a233c 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.js +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.js @@ -26,6 +26,7 @@ function generator({ usePublicArtifact, baseOSImage, ubiImageFlavor, + dockerBuildDate, }) { const copyArtifactTarballInsideDockerOptFolder = () => { if (usePublicArtifact) { @@ -115,6 +116,8 @@ function generator({ org.label-schema.url="https://www.elastic.co/products/kibana" \\ org.label-schema.vcs-url="https://github.com/elastic/kibana" \\ org.label-schema.license="${license}" \\ + org.label-schema.usage="https://www.elastic.co/guide/en/kibana/index.html" \\ + org.label-schema.build-date="${dockerBuildDate}" \\ license="${license}" ENTRYPOINT ["/usr/local/bin/dumb-init", "--"] diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index e5493df0aecf70..78fc041345577e 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -55,6 +55,9 @@ export const IGNORE_FILE_GLOBS = [ // filename is required by storybook 'packages/kbn-storybook/storybook_config/preview-head.html', + + // filename required by api-extractor + 'api-documenter.json', ]; /** diff --git a/src/dev/run_check_core_api_changes.ts b/src/dev/run_check_core_api_changes.ts index 56664477df4915..48f31c261c4456 100644 --- a/src/dev/run_check_core_api_changes.ts +++ b/src/dev/run_check_core_api_changes.ts @@ -83,7 +83,7 @@ const runBuildTypes = async () => { const runApiDocumenter = async (folder: string) => { await execa( 'api-documenter', - ['markdown', '-i', `./build/${folder}`, '-o', `./docs/development/core/${folder}`], + ['generate', '-i', `./build/${folder}`, '-o', `./docs/development/core/${folder}`], { preferLocal: true, } diff --git a/src/dev/run_check_lockfile_symlinks.js b/src/dev/run_check_lockfile_symlinks.js new file mode 100644 index 00000000000000..c1ba22d3a7a44f --- /dev/null +++ b/src/dev/run_check_lockfile_symlinks.js @@ -0,0 +1,182 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { existsSync, lstatSync, readFileSync } from 'fs'; +import globby from 'globby'; +import { dirname } from 'path'; + +import { run, createFailError } from '@kbn/dev-utils'; + +import { REPO_ROOT } from './constants'; +import { File } from './file'; +import { matchesAnyGlob } from './globs'; + +const LOCKFILE_GLOBS = ['**/yarn.lock']; +const MANIFEST_GLOBS = ['**/package.json']; +const IGNORE_FILE_GLOBS = [ + // tests aren't used in production, ignore them + '**/test/**/*', + // fixtures aren't used in production, ignore them + '**/*fixtures*/**/*', + // cypress isn't used in production, ignore it + 'x-pack/legacy/plugins/apm/cypress/*', +]; + +run(async ({ log }) => { + const paths = await globby(LOCKFILE_GLOBS.concat(MANIFEST_GLOBS), { + cwd: REPO_ROOT, + nodir: true, + gitignore: true, + ignore: [ + // the gitignore: true option makes sure that we don't + // include files from node_modules in the result, but it still + // loads all of the files from node_modules before filtering + // so it's still super slow. This prevents loading the files + // and still relies on gitignore to to final ignores + '**/node_modules', + ], + }); + + const files = paths.map(path => new File(path)); + + await checkLockfileSymlinks(log, files); +}); + +async function checkLockfileSymlinks(log, files) { + const filtered = files.filter(file => !matchesAnyGlob(file.getRelativePath(), IGNORE_FILE_GLOBS)); + await checkOnlyLockfileAtProjectRoot(filtered); + await checkSuperfluousSymlinks(log, filtered); + await checkMissingSymlinks(log, filtered); +} + +async function checkOnlyLockfileAtProjectRoot(files) { + const errorPaths = []; + + files + .filter(file => matchesAnyGlob(file.getRelativePath(), LOCKFILE_GLOBS)) + .forEach(file => { + const path = file.getRelativePath(); + const parent = dirname(path); + const stats = lstatSync(path); + if (!stats.isSymbolicLink() && parent !== '.') { + errorPaths.push(path); + } + }); + + if (errorPaths.length) { + throw createFailError( + `These directories MUST NOT have a 'yarn.lock' file:\n${listPaths(errorPaths)}` + ); + } +} + +async function checkSuperfluousSymlinks(log, files) { + const errorPaths = []; + + files + .filter(file => matchesAnyGlob(file.getRelativePath(), LOCKFILE_GLOBS)) + .forEach(file => { + const path = file.getRelativePath(); + const parent = dirname(path); + const stats = lstatSync(path); + if (!stats.isSymbolicLink()) { + return; + } + + const manifestPath = `${parent}/package.json`; + if (!existsSync(manifestPath)) { + log.warning( + `No manifest found at '${manifestPath}', but found an adjacent 'yarn.lock' symlink.` + ); + errorPaths.push(path); + return; + } + + try { + const manifest = readFileSync(manifestPath); + try { + const json = JSON.parse(manifest); + if (!json.dependencies || !Object.keys(json.dependencies).length) { + log.warning( + `Manifest at '${manifestPath}' has an adjacent 'yarn.lock' symlink, but manifest has no dependencies.` + ); + errorPaths.push(path); + } + } catch (err) { + log.warning( + `Manifest at '${manifestPath}' has an adjacent 'yarn.lock' symlink, but could not parse manifest JSON (${err.message}).` + ); + errorPaths.push(path); + } + } catch (err) { + log.warning( + `Manifest at '${manifestPath}', has an adjacent 'yarn.lock' symlink, but could not read manifest (${err.message}).` + ); + errorPaths.push(path); + } + }); + + if (errorPaths.length) { + throw createFailError( + `These directories MUST NOT have a 'yarn.lock' symlink:\n${listPaths(errorPaths)}` + ); + } +} + +async function checkMissingSymlinks(log, files) { + const errorPaths = []; + + files + .filter(file => matchesAnyGlob(file.getRelativePath(), MANIFEST_GLOBS)) + .forEach(file => { + const path = file.getRelativePath(); + const parent = dirname(path); + const lockfilePath = `${parent}/yarn.lock`; + if (existsSync(lockfilePath)) { + return; + } + + try { + const manifest = readFileSync(path); + try { + const json = JSON.parse(manifest); + if (json.dependencies && Object.keys(json.dependencies).length) { + log.warning( + `Manifest at '${path}' has dependencies, but did not find an adjacent 'yarn.lock' symlink.` + ); + errorPaths.push(`${parent}/yarn.lock`); + } + } catch (err) { + log.warning(`Could not parse manifest JSON at '${path}' (${err.message}).`); + } + } catch (err) { + log.warning(`Could not read manifest at '${path}' (${err.message}).`); + } + }); + + if (errorPaths.length) { + throw createFailError( + `These directories MUST have a 'yarn.lock' symlink:\n${listPaths(errorPaths)}` + ); + } +} + +function listPaths(paths) { + return paths.map(path => ` - ${path}`).join('\n'); +} diff --git a/src/legacy/core_plugins/console_legacy/public/styles/_app.scss b/src/legacy/core_plugins/console_legacy/public/styles/_app.scss index c69440225236b0..3b6297f9cdbff7 100644 --- a/src/legacy/core_plugins/console_legacy/public/styles/_app.scss +++ b/src/legacy/core_plugins/console_legacy/public/styles/_app.scss @@ -71,6 +71,8 @@ .conApp__resizer { @include kbnResizer; + // Give the aria selection border priority when the divider is selected on IE11 and Chrome + z-index: $euiZLevel1; } // SASSTODO: This component seems to not be used anymore? diff --git a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts index 633b7e630700d2..c9c72a7be9a147 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts +++ b/src/legacy/core_plugins/data/public/filter/filter_manager/filter_state_manager.ts @@ -18,17 +18,12 @@ */ import _ from 'lodash'; +import { Subscription } from 'rxjs'; import { State } from 'ui/state_management/state'; import { FilterManager, esFilters } from '../../../../../../plugins/data/public'; +import { compareFilters, COMPARE_ALL_OPTIONS } from '../../../../../../plugins/data/public'; -import { - compareFilters, - COMPARE_ALL_OPTIONS, - // this whole file will soon be deprecated by new state management. - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../../../plugins/data/public/query/filter_manager/lib/compare_filters'; - -type GetAppStateFunc = () => State | undefined | null; +type GetAppStateFunc = () => { filters?: esFilters.Filter[]; save?: () => void } | undefined | null; /** * FilterStateManager is responsible for watching for filter changes @@ -36,10 +31,12 @@ type GetAppStateFunc = () => State | undefined | null; * back to the URL. **/ export class FilterStateManager { + private filterManagerUpdatesSubscription: Subscription; + filterManager: FilterManager; globalState: State; getAppState: GetAppStateFunc; - interval: NodeJS.Timeout | undefined; + interval: number | undefined; constructor(globalState: State, getAppState: GetAppStateFunc, filterManager: FilterManager) { this.getAppState = getAppState; @@ -48,7 +45,7 @@ export class FilterStateManager { this.watchFilterState(); - this.filterManager.getUpdates$().subscribe(() => { + this.filterManagerUpdatesSubscription = this.filterManager.getUpdates$().subscribe(() => { this.updateAppState(); }); } @@ -57,12 +54,13 @@ export class FilterStateManager { if (this.interval) { clearInterval(this.interval); } + this.filterManagerUpdatesSubscription.unsubscribe(); } private watchFilterState() { // This is a temporary solution to remove rootscope. // Moving forward, state should provide observable subscriptions. - this.interval = setInterval(() => { + this.interval = window.setInterval(() => { const appState = this.getAppState(); const stateUndefined = !appState || !this.globalState; if (stateUndefined) return; @@ -95,7 +93,7 @@ export class FilterStateManager { private saveState() { const appState = this.getAppState(); - if (appState) appState.save(); + if (appState && appState.save) appState.save(); this.globalState.save(); } diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts index 4514d67ea5fcd0..7fe487667f94e0 100644 --- a/src/legacy/core_plugins/data/public/index.ts +++ b/src/legacy/core_plugins/data/public/index.ts @@ -28,8 +28,6 @@ export function plugin() { /** @public types */ export { DataStart }; -export { EsQuerySortValue, FetchOptions, ISearchSource, SortDirection } from './search/types'; -export { SearchSourceFields } from './search/types'; export { SavedQueryAttributes, SavedQuery, diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 893e477b38583d..6bd85ef020f167 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -18,17 +18,27 @@ */ import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; -import { SearchService, SearchStart } from './search'; -import { DataPublicPluginStart } from '../../../../plugins/data/public'; +import { + DataPublicPluginStart, + addSearchStrategy, + defaultSearchStrategy, +} from '../../../../plugins/data/public'; +import { ExpressionsSetup } from '../../../../plugins/expressions/public'; import { - setFieldFormats, - setNotifications, setIndexPatterns, setQueryService, + setUiSettings, + setInjectedMetadata, + setFieldFormats, + setSearchService, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; +export interface DataPluginSetupDependencies { + expressions: ExpressionsSetup; +} + export interface DataPluginStartDependencies { data: DataPublicPluginStart; } @@ -38,9 +48,7 @@ export interface DataPluginStartDependencies { * * @public */ -export interface DataStart { - search: SearchStart; -} +export interface DataStart {} // eslint-disable-line @typescript-eslint/no-empty-interface /** * Data Plugin - public @@ -54,25 +62,24 @@ export interface DataStart { * or static code. */ -export class DataPlugin implements Plugin { - private readonly search = new SearchService(); +export class DataPlugin + implements Plugin { + public setup(core: CoreSetup) { + setInjectedMetadata(core.injectedMetadata); - public setup(core: CoreSetup) {} + // This is to be deprecated once we switch to the new search service fully + addSearchStrategy(defaultSearchStrategy); + } public start(core: CoreStart, { data }: DataPluginStartDependencies): DataStart { - // This is required for when Angular code uses Field and FieldList. - setFieldFormats(data.fieldFormats); + setUiSettings(core.uiSettings); setQueryService(data.query); setIndexPatterns(data.indexPatterns); setFieldFormats(data.fieldFormats); - setNotifications(core.notifications); + setSearchService(data.search); - return { - search: this.search.start(core), - }; + return {}; } - public stop() { - this.search.stop(); - } + public stop() {} } diff --git a/src/legacy/ui/public/inspector/build_tabular_inspector_data.ts b/src/legacy/core_plugins/data/public/search/expressions/build_tabular_inspector_data.ts similarity index 95% rename from src/legacy/ui/public/inspector/build_tabular_inspector_data.ts rename to src/legacy/core_plugins/data/public/search/expressions/build_tabular_inspector_data.ts index b09ed60e7186f9..6e6d2a15fa2ac8 100644 --- a/src/legacy/ui/public/inspector/build_tabular_inspector_data.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/build_tabular_inspector_data.ts @@ -19,8 +19,8 @@ import { set } from 'lodash'; // @ts-ignore -import { createFilter } from '../../../core_plugins/visualizations/public'; -import { FormattedData } from './adapters'; +import { createFilter } from '../../../../visualizations/public'; +import { FormattedData } from '../../../../../../plugins/inspector/public'; interface Column { id: string; diff --git a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts index 4ec4dbd7f88d69..143283152d1044 100644 --- a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts @@ -28,20 +28,16 @@ import { KibanaDatatableColumn, } from 'src/plugins/expressions/public'; import { + ISearchSource, + SearchSource, Query, TimeRange, esFilters, getTime, FilterManager, } from '../../../../../../plugins/data/public'; -import { - SearchSource, - ISearchSource, - getRequestInspectorStats, - getResponseInspectorStats, -} from '../../../../../ui/public/courier'; -import { buildTabularInspectorData } from '../../../../../ui/public/inspector/build_tabular_inspector_data'; +import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { calculateObjectHash } from '../../../../visualizations/public'; // @ts-ignore import { tabifyAggResponse } from '../../../../../ui/public/agg_response/tabify/tabify'; @@ -49,6 +45,7 @@ import { PersistedState } from '../../../../../ui/public/persisted_state'; import { Adapters } from '../../../../../../plugins/inspector/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { getQueryService, getIndexPatterns } from '../../../../../../plugins/data/public/services'; +import { getRequestInspectorStats, getResponseInspectorStats } from '../..'; export interface RequestHandlerParams { searchSource: ISearchSource; diff --git a/src/legacy/core_plugins/data/public/search/fetch/index.ts b/src/legacy/core_plugins/data/public/search/fetch/index.ts deleted file mode 100644 index 7b89dea1a110cf..00000000000000 --- a/src/legacy/core_plugins/data/public/search/fetch/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export * from './fetch_soon'; -export * from './get_search_params'; diff --git a/src/legacy/core_plugins/data/public/search/fetch/types.ts b/src/legacy/core_plugins/data/public/search/fetch/types.ts deleted file mode 100644 index 0887a1f84c7c8c..00000000000000 --- a/src/legacy/core_plugins/data/public/search/fetch/types.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IUiSettingsClient } from '../../../../../../core/public'; -import { SearchRequest, SearchResponse } from '../types'; - -export interface ApiCaller { - search: (searchRequest: SearchRequest) => ApiCallerResponse; - msearch: (searchRequest: SearchRequest) => ApiCallerResponse; -} - -export interface ApiCallerResponse extends Promise { - abort: () => void; -} - -export interface FetchOptions { - abortSignal?: AbortSignal; - searchStrategyId?: string; -} - -export interface FetchHandlers { - es: ApiCaller; - config: IUiSettingsClient; - esShardTimeout: number; -} diff --git a/src/legacy/core_plugins/data/public/search/index.ts b/src/legacy/core_plugins/data/public/search/index.ts index d930a472195147..e1c93ec0e3b1c4 100644 --- a/src/legacy/core_plugins/data/public/search/index.ts +++ b/src/legacy/core_plugins/data/public/search/index.ts @@ -17,6 +17,4 @@ * under the License. */ -export { SearchService, SearchSetup, SearchStart } from './search_service'; - export { getRequestInspectorStats, getResponseInspectorStats } from './utils'; diff --git a/src/legacy/core_plugins/data/public/search/search_service.ts b/src/legacy/core_plugins/data/public/search/search_service.ts deleted file mode 100644 index 85701187fb31d8..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_service.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Plugin, CoreSetup, CoreStart } from '../../../../../core/public'; -import { SearchSource } from './search_source'; -import { defaultSearchStrategy } from './search_strategy'; -import { SearchStrategyProvider } from './search_strategy/types'; - -export interface SearchSetup {} // eslint-disable-line @typescript-eslint/no-empty-interface - -export interface SearchStart { - defaultSearchStrategy: SearchStrategyProvider; - SearchSource: typeof SearchSource; -} - -/** - * The contract provided here is a new platform shim for ui/courier. - * - * Once it has been refactored to work with new platform services, - * it will move into the existing search service in src/plugins/data/public/search - */ -export class SearchService implements Plugin { - public setup(core: CoreSetup): SearchSetup { - return {}; - } - - public start(core: CoreStart): SearchStart { - return { - defaultSearchStrategy, - SearchSource, - }; - } - - public stop() {} -} diff --git a/src/legacy/core_plugins/data/public/search/search_source/index.ts b/src/legacy/core_plugins/data/public/search/search_source/index.ts deleted file mode 100644 index 72170adc2b1296..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_source/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export * from './search_source'; diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts deleted file mode 100644 index 6efcae4d4b88dc..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * @name SearchSource - * - * @description A promise-based stream of search results that can inherit from other search sources. - * - * Because filters/queries in Kibana have different levels of persistence and come from different - * places, it is important to keep track of where filters come from for when they are saved back to - * the savedObject store in the Kibana index. To do this, we create trees of searchSource objects - * that can have associated query parameters (index, query, filter, etc) which can also inherit from - * other searchSource objects. - * - * At query time, all of the searchSource objects that have subscribers are "flattened", at which - * point the query params from the searchSource are collected while traversing up the inheritance - * chain. At each link in the chain a decision about how to merge the query params is made until a - * single set of query parameters is created for each active searchSource (a searchSource with - * subscribers). - * - * That set of query parameters is then sent to elasticsearch. This is how the filter hierarchy - * works in Kibana. - * - * Visualize, starting from a new search: - * - * - the `savedVis.searchSource` is set as the `appSearchSource`. - * - The `savedVis.searchSource` would normally inherit from the `appSearchSource`, but now it is - * upgraded to inherit from the `rootSearchSource`. - * - Any interaction with the visualization will still apply filters to the `appSearchSource`, so - * they will be stored directly on the `savedVis.searchSource`. - * - Any interaction with the time filter will be written to the `rootSearchSource`, so those - * filters will not be saved by the `savedVis`. - * - When the `savedVis` is saved to elasticsearch, it takes with it all the filters that are - * defined on it directly, but none of the ones that it inherits from other places. - * - * Visualize, starting from an existing search: - * - * - The `savedVis` loads the `savedSearch` on which it is built. - * - The `savedVis.searchSource` is set to inherit from the `saveSearch.searchSource` and set as - * the `appSearchSource`. - * - The `savedSearch.searchSource`, is set to inherit from the `rootSearchSource`. - * - Then the `savedVis` is written to elasticsearch it will be flattened and only include the - * filters created in the visualize application and will reconnect the filters from the - * `savedSearch` at runtime to prevent losing the relationship - * - * Dashboard search sources: - * - * - Each panel in a dashboard has a search source. - * - The `savedDashboard` also has a searchsource, and it is set as the `appSearchSource`. - * - Each panel's search source inherits from the `appSearchSource`, meaning that they inherit from - * the dashboard search source. - * - When a filter is added to the search box, or via a visualization, it is written to the - * `appSearchSource`. - */ - -import _ from 'lodash'; -import { npSetup } from 'ui/new_platform'; -import chrome from 'ui/chrome'; -import { normalizeSortRequest } from './normalize_sort_request'; -import { fetchSoon } from '../fetch'; -import { fieldWildcardFilter } from '../../../../../../plugins/kibana_utils/public'; -import { getHighlightRequest, esFilters, esQuery } from '../../../../../../plugins/data/public'; -import { RequestFailure } from '../fetch/errors'; -import { filterDocvalueFields } from './filter_docvalue_fields'; -import { SearchSourceOptions, SearchSourceFields, SearchRequest } from './types'; -import { FetchOptions, ApiCaller } from '../fetch/types'; - -const esShardTimeout = npSetup.core.injectedMetadata.getInjectedVar('esShardTimeout') as number; -const config = npSetup.core.uiSettings; - -export type ISearchSource = Pick; - -export class SearchSource { - private id: string = _.uniqueId('data_source'); - private searchStrategyId?: string; - private parent?: SearchSource; - private requestStartHandlers: Array< - (searchSource: ISearchSource, options?: FetchOptions) => Promise - > = []; - private inheritOptions: SearchSourceOptions = {}; - public history: SearchRequest[] = []; - - constructor(private fields: SearchSourceFields = {}) {} - - /** *** - * PUBLIC API - *****/ - - setPreferredSearchStrategyId(searchStrategyId: string) { - this.searchStrategyId = searchStrategyId; - } - - setFields(newFields: SearchSourceFields) { - this.fields = newFields; - return this; - } - - setField(field: K, value: SearchSourceFields[K]) { - if (value == null) { - delete this.fields[field]; - } else { - this.fields[field] = value; - } - return this; - } - - getId() { - return this.id; - } - - getFields() { - return { ...this.fields }; - } - - /** - * Get fields from the fields - */ - getField(field: K, recurse = true): SearchSourceFields[K] { - if (!recurse || this.fields[field] !== void 0) { - return this.fields[field]; - } - const parent = this.getParent(); - return parent && parent.getField(field); - } - - /** - * Get the field from our own fields, don't traverse up the chain - */ - getOwnField(field: K): SearchSourceFields[K] { - return this.getField(field, false); - } - - create() { - return new SearchSource(); - } - - createCopy() { - const newSearchSource = new SearchSource(); - newSearchSource.setFields({ ...this.fields }); - // when serializing the internal fields we lose the internal classes used in the index - // pattern, so we have to set it again to workaround this behavior - newSearchSource.setField('index', this.getField('index')); - newSearchSource.setParent(this.getParent()); - return newSearchSource; - } - - createChild(options = {}) { - const childSearchSource = new SearchSource(); - childSearchSource.setParent(this, options); - return childSearchSource; - } - - /** - * Set a searchSource that this source should inherit from - * @param {SearchSource} parent - the parent searchSource - * @param {SearchSourceOptions} options - the inherit options - * @return {this} - chainable - */ - setParent(parent?: ISearchSource, options: SearchSourceOptions = {}) { - this.parent = parent as SearchSource; - this.inheritOptions = options; - return this; - } - - /** - * Get the parent of this SearchSource - * @return {undefined|searchSource} - */ - getParent() { - return this.parent; - } - - /** - * Fetch this source and reject the returned Promise on error - * - * @async - */ - async fetch(options: FetchOptions = {}) { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const es = $injector.get('es') as ApiCaller; - - await this.requestIsStarting(options); - - const searchRequest = await this.flatten(); - this.history = [searchRequest]; - - const response = await fetchSoon( - searchRequest, - { - ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), - ...options, - }, - { es, config, esShardTimeout } - ); - - if (response.error) { - throw new RequestFailure(null, response); - } - - return response; - } - - /** - * Add a handler that will be notified whenever requests start - * @param {Function} handler - * @return {undefined} - */ - onRequestStart( - handler: (searchSource: ISearchSource, options?: FetchOptions) => Promise - ) { - this.requestStartHandlers.push(handler); - } - - async getSearchRequestBody() { - const searchRequest = await this.flatten(); - return searchRequest.body; - } - - /** - * Completely destroy the SearchSource. - * @return {undefined} - */ - destroy() { - this.requestStartHandlers.length = 0; - } - - /** **** - * PRIVATE APIS - ******/ - - /** - * Called by requests of this search source when they are started - * @param {Courier.Request} request - * @param options - * @return {Promise} - */ - private requestIsStarting(options: FetchOptions = {}) { - const handlers = [...this.requestStartHandlers]; - // If callParentStartHandlers has been set to true, we also call all - // handlers of parent search sources. - if (this.inheritOptions.callParentStartHandlers) { - let searchSource = this.getParent(); - while (searchSource) { - handlers.push(...searchSource.requestStartHandlers); - searchSource = searchSource.getParent(); - } - } - - return Promise.all(handlers.map(fn => fn(this, options))); - } - - /** - * Used to merge properties into the data within ._flatten(). - * The data is passed in and modified by the function - * - * @param {object} data - the current merged data - * @param {*} val - the value at `key` - * @param {*} key - The key of `val` - * @return {undefined} - */ - private mergeProp( - data: SearchRequest, - val: SearchSourceFields[K], - key: K - ) { - val = typeof val === 'function' ? val(this) : val; - if (val == null || !key) return; - - const addToRoot = (rootKey: string, value: any) => { - data[rootKey] = value; - }; - - /** - * Add the key and val to the body of the request - */ - const addToBody = (bodyKey: string, value: any) => { - // ignore if we already have a value - if (data.body[bodyKey] == null) { - data.body[bodyKey] = value; - } - }; - - switch (key) { - case 'filter': - return addToRoot('filters', (data.filters || []).concat(val)); - case 'query': - return addToRoot(key, (data[key] || []).concat(val)); - case 'fields': - const fields = _.uniq((data[key] || []).concat(val)); - return addToRoot(key, fields); - case 'index': - case 'type': - case 'highlightAll': - return key && data[key] == null && addToRoot(key, val); - case 'searchAfter': - return addToBody('search_after', val); - case 'source': - return addToBody('_source', val); - case 'sort': - const sort = normalizeSortRequest(val, this.getField('index'), config.get('sort:options')); - return addToBody(key, sort); - default: - return addToBody(key, val); - } - } - - /** - * Walk the inheritance chain of a source and return its - * flat representation (taking into account merging rules) - * @returns {Promise} - * @resolved {Object|null} - the flat data of the SearchSource - */ - private mergeProps(root = this, searchRequest: SearchRequest = { body: {} }) { - Object.entries(this.fields).forEach(([key, value]) => { - this.mergeProp(searchRequest, value, key as keyof SearchSourceFields); - }); - if (this.parent) { - this.parent.mergeProps(root, searchRequest); - } - return searchRequest; - } - - private flatten() { - const searchRequest = this.mergeProps(); - - searchRequest.body = searchRequest.body || {}; - const { body, index, fields, query, filters, highlightAll } = searchRequest; - - const computedFields = index ? index.getComputedFields() : {}; - - body.stored_fields = computedFields.storedFields; - body.script_fields = body.script_fields || {}; - _.extend(body.script_fields, computedFields.scriptFields); - - const defaultDocValueFields = computedFields.docvalueFields - ? computedFields.docvalueFields - : []; - body.docvalue_fields = body.docvalue_fields || defaultDocValueFields; - - if (!body.hasOwnProperty('_source') && index) { - body._source = index.getSourceFiltering(); - } - - if (body._source) { - // exclude source fields for this index pattern specified by the user - const filter = fieldWildcardFilter(body._source.excludes, config.get('metaFields')); - body.docvalue_fields = body.docvalue_fields.filter((docvalueField: any) => - filter(docvalueField.field) - ); - } - - // if we only want to search for certain fields - if (fields) { - // filter out the docvalue_fields, and script_fields to only include those that we are concerned with - body.docvalue_fields = filterDocvalueFields(body.docvalue_fields, fields); - body.script_fields = _.pick(body.script_fields, fields); - - // request the remaining fields from both stored_fields and _source - const remainingFields = _.difference(fields, _.keys(body.script_fields)); - body.stored_fields = remainingFields; - _.set(body, '_source.includes', remainingFields); - } - - const esQueryConfigs = esQuery.getEsQueryConfig(config); - body.query = esQuery.buildEsQuery(index, query, filters, esQueryConfigs); - - if (highlightAll && body.query) { - body.highlight = getHighlightRequest(body.query, config.get('doc_table:highlight')); - delete searchRequest.highlightAll; - } - - const translateToQuery = (filter: esFilters.Filter) => filter && (filter.query || filter); - - // re-write filters within filter aggregations - (function recurse(aggBranch) { - if (!aggBranch) return; - Object.keys(aggBranch).forEach(function(id) { - const agg = aggBranch[id]; - - if (agg.filters) { - // translate filters aggregations - const { filters: aggFilters } = agg.filters; - Object.keys(aggFilters).forEach(filterId => { - aggFilters[filterId] = translateToQuery(aggFilters[filterId]); - }); - } - - recurse(agg.aggs || agg.aggregations); - }); - })(body.aggs || body.aggregations); - - return searchRequest; - } -} diff --git a/src/legacy/core_plugins/data/public/search/search_source/types.ts b/src/legacy/core_plugins/data/public/search/search_source/types.ts deleted file mode 100644 index 9c5b57519d75f9..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_source/types.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { NameList } from 'elasticsearch'; -import { esFilters, IndexPattern, Query } from '../../../../../../plugins/data/public'; - -export type EsQuerySearchAfter = [string | number, string | number]; - -export enum SortDirection { - asc = 'asc', - desc = 'desc', -} - -export type EsQuerySortValue = Record; - -export interface SearchSourceFields { - type?: string; - query?: Query; - filter?: - | esFilters.Filter[] - | esFilters.Filter - | (() => esFilters.Filter[] | esFilters.Filter | undefined); - sort?: EsQuerySortValue | EsQuerySortValue[]; - highlight?: any; - highlightAll?: boolean; - aggs?: any; - from?: number; - size?: number; - source?: NameList; - version?: boolean; - fields?: NameList; - index?: IndexPattern; - searchAfter?: EsQuerySearchAfter; - timeout?: string; - terminate_after?: number; -} - -export interface SearchSourceOptions { - callParentStartHandlers?: boolean; -} - -export { ISearchSource } from './search_source'; - -export interface SortOptions { - mode?: 'min' | 'max' | 'sum' | 'avg' | 'median'; - type?: 'double' | 'long' | 'date' | 'date_nanos'; - nested?: object; - unmapped_type?: string; - distance_type?: 'arc' | 'plane'; - unit?: string; - ignore_unmapped?: boolean; - _script?: object; -} - -export interface Request { - docvalue_fields: string[]; - _source: unknown; - query: unknown; - script_fields: unknown; - sort: unknown; - stored_fields: string[]; -} - -export interface ResponseWithShardFailure { - _shards: { - failed: number; - failures: ShardFailure[]; - skipped: number; - successful: number; - total: number; - }; -} - -export interface ShardFailure { - index: string; - node: string; - reason: { - caused_by: { - reason: string; - type: string; - }; - reason: string; - lang?: string; - script?: string; - script_stack?: string[]; - type: string; - }; - shard: number; -} - -export type SearchRequest = any; -export type SearchResponse = any; diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts deleted file mode 100644 index 0ec6a6c2e143e7..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { defaultSearchStrategy } from './default_search_strategy'; -import { IUiSettingsClient } from '../../../../../../core/public'; -import { SearchStrategySearchParams } from './types'; - -const { search } = defaultSearchStrategy; - -function getConfigStub(config: any = {}) { - return { - get: key => config[key], - } as IUiSettingsClient; -} - -const msearchMockResponse: any = Promise.resolve([]); -msearchMockResponse.abort = jest.fn(); -const msearchMock = jest.fn().mockReturnValue(msearchMockResponse); - -const searchMockResponse: any = Promise.resolve([]); -searchMockResponse.abort = jest.fn(); -const searchMock = jest.fn().mockReturnValue(searchMockResponse); - -describe('defaultSearchStrategy', function() { - describe('search', function() { - let searchArgs: MockedKeys>; - - beforeEach(() => { - msearchMockResponse.abort.mockClear(); - msearchMock.mockClear(); - - searchMockResponse.abort.mockClear(); - searchMock.mockClear(); - - searchArgs = { - searchRequests: [ - { - index: { title: 'foo' }, - }, - ], - esShardTimeout: 0, - es: { - msearch: msearchMock, - search: searchMock, - }, - }; - }); - - test('does not send max_concurrent_shard_requests by default', async () => { - const config = getConfigStub({ 'courier:batchSearches': true }); - await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(undefined); - }); - - test('allows configuration of max_concurrent_shard_requests', async () => { - const config = getConfigStub({ - 'courier:batchSearches': true, - 'courier:maxConcurrentShardRequests': 42, - }); - await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(42); - }); - - test('should set rest_total_hits_as_int to true on a request', async () => { - const config = getConfigStub({ 'courier:batchSearches': true }); - await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('rest_total_hits_as_int', true); - }); - - test('should set ignore_throttled=false when including frozen indices', async () => { - const config = getConfigStub({ - 'courier:batchSearches': true, - 'search:includeFrozen': true, - }); - await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false); - }); - - test('should properly call abort with msearch', () => { - const config = getConfigStub({ - 'courier:batchSearches': true, - }); - search({ ...searchArgs, config }).abort(); - expect(msearchMockResponse.abort).toHaveBeenCalled(); - }); - - test('should properly abort with search', async () => { - const config = getConfigStub({ - 'courier:batchSearches': false, - }); - search({ ...searchArgs, config }).abort(); - expect(searchMockResponse.abort).toHaveBeenCalled(); - }); - }); -}); diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts deleted file mode 100644 index 9bfa1df71aa81a..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { SearchStrategyProvider, SearchStrategySearchParams } from './types'; -import { isDefaultTypeIndexPattern } from './is_default_type_index_pattern'; -import { - getSearchParams, - getMSearchParams, - getPreference, - getTimeout, -} from '../fetch/get_search_params'; - -export const defaultSearchStrategy: SearchStrategyProvider = { - id: 'default', - - search: params => { - return params.config.get('courier:batchSearches') ? msearch(params) : search(params); - }, - - isViable: indexPattern => { - return indexPattern && isDefaultTypeIndexPattern(indexPattern); - }, -}; - -function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { - const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => { - const inlineHeader = { - index: index.title || index, - search_type: searchType, - ignore_unavailable: true, - preference: getPreference(config), - }; - const inlineBody = { - ...body, - timeout: getTimeout(esShardTimeout), - }; - return `${JSON.stringify(inlineHeader)}\n${JSON.stringify(inlineBody)}`; - }); - - const searching = es.msearch({ - ...getMSearchParams(config), - body: `${inlineRequests.join('\n')}\n`, - }); - return { - searching: searching.then(({ responses }) => responses), - abort: searching.abort, - }; -} - -function search({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { - const abortController = new AbortController(); - const searchParams = getSearchParams(config, esShardTimeout); - const promises = searchRequests.map(({ index, body }) => { - const searching = es.search({ index: index.title || index, body, ...searchParams }); - abortController.signal.addEventListener('abort', searching.abort); - return searching.catch(({ response }) => JSON.parse(response)); - }); - return { - searching: Promise.all(promises), - abort: () => abortController.abort(), - }; -} diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/index.ts b/src/legacy/core_plugins/data/public/search/search_strategy/index.ts deleted file mode 100644 index 1584baa4faade4..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_strategy/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { - addSearchStrategy, - hasSearchStategyForIndexPattern, - getSearchStrategyById, - getSearchStrategyForSearchRequest, -} from './search_strategy_registry'; - -export { defaultSearchStrategy } from './default_search_strategy'; - -export { isDefaultTypeIndexPattern } from './is_default_type_index_pattern'; - -export { SearchError, getSearchErrorType } from './search_error'; diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/is_default_type_index_pattern.ts b/src/legacy/core_plugins/data/public/search/search_strategy/is_default_type_index_pattern.ts deleted file mode 100644 index 7d03b1dc9e0b1a..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_strategy/is_default_type_index_pattern.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IndexPattern } from '../../../../../../plugins/data/public'; - -export const isDefaultTypeIndexPattern = (indexPattern: IndexPattern) => { - // Default index patterns don't have `type` defined. - return !indexPattern.type; -}; diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/types.ts b/src/legacy/core_plugins/data/public/search/search_strategy/types.ts deleted file mode 100644 index ad8576589e4e38..00000000000000 --- a/src/legacy/core_plugins/data/public/search/search_strategy/types.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IndexPattern } from '../../../../../../plugins/data/public'; -import { FetchHandlers } from '../fetch/types'; -import { SearchRequest, SearchResponse } from '../types'; - -export interface SearchStrategyProvider { - id: string; - search: (params: SearchStrategySearchParams) => SearchStrategyResponse; - isViable: (indexPattern: IndexPattern) => boolean; -} - -export interface SearchStrategyResponse { - searching: Promise; - abort: () => void; -} - -export interface SearchStrategySearchParams extends FetchHandlers { - searchRequests: SearchRequest[]; -} diff --git a/src/legacy/core_plugins/data/public/search/types.ts b/src/legacy/core_plugins/data/public/search/types.ts index 23d74ce6a57da8..140ceea4870997 100644 --- a/src/legacy/core_plugins/data/public/search/types.ts +++ b/src/legacy/core_plugins/data/public/search/types.ts @@ -17,7 +17,4 @@ * under the License. */ -export * from './fetch/types'; -export * from './search_source/types'; -export * from './search_strategy/types'; export * from './utils/types'; diff --git a/src/legacy/core_plugins/data/public/search/utils/courier_inspector_utils.ts b/src/legacy/core_plugins/data/public/search/utils/courier_inspector_utils.ts index 7f7d216d8f0f3f..62b7c572032c86 100644 --- a/src/legacy/core_plugins/data/public/search/utils/courier_inspector_utils.ts +++ b/src/legacy/core_plugins/data/public/search/utils/courier_inspector_utils.ts @@ -26,7 +26,8 @@ import { i18n } from '@kbn/i18n'; import { SearchResponse } from 'elasticsearch'; -import { ISearchSource, RequestInspectorStats } from '../types'; +import { RequestInspectorStats } from '../types'; +import { ISearchSource } from '../../../../../../plugins/data/public'; export function getRequestInspectorStats(searchSource: ISearchSource) { const stats: RequestInspectorStats = {}; diff --git a/src/legacy/core_plugins/elasticsearch/index.js b/src/legacy/core_plugins/elasticsearch/index.js index da7b557e7ea190..5872a33d8aa082 100644 --- a/src/legacy/core_plugins/elasticsearch/index.js +++ b/src/legacy/core_plugins/elasticsearch/index.js @@ -17,10 +17,10 @@ * under the License. */ import { first } from 'rxjs/operators'; -import healthCheck from './lib/health_check'; -import { Cluster } from './lib/cluster'; -import { createProxy } from './lib/create_proxy'; -import { handleESError } from './lib/handle_es_error'; +import healthCheck from './server/lib/health_check'; +import { Cluster } from './server/lib/cluster'; +import { createProxy } from './server/lib/create_proxy'; +import { handleESError } from './server/lib/handle_es_error'; export default function(kibana) { let defaultVars; diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js b/src/legacy/core_plugins/elasticsearch/server/lib/__tests__/ensure_es_version.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js rename to src/legacy/core_plugins/elasticsearch/server/lib/__tests__/ensure_es_version.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/handle_es_error.js b/src/legacy/core_plugins/elasticsearch/server/lib/__tests__/handle_es_error.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/__tests__/handle_es_error.js rename to src/legacy/core_plugins/elasticsearch/server/lib/__tests__/handle_es_error.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js b/src/legacy/core_plugins/elasticsearch/server/lib/__tests__/health_check.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js rename to src/legacy/core_plugins/elasticsearch/server/lib/__tests__/health_check.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/is_es_compatible_with_kibana.js b/src/legacy/core_plugins/elasticsearch/server/lib/__tests__/is_es_compatible_with_kibana.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/__tests__/is_es_compatible_with_kibana.js rename to src/legacy/core_plugins/elasticsearch/server/lib/__tests__/is_es_compatible_with_kibana.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/abortable_request_handler.js b/src/legacy/core_plugins/elasticsearch/server/lib/abortable_request_handler.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/abortable_request_handler.js rename to src/legacy/core_plugins/elasticsearch/server/lib/abortable_request_handler.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/abortable_request_handler.test.js b/src/legacy/core_plugins/elasticsearch/server/lib/abortable_request_handler.test.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/abortable_request_handler.test.js rename to src/legacy/core_plugins/elasticsearch/server/lib/abortable_request_handler.test.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/cluster.ts b/src/legacy/core_plugins/elasticsearch/server/lib/cluster.ts similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/cluster.ts rename to src/legacy/core_plugins/elasticsearch/server/lib/cluster.ts diff --git a/src/legacy/core_plugins/elasticsearch/lib/create_proxy.js b/src/legacy/core_plugins/elasticsearch/server/lib/create_proxy.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/create_proxy.js rename to src/legacy/core_plugins/elasticsearch/server/lib/create_proxy.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/ensure_es_version.js b/src/legacy/core_plugins/elasticsearch/server/lib/ensure_es_version.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/ensure_es_version.js rename to src/legacy/core_plugins/elasticsearch/server/lib/ensure_es_version.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/handle_es_error.js b/src/legacy/core_plugins/elasticsearch/server/lib/handle_es_error.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/handle_es_error.js rename to src/legacy/core_plugins/elasticsearch/server/lib/handle_es_error.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/health_check.js b/src/legacy/core_plugins/elasticsearch/server/lib/health_check.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/health_check.js rename to src/legacy/core_plugins/elasticsearch/server/lib/health_check.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/is_es_compatible_with_kibana.js b/src/legacy/core_plugins/elasticsearch/server/lib/is_es_compatible_with_kibana.js similarity index 100% rename from src/legacy/core_plugins/elasticsearch/lib/is_es_compatible_with_kibana.js rename to src/legacy/core_plugins/elasticsearch/server/lib/is_es_compatible_with_kibana.js diff --git a/src/legacy/core_plugins/elasticsearch/lib/kibana_version.js b/src/legacy/core_plugins/elasticsearch/server/lib/kibana_version.js similarity index 92% rename from src/legacy/core_plugins/elasticsearch/lib/kibana_version.js rename to src/legacy/core_plugins/elasticsearch/server/lib/kibana_version.js index e00c12f8271b09..344dbbb5bdf692 100644 --- a/src/legacy/core_plugins/elasticsearch/lib/kibana_version.js +++ b/src/legacy/core_plugins/elasticsearch/server/lib/kibana_version.js @@ -17,7 +17,7 @@ * under the License. */ -import { version as kibanaVersion } from '../../../../../package.json'; +import { version as kibanaVersion } from '../../../../../../package.json'; export default { // Make the version stubbable to improve testability. diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/controls_tab.test.tsx b/src/legacy/core_plugins/input_control_vis/public/components/editor/controls_tab.test.tsx index 4e7c9bafbf5102..3419d773bd09e6 100644 --- a/src/legacy/core_plugins/input_control_vis/public/components/editor/controls_tab.test.tsx +++ b/src/legacy/core_plugins/input_control_vis/public/components/editor/controls_tab.test.tsx @@ -21,8 +21,7 @@ import React from 'react'; import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers'; // @ts-ignore import { findTestSubject } from '@elastic/eui/lib/test'; -import { getDepsMock } from './__tests__/get_deps_mock'; -import { getIndexPatternMock } from './__tests__/get_index_pattern_mock'; +import { getDepsMock, getIndexPatternMock } from '../../test_utils'; import { ControlsTab, ControlsTabUiProps } from './controls_tab'; const indexPatternsMock = { diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/list_control_editor.test.tsx b/src/legacy/core_plugins/input_control_vis/public/components/editor/list_control_editor.test.tsx index f08a68b0da179b..942517e24514ed 100644 --- a/src/legacy/core_plugins/input_control_vis/public/components/editor/list_control_editor.test.tsx +++ b/src/legacy/core_plugins/input_control_vis/public/components/editor/list_control_editor.test.tsx @@ -25,11 +25,10 @@ import { shallow } from 'enzyme'; import { findTestSubject } from '@elastic/eui/lib/test'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { getDepsMock } from './__tests__/get_deps_mock'; -import { getIndexPatternMock } from './__tests__/get_index_pattern_mock'; +import { getIndexPatternMock } from '../../test_utils/get_index_pattern_mock'; import { ListControlEditor } from './list_control_editor'; import { ControlParams } from '../../editor_utils'; -import { updateComponent } from './__tests__/update_component'; +import { getDepsMock, updateComponent } from '../../test_utils'; const controlParamsBase: ControlParams = { id: '1', diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/range_control_editor.test.tsx b/src/legacy/core_plugins/input_control_vis/public/components/editor/range_control_editor.test.tsx index 55c4c71ce430b2..8f564e09bf4b2e 100644 --- a/src/legacy/core_plugins/input_control_vis/public/components/editor/range_control_editor.test.tsx +++ b/src/legacy/core_plugins/input_control_vis/public/components/editor/range_control_editor.test.tsx @@ -24,12 +24,11 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; // @ts-ignore import { findTestSubject } from '@elastic/eui/lib/test'; -import { getIndexPatternMock } from './__tests__/get_index_pattern_mock'; import { RangeControlEditor } from './range_control_editor'; import { ControlParams } from '../../editor_utils'; -import { getDepsMock } from './__tests__/get_deps_mock'; -import { updateComponent } from './__tests__/update_component'; +import { getDepsMock } from '../../test_utils/get_deps_mock'; +import { getIndexPatternMock, updateComponent } from '../../test_utils'; const controlParams: ControlParams = { id: '1', diff --git a/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.test.ts b/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.test.ts index 2420907727638c..e6426e5a4c69d9 100644 --- a/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.test.ts +++ b/src/legacy/core_plugins/input_control_vis/public/control/list_control_factory.test.ts @@ -19,8 +19,7 @@ import { listControlFactory, ListControl } from './list_control_factory'; import { ControlParams, CONTROL_TYPES } from '../editor_utils'; -import { getDepsMock } from '../components/editor/__tests__/get_deps_mock'; -import { getSearchSourceMock } from '../components/editor/__tests__/get_search_service_mock'; +import { getDepsMock, getSearchSourceMock } from '../test_utils'; const MockSearchSource = getSearchSourceMock(); const deps = getDepsMock(); diff --git a/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.test.ts b/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.test.ts index 5328aeb6c6a477..32df9de8ac9830 100644 --- a/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.test.ts +++ b/src/legacy/core_plugins/input_control_vis/public/control/range_control_factory.test.ts @@ -19,8 +19,7 @@ import { rangeControlFactory } from './range_control_factory'; import { ControlParams, CONTROL_TYPES } from '../editor_utils'; -import { getSearchSourceMock } from '../components/editor/__tests__/get_search_service_mock'; -import { getDepsMock } from '../components/editor/__tests__/get_deps_mock'; +import { getDepsMock, getSearchSourceMock } from '../test_utils'; const deps = getDepsMock(); diff --git a/src/legacy/core_plugins/input_control_vis/public/legacy_imports.ts b/src/legacy/core_plugins/input_control_vis/public/legacy_imports.ts index 176fe68fe4788a..9270cff84cc079 100644 --- a/src/legacy/core_plugins/input_control_vis/public/legacy_imports.ts +++ b/src/legacy/core_plugins/input_control_vis/public/legacy_imports.ts @@ -17,13 +17,14 @@ * under the License. */ -import { SearchSource as SearchSourceClass, ISearchSource } from 'ui/courier'; import { Class } from '@kbn/utility-types'; +import { SearchSource as SearchSourceClass, ISearchSource } from '../../../../plugins/data/public'; + +export { SearchSourceFields } from '../../../../plugins/data/public'; export { Vis, VisParams } from 'ui/vis'; export { VisOptionsProps } from 'ui/vis/editors/default'; export { ValidatedDualRange } from 'ui/validated_range'; -export { SearchSourceFields } from '../../data/public'; export type SearchSource = Class; export const SearchSource = SearchSourceClass; diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_deps_mock.tsx b/src/legacy/core_plugins/input_control_vis/public/test_utils/get_deps_mock.tsx similarity index 97% rename from src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_deps_mock.tsx rename to src/legacy/core_plugins/input_control_vis/public/test_utils/get_deps_mock.tsx index a9505aefa3113c..7b10eea3dde444 100644 --- a/src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_deps_mock.tsx +++ b/src/legacy/core_plugins/input_control_vis/public/test_utils/get_deps_mock.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { FieldList } from 'src/plugins/data/public'; -import { InputControlVisDependencies } from '../../../plugin'; +import { InputControlVisDependencies } from '../plugin'; const fields: FieldList = [] as any; fields.push({ name: 'myField' } as any); diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_index_pattern_mock.ts b/src/legacy/core_plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts similarity index 94% rename from src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_index_pattern_mock.ts rename to src/legacy/core_plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts index 638dd7170cb8df..da4663dc33429b 100644 --- a/src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_index_pattern_mock.ts +++ b/src/legacy/core_plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IIndexPattern } from '../../../../../../../plugins/data/public'; +import { IIndexPattern } from 'src/plugins/data/public'; /** * Returns forced **Partial** IndexPattern for use in tests diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_index_patterns_mock.ts b/src/legacy/core_plugins/input_control_vis/public/test_utils/get_index_patterns_mock.ts similarity index 100% rename from src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_index_patterns_mock.ts rename to src/legacy/core_plugins/input_control_vis/public/test_utils/get_index_patterns_mock.ts diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_search_service_mock.ts b/src/legacy/core_plugins/input_control_vis/public/test_utils/get_search_service_mock.ts similarity index 96% rename from src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_search_service_mock.ts rename to src/legacy/core_plugins/input_control_vis/public/test_utils/get_search_service_mock.ts index 9da47bedcc7843..94a460086e9da7 100644 --- a/src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/get_search_service_mock.ts +++ b/src/legacy/core_plugins/input_control_vis/public/test_utils/get_search_service_mock.ts @@ -17,7 +17,7 @@ * under the License. */ -import { SearchSource } from '../../../legacy_imports'; +import { SearchSource } from '../legacy_imports'; export const getSearchSourceMock = (esSearchResponse?: any): SearchSource => jest.fn().mockImplementation(() => ({ diff --git a/src/legacy/core_plugins/input_control_vis/public/test_utils/index.ts b/src/legacy/core_plugins/input_control_vis/public/test_utils/index.ts new file mode 100644 index 00000000000000..b474d39a540742 --- /dev/null +++ b/src/legacy/core_plugins/input_control_vis/public/test_utils/index.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { getDepsMock } from './get_deps_mock'; +export { getIndexPatternMock } from './get_index_pattern_mock'; +export { getIndexPatternsMock } from './get_index_patterns_mock'; +export { getSearchSourceMock } from './get_search_service_mock'; +export { updateComponent } from './update_component'; diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/update_component.ts b/src/legacy/core_plugins/input_control_vis/public/test_utils/update_component.ts similarity index 100% rename from src/legacy/core_plugins/input_control_vis/public/components/editor/__tests__/update_component.ts rename to src/legacy/core_plugins/input_control_vis/public/test_utils/update_component.ts diff --git a/src/legacy/core_plugins/kibana/common/lib/__tests__/convert_pattern_and_ingest_name.js b/src/legacy/core_plugins/kibana/common/lib/__tests__/convert_pattern_and_ingest_name.js deleted file mode 100644 index 2d138df67ebf97..00000000000000 --- a/src/legacy/core_plugins/kibana/common/lib/__tests__/convert_pattern_and_ingest_name.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { patternToIngest, ingestToPattern } from '../convert_pattern_and_ingest_name'; - -describe('convertPatternAndTemplateName', function() { - describe('ingestToPattern', function() { - it("should convert an index template's name to its matching index pattern's title", function() { - expect(ingestToPattern('kibana-logstash-*')).to.be('logstash-*'); - }); - - it("should throw an error if the template name isn't a valid kibana namespaced name", function() { - expect(ingestToPattern) - .withArgs('logstash-*') - .to.throwException('not a valid kibana namespaced template name'); - expect(ingestToPattern) - .withArgs('') - .to.throwException(/not a valid kibana namespaced template name/); - }); - }); - - describe('patternToIngest', function() { - it("should convert an index pattern's title to its matching index template's name", function() { - expect(patternToIngest('logstash-*')).to.be('kibana-logstash-*'); - }); - - it('should throw an error if the pattern is empty', function() { - expect(patternToIngest) - .withArgs('') - .to.throwException(/pattern must not be empty/); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/common/lib/convert_pattern_and_ingest_name.js b/src/legacy/core_plugins/kibana/common/lib/convert_pattern_and_ingest_name.js deleted file mode 100644 index 216dc7d882a2cd..00000000000000 --- a/src/legacy/core_plugins/kibana/common/lib/convert_pattern_and_ingest_name.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// To avoid index template naming collisions the index pattern creation API -// namespaces template names by prepending 'kibana-' to the matching pattern's title. -// e.g. a pattern with title `logstash-*` will have a matching template named `kibana-logstash-*`. -// This module provides utility functions for easily converting between template and pattern names. - -export function ingestToPattern(templateName) { - if (templateName.indexOf('kibana-') === -1) { - throw new Error('not a valid kibana namespaced template name'); - } - - return templateName.slice(templateName.indexOf('-') + 1); -} - -export function patternToIngest(patternName) { - if (patternName === '') { - throw new Error('pattern must not be empty'); - } - - return `kibana-${patternName.toLowerCase()}`; -} diff --git a/src/legacy/core_plugins/kibana/common/lib/get_space_id_for_beats_tutorial.js b/src/legacy/core_plugins/kibana/common/lib/get_space_id_for_beats_tutorial.js deleted file mode 100644 index f7da5895260036..00000000000000 --- a/src/legacy/core_plugins/kibana/common/lib/get_space_id_for_beats_tutorial.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Returns valid configuration for a beat.yml file for adding the space id - * if there is an active space and that space is not the default one. - * - * @param {object} context - Context object generated from tutorial factory (see #22760) - */ -export function getSpaceIdForBeatsTutorial(context) { - if (!context || !context.spaceId || context.isInDefaultSpace) { - return ''; - } - - return ` space.id: "${context.spaceId}"`; -} diff --git a/src/legacy/core_plugins/kibana/common/tutorials/auditbeat_instructions.js b/src/legacy/core_plugins/kibana/common/tutorials/auditbeat_instructions.js deleted file mode 100644 index 3d95738ab21f76..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/auditbeat_instructions.js +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { INSTRUCTION_VARIANT } from './instruction_variant'; -import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; -import { getSpaceIdForBeatsTutorial } from '../lib/get_space_id_for_beats_tutorial'; - -export const createAuditbeatInstructions = context => ({ - INSTALL: { - OSX: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.osxTitle', { - defaultMessage: 'Download and install Auditbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.osxTextPre', { - defaultMessage: 'First time using Auditbeat? See the [Getting Started Guide]({linkUrl}).', - values: { - linkUrl: '{config.docs.beats.auditbeat}/auditbeat-getting-started.html', - }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'tar xzvf auditbeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'cd auditbeat-{config.kibana.version}-darwin-x86_64/', - ], - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.debTitle', { - defaultMessage: 'Download and install Auditbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.debTextPre', { - defaultMessage: 'First time using Auditbeat? See the [Getting Started Guide]({linkUrl}).', - values: { - linkUrl: '{config.docs.beats.auditbeat}/auditbeat-getting-started.html', - }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-{config.kibana.version}-amd64.deb', - 'sudo dpkg -i auditbeat-{config.kibana.version}-amd64.deb', - ], - textPost: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.debTextPost', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({linkUrl}).', - values: { - linkUrl: 'https://www.elastic.co/downloads/beats/auditbeat', - }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.rpmTitle', { - defaultMessage: 'Download and install Auditbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.rpmTextPre', { - defaultMessage: 'First time using Auditbeat? See the [Getting Started Guide]({linkUrl}).', - values: { - linkUrl: '{config.docs.beats.auditbeat}/auditbeat-getting-started.html', - }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-{config.kibana.version}-x86_64.rpm', - 'sudo rpm -vi auditbeat-{config.kibana.version}-x86_64.rpm', - ], - textPost: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.rpmTextPost', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({linkUrl}).', - values: { - linkUrl: 'https://www.elastic.co/downloads/beats/auditbeat', - }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.windowsTitle', { - defaultMessage: 'Download and install Auditbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.install.windowsTextPre', { - defaultMessage: - 'First time using Auditbeat? See the [Getting Started Guide]({guideLinkUrl}).\n\ - 1. Download the Auditbeat Windows zip file from the [Download]({auditbeatLinkUrl}) page.\n\ - 2. Extract the contents of the zip file into {folderPath}.\n\ - 3. Rename the `{directoryName}` directory to `Auditbeat`.\n\ - 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ -**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ - 5. From the PowerShell prompt, run the following commands to install Auditbeat as a Windows service.', - values: { - folderPath: '`C:\\Program Files`', - guideLinkUrl: '{config.docs.beats.auditbeat}/auditbeat-getting-started.html', - auditbeatLinkUrl: 'https://www.elastic.co/downloads/beats/auditbeat', - directoryName: 'auditbeat-{config.kibana.version}-windows', - }, - }), - commands: ['cd "C:\\Program Files\\Auditbeat"', '.\\install-service-auditbeat.ps1'], - textPost: i18n.translate( - 'kbn.common.tutorials.auditbeatInstructions.install.windowsTextPost', - { - defaultMessage: - 'Modify the settings under {propertyName} in the {auditbeatPath} file to point to your Elasticsearch installation.', - values: { - propertyName: '`output.elasticsearch`', - auditbeatPath: '`C:\\Program Files\\Auditbeat\\auditbeat.yml`', - }, - } - ), - }, - }, - START: { - OSX: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.start.osxTitle', { - defaultMessage: 'Start Auditbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.start.osxTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['./auditbeat setup', './auditbeat -e'], - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.start.debTitle', { - defaultMessage: 'Start Auditbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.start.debTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['sudo auditbeat setup', 'sudo service auditbeat start'], - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.start.rpmTitle', { - defaultMessage: 'Start Auditbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.start.rpmTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['sudo auditbeat setup', 'sudo service auditbeat start'], - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.start.windowsTitle', { - defaultMessage: 'Start Auditbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.start.windowsTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['.\\auditbeat.exe setup', 'Start-Service auditbeat'], - }, - }, - CONFIG: { - OSX: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.osxTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`auditbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.osxTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.debTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.debTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`/etc/auditbeat/auditbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.debTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.rpmTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.rpmTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`/etc/auditbeat/auditbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.rpmTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatInstructions.config.windowsTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`C:\\Program Files\\Auditbeat\\auditbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate( - 'kbn.common.tutorials.auditbeatInstructions.config.windowsTextPost', - { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - } - ), - }, - }, -}); - -export const createAuditbeatCloudInstructions = () => ({ - CONFIG: { - OSX: { - title: i18n.translate('kbn.common.tutorials.auditbeatCloudInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatCloudInstructions.config.osxTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`auditbeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.auditbeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.auditbeatCloudInstructions.config.debTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatCloudInstructions.config.debTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`/etc/auditbeat/auditbeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.auditbeatCloudInstructions.config.debTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`/etc/auditbeat/auditbeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`C:\\Program Files\\Auditbeat\\auditbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - }, -}); - -export function auditbeatStatusCheck() { - return { - title: i18n.translate('kbn.common.tutorials.auditbeatStatusCheck.title', { - defaultMessage: 'Status', - }), - text: i18n.translate('kbn.common.tutorials.auditbeatStatusCheck.text', { - defaultMessage: 'Check that data is received from Auditbeat', - }), - btnLabel: i18n.translate('kbn.common.tutorials.auditbeatStatusCheck.buttonLabel', { - defaultMessage: 'Check data', - }), - success: i18n.translate('kbn.common.tutorials.auditbeatStatusCheck.successText', { - defaultMessage: 'Data successfully received', - }), - error: i18n.translate('kbn.common.tutorials.auditbeatStatusCheck.errorText', { - defaultMessage: 'No data has been received yet', - }), - esHitsCheck: { - index: 'auditbeat-*', - query: { - bool: { - filter: { - term: { - 'agent.type': 'auditbeat', - }, - }, - }, - }, - }, - }; -} - -export function onPremInstructions(platforms, context) { - const AUDITBEAT_INSTRUCTIONS = createAuditbeatInstructions(context); - - const variants = []; - for (let i = 0; i < platforms.length; i++) { - const platform = platforms[i]; - const instructions = []; - instructions.push(AUDITBEAT_INSTRUCTIONS.INSTALL[platform]); - instructions.push(AUDITBEAT_INSTRUCTIONS.CONFIG[platform]); - instructions.push(AUDITBEAT_INSTRUCTIONS.START[platform]); - variants.push({ - id: INSTRUCTION_VARIANT[platform], - instructions: instructions, - }); - } - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.auditbeat.premInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: variants, - statusCheck: auditbeatStatusCheck(), - }, - ], - }; -} - -export function onPremCloudInstructions(platforms) { - const AUDITBEAT_INSTRUCTIONS = createAuditbeatInstructions(); - const TRYCLOUD_OPTION1 = createTrycloudOption1(); - const TRYCLOUD_OPTION2 = createTrycloudOption2(); - - const variants = []; - for (let i = 0; i < platforms.length; i++) { - const platform = platforms[i]; - variants.push({ - id: INSTRUCTION_VARIANT[platform], - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - AUDITBEAT_INSTRUCTIONS.INSTALL[platform], - AUDITBEAT_INSTRUCTIONS.CONFIG[platform], - AUDITBEAT_INSTRUCTIONS.START[platform], - ], - }); - } - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.auditbeat.premCloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: variants, - statusCheck: auditbeatStatusCheck(), - }, - ], - }; -} - -export function cloudInstructions(platforms) { - const AUDITBEAT_INSTRUCTIONS = createAuditbeatInstructions(); - const AUDITBEAT_CLOUD_INSTRUCTIONS = createAuditbeatCloudInstructions(); - - const variants = []; - for (let i = 0; i < platforms.length; i++) { - const platform = platforms[i]; - variants.push({ - id: INSTRUCTION_VARIANT[platform], - instructions: [ - AUDITBEAT_INSTRUCTIONS.INSTALL[platform], - AUDITBEAT_CLOUD_INSTRUCTIONS.CONFIG[platform], - AUDITBEAT_INSTRUCTIONS.START[platform], - ], - }); - } - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.auditbeat.cloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: variants, - statusCheck: auditbeatStatusCheck(), - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/common/tutorials/filebeat_instructions.js b/src/legacy/core_plugins/kibana/common/tutorials/filebeat_instructions.js deleted file mode 100644 index 2180a489a449d1..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/filebeat_instructions.js +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { INSTRUCTION_VARIANT } from './instruction_variant'; -import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; -import { getSpaceIdForBeatsTutorial } from '../lib/get_space_id_for_beats_tutorial'; - -export const createFilebeatInstructions = context => ({ - INSTALL: { - OSX: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.osxTitle', { - defaultMessage: 'Download and install Filebeat', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.osxTextPre', { - defaultMessage: 'First time using Filebeat? See the [Getting Started Guide]({linkUrl}).', - values: { - linkUrl: '{config.docs.beats.filebeat}/filebeat-getting-started.html', - }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'tar xzvf filebeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'cd filebeat-{config.kibana.version}-darwin-x86_64/', - ], - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.debTitle', { - defaultMessage: 'Download and install Filebeat', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.debTextPre', { - defaultMessage: 'First time using Filebeat? See the [Getting Started Guide]({linkUrl}).', - values: { - linkUrl: '{config.docs.beats.filebeat}/filebeat-getting-started.html', - }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-amd64.deb', - 'sudo dpkg -i filebeat-{config.kibana.version}-amd64.deb', - ], - textPost: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.debTextPost', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({linkUrl}).', - values: { - linkUrl: 'https://www.elastic.co/downloads/beats/filebeat', - }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.rpmTitle', { - defaultMessage: 'Download and install Filebeat', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.rpmTextPre', { - defaultMessage: 'First time using Filebeat? See the [Getting Started Guide]({linkUrl}).', - values: { - linkUrl: '{config.docs.beats.filebeat}/filebeat-getting-started.html', - }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-x86_64.rpm', - 'sudo rpm -vi filebeat-{config.kibana.version}-x86_64.rpm', - ], - textPost: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.rpmTextPost', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({linkUrl}).', - values: { - linkUrl: 'https://www.elastic.co/downloads/beats/filebeat', - }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.windowsTitle', { - defaultMessage: 'Download and install Filebeat', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.install.windowsTextPre', { - defaultMessage: - 'First time using Filebeat? See the [Getting Started Guide]({guideLinkUrl}).\n\ - 1. Download the Filebeat Windows zip file from the [Download]({filebeatLinkUrl}) page.\n\ - 2. Extract the contents of the zip file into {folderPath}.\n\ - 3. Rename the `{directoryName}` directory to `Filebeat`.\n\ - 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ -**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ - 5. From the PowerShell prompt, run the following commands to install Filebeat as a Windows service.', - values: { - folderPath: '`C:\\Program Files`', - guideLinkUrl: '{config.docs.beats.filebeat}/filebeat-getting-started.html', - filebeatLinkUrl: 'https://www.elastic.co/downloads/beats/filebeat', - directoryName: 'filebeat-{config.kibana.version}-windows', - }, - }), - commands: ['cd "C:\\Program Files\\Filebeat"', '.\\install-service-filebeat.ps1'], - textPost: i18n.translate( - 'kbn.common.tutorials.filebeatInstructions.install.windowsTextPost', - { - defaultMessage: - 'Modify the settings under {propertyName} in the {filebeatPath} file to point to your Elasticsearch installation.', - values: { - propertyName: '`output.elasticsearch`', - filebeatPath: '`C:\\Program Files\\Filebeat\\filebeat.yml`', - }, - } - ), - }, - }, - START: { - OSX: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.start.osxTitle', { - defaultMessage: 'Start Filebeat', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.start.osxTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['./filebeat setup', './filebeat -e'], - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.start.debTitle', { - defaultMessage: 'Start Filebeat', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.start.debTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['sudo filebeat setup', 'sudo service filebeat start'], - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.start.rpmTitle', { - defaultMessage: 'Start Filebeat', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.start.rpmTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['sudo filebeat setup', 'sudo service filebeat start'], - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.start.windowsTitle', { - defaultMessage: 'Start Filebeat', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.start.windowsTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['.\\filebeat.exe setup', 'Start-Service filebeat'], - }, - }, - CONFIG: { - OSX: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.osxTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`filebeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.osxTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.debTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.debTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`/etc/filebeat/filebeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.debTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.rpmTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.rpmTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`/etc/filebeat/filebeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.rpmTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.windowsTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`C:\\Program Files\\Filebeat\\filebeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.filebeatInstructions.config.windowsTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - }, -}); - -export const createFilebeatCloudInstructions = () => ({ - CONFIG: { - OSX: { - title: i18n.translate('kbn.common.tutorials.filebeatCloudInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatCloudInstructions.config.osxTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`filebeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.filebeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.filebeatCloudInstructions.config.debTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatCloudInstructions.config.debTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`/etc/filebeat/filebeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.filebeatCloudInstructions.config.debTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.filebeatCloudInstructions.config.rpmTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatCloudInstructions.config.rpmTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`/etc/filebeat/filebeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.filebeatCloudInstructions.config.rpmTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.filebeatCloudInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.filebeatCloudInstructions.config.windowsTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`C:\\Program Files\\Filebeat\\filebeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.filebeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - }, -}); - -export function filebeatEnableInstructions(moduleName) { - return { - OSX: { - title: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.osxTitle', { - defaultMessage: 'Enable and configure the {moduleName} module', - values: { moduleName }, - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.osxTextPre', { - defaultMessage: 'From the installation directory, run:', - }), - commands: ['./filebeat modules enable ' + moduleName], - textPost: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.osxTextPost', { - defaultMessage: 'Modify the settings in the `modules.d/{moduleName}.yml` file.', - values: { moduleName }, - }), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.debTitle', { - defaultMessage: 'Enable and configure the {moduleName} module', - values: { moduleName }, - }), - commands: ['sudo filebeat modules enable ' + moduleName], - textPost: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.debTextPost', { - defaultMessage: - 'Modify the settings in the `/etc/filebeat/modules.d/{moduleName}.yml` file.', - values: { moduleName }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.rpmTitle', { - defaultMessage: 'Enable and configure the {moduleName} module', - values: { moduleName }, - }), - commands: ['sudo filebeat modules enable ' + moduleName], - textPost: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.rpmTextPost', { - defaultMessage: - 'Modify the settings in the `/etc/filebeat/modules.d/{moduleName}.yml` file.', - values: { moduleName }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.windowsTitle', { - defaultMessage: 'Enable and configure the {moduleName} module', - values: { moduleName }, - }), - textPre: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.windowsTextPre', { - defaultMessage: 'From the {path} folder, run:', - values: { path: `C:\\Program Files\\Filebeat` }, - }), - commands: ['filebeat.exe modules enable ' + moduleName], - textPost: i18n.translate('kbn.common.tutorials.filebeatEnableInstructions.windowsTextPost', { - defaultMessage: 'Modify the settings in the `modules.d/{moduleName}.yml` file.', - values: { moduleName }, - }), - }, - }; -} - -export function filebeatStatusCheck(moduleName) { - return { - title: i18n.translate('kbn.common.tutorials.filebeatStatusCheck.title', { - defaultMessage: 'Module status', - }), - text: i18n.translate('kbn.common.tutorials.filebeatStatusCheck.text', { - defaultMessage: 'Check that data is received from the Filebeat `{moduleName}` module', - values: { moduleName }, - }), - btnLabel: i18n.translate('kbn.common.tutorials.filebeatStatusCheck.buttonLabel', { - defaultMessage: 'Check data', - }), - success: i18n.translate('kbn.common.tutorials.filebeatStatusCheck.successText', { - defaultMessage: 'Data successfully received from this module', - }), - error: i18n.translate('kbn.common.tutorials.filebeatStatusCheck.errorText', { - defaultMessage: 'No data has been received from this module yet', - }), - esHitsCheck: { - index: 'filebeat-*', - query: { - bool: { - filter: { - term: { - 'event.module': moduleName, - }, - }, - }, - }, - }, - }; -} - -export function onPremInstructions(moduleName, platforms, context) { - const FILEBEAT_INSTRUCTIONS = createFilebeatInstructions(context); - - const variants = []; - for (let i = 0; i < platforms.length; i++) { - const platform = platforms[i]; - const instructions = []; - instructions.push(FILEBEAT_INSTRUCTIONS.INSTALL[platform]); - instructions.push(FILEBEAT_INSTRUCTIONS.CONFIG[platform]); - instructions.push(filebeatEnableInstructions(moduleName)[platform]); - instructions.push(FILEBEAT_INSTRUCTIONS.START[platform]); - variants.push({ - id: INSTRUCTION_VARIANT[platform], - instructions: instructions, - }); - } - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.filebeat.premInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: variants, - statusCheck: filebeatStatusCheck(moduleName), - }, - ], - }; -} - -export function onPremCloudInstructions(moduleName, platforms) { - const FILEBEAT_INSTRUCTIONS = createFilebeatInstructions(); - const TRYCLOUD_OPTION1 = createTrycloudOption1(); - const TRYCLOUD_OPTION2 = createTrycloudOption2(); - - const variants = []; - for (let i = 0; i < platforms.length; i++) { - const platform = platforms[i]; - variants.push({ - id: INSTRUCTION_VARIANT[platform], - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - FILEBEAT_INSTRUCTIONS.INSTALL[platform], - FILEBEAT_INSTRUCTIONS.CONFIG[platform], - filebeatEnableInstructions(moduleName)[platform], - FILEBEAT_INSTRUCTIONS.START[platform], - ], - }); - } - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.filebeat.premCloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: variants, - statusCheck: filebeatStatusCheck(moduleName), - }, - ], - }; -} - -export function cloudInstructions(moduleName, platforms) { - const FILEBEAT_INSTRUCTIONS = createFilebeatInstructions(); - const FILEBEAT_CLOUD_INSTRUCTIONS = createFilebeatCloudInstructions(); - - const variants = []; - for (let i = 0; i < platforms.length; i++) { - const platform = platforms[i]; - variants.push({ - id: INSTRUCTION_VARIANT[platform], - instructions: [ - FILEBEAT_INSTRUCTIONS.INSTALL[platform], - FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG[platform], - filebeatEnableInstructions(moduleName)[platform], - FILEBEAT_INSTRUCTIONS.START[platform], - ], - }); - } - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.filebeat.cloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: variants, - statusCheck: filebeatStatusCheck(moduleName), - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/common/tutorials/functionbeat_instructions.js b/src/legacy/core_plugins/kibana/common/tutorials/functionbeat_instructions.js deleted file mode 100644 index f4116191c1cac5..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/functionbeat_instructions.js +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { INSTRUCTION_VARIANT } from './instruction_variant'; -import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; -import { getSpaceIdForBeatsTutorial } from '../lib/get_space_id_for_beats_tutorial'; - -export const createFunctionbeatInstructions = context => ({ - INSTALL: { - OSX: { - title: i18n.translate('kbn.common.tutorials.functionbeatInstructions.install.osxTitle', { - defaultMessage: 'Download and install Functionbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.functionbeatInstructions.install.osxTextPre', { - defaultMessage: 'First time using Functionbeat? See the [Getting Started Guide]({link}).', - values: { link: '{config.docs.beats.functionbeat}/functionbeat-getting-started.html' }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/functionbeat/functionbeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'tar xzvf functionbeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'cd functionbeat-{config.kibana.version}-darwin-x86_64/', - ], - }, - LINUX: { - title: i18n.translate('kbn.common.tutorials.functionbeatInstructions.install.linuxTitle', { - defaultMessage: 'Download and install Functionbeat', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.functionbeatInstructions.install.linuxTextPre', - { - defaultMessage: 'First time using Functionbeat? See the [Getting Started Guide]({link}).', - values: { link: '{config.docs.beats.functionbeat}/functionbeat-getting-started.html' }, - } - ), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/functionbeat/functionbeat-{config.kibana.version}-linux-x86_64.tar.gz', - 'tar xzvf functionbeat-{config.kibana.version}-linux-x86_64.tar.gz', - 'cd functionbeat-{config.kibana.version}-linux-x86_64/', - ], - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.functionbeatInstructions.install.windowsTitle', { - defaultMessage: 'Download and install Functionbeat', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.functionbeatInstructions.install.windowsTextPre', - { - defaultMessage: - 'First time using Functionbeat? See the [Getting Started Guide]({functionbeatLink}).\n\ - 1. Download the Functionbeat Windows zip file from the [Download]({elasticLink}) page.\n\ - 2. Extract the contents of the zip file into {folderPath}.\n\ - 3. Rename the {directoryName} directory to `Functionbeat`.\n\ - 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ -**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ - 5. From the PowerShell prompt, go to the Functionbeat directory:', - values: { - directoryName: '`functionbeat-{config.kibana.version}-windows`', - folderPath: '`C:\\Program Files`', - functionbeatLink: '{config.docs.beats.functionbeat}/functionbeat-getting-started.html', - elasticLink: 'https://www.elastic.co/downloads/beats/functionbeat', - }, - } - ), - commands: ['cd "C:\\Program Files\\Functionbeat"'], - }, - }, - DEPLOY: { - OSX_LINUX: { - title: i18n.translate('kbn.common.tutorials.functionbeatInstructions.deploy.osxTitle', { - defaultMessage: 'Deploy Functionbeat to AWS Lambda', - }), - textPre: i18n.translate('kbn.common.tutorials.functionbeatInstructions.deploy.osxTextPre', { - defaultMessage: - 'This installs Functionbeat as a Lambda function.\ -The `setup` command checks the Elasticsearch configuration and loads the \ -Kibana index pattern. It is normally safe to omit this command.', - }), - commands: ['./functionbeat setup', './functionbeat deploy fn-cloudwatch-logs'], - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.functionbeatInstructions.deploy.windowsTitle', { - defaultMessage: 'Deploy Functionbeat to AWS Lambda', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.functionbeatInstructions.deploy.windowsTextPre', - { - defaultMessage: - 'This installs Functionbeat as a Lambda function.\ -The `setup` command checks the Elasticsearch configuration and loads the \ -Kibana index pattern. It is normally safe to omit this command.', - } - ), - commands: ['.\\functionbeat.exe setup', '.\\functionbeat.exe deploy fn-cloudwatch-logs'], - }, - }, - CONFIG: { - OSX_LINUX: { - title: i18n.translate('kbn.common.tutorials.functionbeatInstructions.config.osxTitle', { - defaultMessage: 'Configure the Elastic cluster', - }), - textPre: i18n.translate('kbn.common.tutorials.functionbeatInstructions.config.osxTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`functionbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.functionbeatInstructions.config.osxTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.functionbeatInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.functionbeatInstructions.config.windowsTextPre', - { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`C:\\Program Files\\Functionbeat\\functionbeat.yml`', - }, - } - ), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate( - 'kbn.common.tutorials.functionbeatInstructions.config.windowsTextPost', - { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - } - ), - }, - }, -}); - -export const createFunctionbeatCloudInstructions = () => ({ - CONFIG: { - OSX_LINUX: { - title: i18n.translate('kbn.common.tutorials.functionbeatCloudInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.functionbeatCloudInstructions.config.osxTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`functionbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.functionbeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - WINDOWS: { - title: i18n.translate( - 'kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`C:\\Program Files\\Functionbeat\\functionbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - }, -}); - -export function functionbeatEnableInstructions() { - const defaultTitle = i18n.translate( - 'kbn.common.tutorials.functionbeatEnableOnPremInstructions.defaultTitle', - { - defaultMessage: 'Configure the Cloudwatch log group', - } - ); - const defaultCommands = [ - 'functionbeat.provider.aws.functions:', - ' - name: fn-cloudwatch-logs', - ' enabled: true', - ' type: cloudwatch_logs', - ' triggers:', - ' - log_group_name: ', - 'functionbeat.provider.aws.deploy_bucket: ', - ]; - const defaultTextPost = i18n.translate( - 'kbn.common.tutorials.functionbeatEnableOnPremInstructions.defaultTextPost', - { - defaultMessage: - 'Where `` is the name of the log group you want to ingest, \ -and `` is a valid S3 bucket name which will be used for staging the \ -Functionbeat deploy.', - } - ); - return { - OSX_LINUX: { - title: defaultTitle, - textPre: i18n.translate( - 'kbn.common.tutorials.functionbeatEnableOnPremInstructionsOSXLinux.textPre', - { - defaultMessage: 'Modify the settings in the `functionbeat.yml` file.', - } - ), - commands: defaultCommands, - textPost: defaultTextPost, - }, - WINDOWS: { - title: defaultTitle, - textPre: i18n.translate( - 'kbn.common.tutorials.functionbeatEnableOnPremInstructionsWindows.textPre', - { - defaultMessage: 'Modify the settings in the {path} file.', - values: { - path: '`C:\\Program Files\\Functionbeat\\functionbeat.yml`', - }, - } - ), - commands: defaultCommands, - textPost: defaultTextPost, - }, - }; -} - -export function functionbeatAWSInstructions() { - const defaultTitle = i18n.translate('kbn.common.tutorials.functionbeatAWSInstructions.title', { - defaultMessage: 'Set AWS credentials', - }); - const defaultPre = i18n.translate('kbn.common.tutorials.functionbeatAWSInstructions.textPre', { - defaultMessage: 'Set your AWS account credentials in the environment:', - }); - const defaultPost = i18n.translate('kbn.common.tutorials.functionbeatAWSInstructions.textPost', { - defaultMessage: - 'Where `` and `` are your account credentials and \ -`us-east-1` is the desired region.', - }); - - return { - OSX_LINUX: { - title: defaultTitle, - textPre: defaultPre, - commands: [ - 'export AWS_ACCESS_KEY_ID=', - 'export AWS_SECRET_ACCESS_KEY=', - 'export AWS_DEFAULT_REGION=us-east-1', - ], - textPost: defaultPost, - }, - WINDOWS: { - title: defaultTitle, - textPre: defaultPre, - commands: [ - 'set AWS_ACCESS_KEY_ID=', - 'set AWS_SECRET_ACCESS_KEY=', - 'set AWS_DEFAULT_REGION=us-east-1', - ], - textPost: defaultPost, - }, - }; -} - -export function functionbeatStatusCheck() { - return { - title: i18n.translate('kbn.common.tutorials.functionbeatStatusCheck.title', { - defaultMessage: 'Functionbeat status', - }), - text: i18n.translate('kbn.common.tutorials.functionbeatStatusCheck.text', { - defaultMessage: 'Check that data is received from Functionbeat', - }), - btnLabel: i18n.translate('kbn.common.tutorials.functionbeatStatusCheck.buttonLabel', { - defaultMessage: 'Check data', - }), - success: i18n.translate('kbn.common.tutorials.functionbeatStatusCheck.successText', { - defaultMessage: 'Data successfully received from Functionbeat', - }), - error: i18n.translate('kbn.common.tutorials.functionbeatStatusCheck.errorText', { - defaultMessage: 'No data has been received from Functionbeat yet', - }), - esHitsCheck: { - index: 'functionbeat-*', - query: { - match_all: {}, - }, - }, - }; -} - -export function onPremInstructions(platforms, context) { - const FUNCTIONBEAT_INSTRUCTIONS = createFunctionbeatInstructions(context); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.functionbeat.premInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.OSX, - functionbeatAWSInstructions().OSX_LINUX, - functionbeatEnableInstructions().OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.CONFIG.OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, - ], - }, - { - id: INSTRUCTION_VARIANT.LINUX, - instructions: [ - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.LINUX, - functionbeatAWSInstructions().OSX_LINUX, - functionbeatEnableInstructions().OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.CONFIG.OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - functionbeatAWSInstructions().WINDOWS, - functionbeatEnableInstructions().WINDOWS, - FUNCTIONBEAT_INSTRUCTIONS.CONFIG.WINDOWS, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.WINDOWS, - ], - }, - ], - statusCheck: functionbeatStatusCheck(), - }, - ], - }; -} - -export function onPremCloudInstructions() { - const TRYCLOUD_OPTION1 = createTrycloudOption1(); - const TRYCLOUD_OPTION2 = createTrycloudOption2(); - const FUNCTIONBEAT_INSTRUCTIONS = createFunctionbeatInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.functionbeat.premCloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.OSX, - functionbeatAWSInstructions().OSX_LINUX, - functionbeatEnableInstructions().OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.CONFIG.OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, - ], - }, - { - id: INSTRUCTION_VARIANT.LINUX, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.LINUX, - functionbeatAWSInstructions().OSX_LINUX, - functionbeatEnableInstructions().OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.CONFIG.OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - functionbeatAWSInstructions().WINDOWS, - functionbeatEnableInstructions().WINDOWS, - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - FUNCTIONBEAT_INSTRUCTIONS.CONFIG.WINDOWS, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.WINDOWS, - ], - }, - ], - statusCheck: functionbeatStatusCheck(), - }, - ], - }; -} - -export function cloudInstructions() { - const FUNCTIONBEAT_INSTRUCTIONS = createFunctionbeatInstructions(); - const FUNCTIONBEAT_CLOUD_INSTRUCTIONS = createFunctionbeatCloudInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.functionbeat.cloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.OSX, - functionbeatAWSInstructions().OSX_LINUX, - functionbeatEnableInstructions().OSX_LINUX, - FUNCTIONBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, - ], - }, - { - id: INSTRUCTION_VARIANT.LINUX, - instructions: [ - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.LINUX, - functionbeatAWSInstructions().OSX_LINUX, - functionbeatEnableInstructions().OSX_LINUX, - FUNCTIONBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX_LINUX, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - FUNCTIONBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - functionbeatAWSInstructions().WINDOWS, - functionbeatEnableInstructions().WINDOWS, - FUNCTIONBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS, - FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.WINDOWS, - ], - }, - ], - statusCheck: functionbeatStatusCheck(), - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/common/tutorials/heartbeat_instructions.js b/src/legacy/core_plugins/kibana/common/tutorials/heartbeat_instructions.js deleted file mode 100644 index d9af2126174f7d..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/heartbeat_instructions.js +++ /dev/null @@ -1,674 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { INSTRUCTION_VARIANT } from './instruction_variant'; -import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; -import { getSpaceIdForBeatsTutorial } from '../lib/get_space_id_for_beats_tutorial'; - -export const createHeartbeatInstructions = context => ({ - INSTALL: { - OSX: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.osxTitle', { - defaultMessage: 'Download and install Heartbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.osxTextPre', { - defaultMessage: 'First time using Heartbeat? See the [Getting Started Guide]({link}).', - values: { link: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html' }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'tar xzvf heartbeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'cd heartbeat-{config.kibana.version}-darwin-x86_64/', - ], - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.debTitle', { - defaultMessage: 'Download and install Heartbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.debTextPre', { - defaultMessage: 'First time using Heartbeat? See the [Getting Started Guide]({link}).', - values: { link: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html' }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-{config.kibana.version}-amd64.deb', - 'sudo dpkg -i heartbeat-{config.kibana.version}-amd64.deb', - ], - textPost: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.debTextPost', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({link}).', - values: { link: 'https://www.elastic.co/downloads/beats/heartbeat' }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.rpmTitle', { - defaultMessage: 'Download and install Heartbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.rpmTextPre', { - defaultMessage: 'First time using Heartbeat? See the [Getting Started Guide]({link}).', - values: { link: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html' }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-{config.kibana.version}-x86_64.rpm', - 'sudo rpm -vi heartbeat-{config.kibana.version}-x86_64.rpm', - ], - textPost: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.debTextPost', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({link}).', - values: { link: 'https://www.elastic.co/downloads/beats/heartbeat' }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.windowsTitle', { - defaultMessage: 'Download and install Heartbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.install.windowsTextPre', { - defaultMessage: - 'First time using Heartbeat? See the [Getting Started Guide]({heartbeatLink}).\n\ - 1. Download the Heartbeat Windows zip file from the [Download]({elasticLink}) page.\n\ - 2. Extract the contents of the zip file into {folderPath}.\n\ - 3. Rename the {directoryName} directory to `Heartbeat`.\n\ - 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ -**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ - 5. From the PowerShell prompt, run the following commands to install Heartbeat as a Windows service.', - values: { - directoryName: '`heartbeat-{config.kibana.version}-windows`', - folderPath: '`C:\\Program Files`', - heartbeatLink: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html', - elasticLink: 'https://www.elastic.co/downloads/beats/heartbeat', - }, - }), - commands: ['cd "C:\\Program Files\\Heartbeat"', '.\\install-service-heartbeat.ps1'], - }, - }, - START: { - OSX: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.start.osxTitle', { - defaultMessage: 'Start Heartbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.start.osxTextPre', { - defaultMessage: 'The `setup` command loads the Kibana index pattern.', - }), - commands: ['./heartbeat setup', './heartbeat -e'], - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.start.debTitle', { - defaultMessage: 'Start Heartbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.start.debTextPre', { - defaultMessage: 'The `setup` command loads the Kibana index pattern.', - }), - commands: ['sudo heartbeat setup', 'sudo service heartbeat-elastic start'], - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.start.rpmTitle', { - defaultMessage: 'Start Heartbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.start.rpmTextPre', { - defaultMessage: 'The `setup` command loads the Kibana index pattern.', - }), - commands: ['sudo heartbeat setup', 'sudo service heartbeat-elastic start'], - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.start.windowsTitle', { - defaultMessage: 'Start Heartbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.start.windowsTextPre', { - defaultMessage: 'The `setup` command loads the Kibana index pattern.', - }), - commands: ['.\\heartbeat.exe setup', 'Start-Service heartbeat'], - }, - }, - CONFIG: { - OSX: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.osxTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`heartbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.osxTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.debTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.debTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`/etc/heartbeat/heartbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.debTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.rpmTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.rpmTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`/etc/heartbeat/heartbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.rpmTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatInstructions.config.windowsTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`C:\\Program Files\\Heartbeat\\heartbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate( - 'kbn.common.tutorials.heartbeatInstructions.config.windowsTextPost', - { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - } - ), - }, - }, -}); - -export const createHeartbeatCloudInstructions = () => ({ - CONFIG: { - OSX: { - title: i18n.translate('kbn.common.tutorials.heartbeatCloudInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatCloudInstructions.config.osxTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`heartbeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.heartbeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.heartbeatCloudInstructions.config.debTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatCloudInstructions.config.debTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`/etc/heartbeat/heartbeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.heartbeatCloudInstructions.config.debTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTextPre', { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`/etc/heartbeat/heartbeat.yml`', - }, - }), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`C:\\Program Files\\Heartbeat\\heartbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - }, -}); - -export function heartbeatEnableInstructionsOnPrem() { - const defaultTitle = i18n.translate( - 'kbn.common.tutorials.heartbeatEnableOnPremInstructions.defaultTitle', - { - defaultMessage: 'Edit the configuration - Add monitors', - } - ); - const defaultCommands = [ - 'heartbeat.monitors:', - '- type: http', - ' urls: [""]', - ' schedule: "@every 10s"', - ]; - const defaultTextPost = i18n.translate( - 'kbn.common.tutorials.heartbeatEnableOnPremInstructions.defaultTextPost', - { - defaultMessage: - 'Where {hostTemplate} is your monitored URL, For more details on how to configure Monitors in \ - Heartbeat, read the [Heartbeat configuration docs.]({configureLink})', - values: { - configureLink: '{config.docs.beats.heartbeat}/heartbeat-configuration.html', - hostTemplate: '``', - }, - } - ); - return { - OSX: { - title: defaultTitle, - textPre: i18n.translate('kbn.common.tutorials.heartbeatEnableOnPremInstructions.osxTextPre', { - defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', - }), - commands: defaultCommands, - textPost: defaultTextPost, - }, - DEB: { - title: defaultTitle, - textPre: i18n.translate('kbn.common.tutorials.heartbeatEnableOnPremInstructions.debTextPre', { - defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', - }), - commands: defaultCommands, - textPost: defaultTextPost, - }, - RPM: { - title: defaultTitle, - textPre: i18n.translate('kbn.common.tutorials.heartbeatEnableOnPremInstructions.rpmTextPre', { - defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', - }), - commands: defaultCommands, - textPost: defaultTextPost, - }, - WINDOWS: { - title: defaultTitle, - textPre: i18n.translate( - 'kbn.common.tutorials.heartbeatEnableOnPremInstructions.windowsTextPre', - { - defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', - } - ), - commands: defaultCommands, - textPost: defaultTextPost, - }, - }; -} - -export function heartbeatEnableInstructionsCloud() { - const defaultTitle = i18n.translate( - 'kbn.common.tutorials.heartbeatEnableCloudInstructions.defaultTitle', - { - defaultMessage: 'Edit the configuration - Add monitors', - } - ); - const defaultCommands = [ - 'heartbeat.monitors:', - '- type: http', - ' urls: ["http://elastic.co"]', - ' schedule: "@every 10s"', - ]; - const defaultTextPost = i18n.translate( - 'kbn.common.tutorials.heartbeatEnableCloudInstructions.defaultTextPost', - { - defaultMessage: - 'For more details on how to configure Monitors in Heartbeat, read the [Heartbeat configuration docs.]({configureLink})', - values: { configureLink: '{config.docs.beats.heartbeat}/heartbeat-configuration.html' }, - } - ); - return { - OSX: { - title: defaultTitle, - textPre: i18n.translate('kbn.common.tutorials.heartbeatEnableCloudInstructions.osxTextPre', { - defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', - }), - commands: defaultCommands, - textPost: defaultTextPost, - }, - DEB: { - title: defaultTitle, - textPre: i18n.translate('kbn.common.tutorials.heartbeatEnableCloudInstructions.debTextPre', { - defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', - }), - commands: defaultCommands, - textPost: defaultTextPost, - }, - RPM: { - title: defaultTitle, - textPre: i18n.translate('kbn.common.tutorials.heartbeatEnableCloudInstructions.rpmTextPre', { - defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', - }), - commands: defaultCommands, - textPost: defaultTextPost, - }, - WINDOWS: { - title: defaultTitle, - textPre: i18n.translate( - 'kbn.common.tutorials.heartbeatEnableCloudInstructions.windowsTextPre', - { - defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', - } - ), - commands: defaultCommands, - textPost: defaultTextPost, - }, - }; -} - -export function heartbeatStatusCheck() { - return { - title: i18n.translate('kbn.common.tutorials.heartbeatStatusCheck.title', { - defaultMessage: 'Heartbeat status', - }), - text: i18n.translate('kbn.common.tutorials.heartbeatStatusCheck.text', { - defaultMessage: 'Check that data is received from Heartbeat', - }), - btnLabel: i18n.translate('kbn.common.tutorials.heartbeatStatusCheck.buttonLabel', { - defaultMessage: 'Check data', - }), - success: i18n.translate('kbn.common.tutorials.heartbeatStatusCheck.successText', { - defaultMessage: 'Data successfully received from Heartbeat', - }), - error: i18n.translate('kbn.common.tutorials.heartbeatStatusCheck.errorText', { - defaultMessage: 'No data has been received from Heartbeat yet', - }), - esHitsCheck: { - index: 'heartbeat-*', - query: { - match_all: {}, - }, - }, - }; -} - -export function onPremInstructions(platforms, context) { - const HEARTBEAT_INSTRUCTIONS = createHeartbeatInstructions(context); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.heartbeat.premInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - HEARTBEAT_INSTRUCTIONS.INSTALL.OSX, - HEARTBEAT_INSTRUCTIONS.CONFIG.OSX, - heartbeatEnableInstructionsOnPrem().OSX, - HEARTBEAT_INSTRUCTIONS.START.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.DEB, - instructions: [ - HEARTBEAT_INSTRUCTIONS.INSTALL.DEB, - HEARTBEAT_INSTRUCTIONS.CONFIG.DEB, - heartbeatEnableInstructionsOnPrem().DEB, - HEARTBEAT_INSTRUCTIONS.START.DEB, - ], - }, - { - id: INSTRUCTION_VARIANT.RPM, - instructions: [ - HEARTBEAT_INSTRUCTIONS.INSTALL.RPM, - HEARTBEAT_INSTRUCTIONS.CONFIG.RPM, - heartbeatEnableInstructionsOnPrem().RPM, - HEARTBEAT_INSTRUCTIONS.START.RPM, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - HEARTBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - HEARTBEAT_INSTRUCTIONS.CONFIG.WINDOWS, - heartbeatEnableInstructionsOnPrem().WINDOWS, - HEARTBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: heartbeatStatusCheck(), - }, - ], - }; -} - -export function onPremCloudInstructions() { - const TRYCLOUD_OPTION1 = createTrycloudOption1(); - const TRYCLOUD_OPTION2 = createTrycloudOption2(); - const HEARTBEAT_INSTRUCTIONS = createHeartbeatInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.heartbeat.premCloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - HEARTBEAT_INSTRUCTIONS.INSTALL.OSX, - HEARTBEAT_INSTRUCTIONS.CONFIG.OSX, - heartbeatEnableInstructionsCloud().OSX, - HEARTBEAT_INSTRUCTIONS.START.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.DEB, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - HEARTBEAT_INSTRUCTIONS.INSTALL.DEB, - HEARTBEAT_INSTRUCTIONS.CONFIG.DEB, - heartbeatEnableInstructionsCloud().DEB, - HEARTBEAT_INSTRUCTIONS.START.DEB, - ], - }, - { - id: INSTRUCTION_VARIANT.RPM, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - HEARTBEAT_INSTRUCTIONS.INSTALL.RPM, - HEARTBEAT_INSTRUCTIONS.CONFIG.RPM, - heartbeatEnableInstructionsCloud().RPM, - HEARTBEAT_INSTRUCTIONS.START.RPM, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - HEARTBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - HEARTBEAT_INSTRUCTIONS.CONFIG.WINDOWS, - heartbeatEnableInstructionsCloud().WINDOWS, - HEARTBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: heartbeatStatusCheck(), - }, - ], - }; -} - -export function cloudInstructions() { - const HEARTBEAT_INSTRUCTIONS = createHeartbeatInstructions(); - const HEARTBEAT_CLOUD_INSTRUCTIONS = createHeartbeatCloudInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.heartbeat.cloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - HEARTBEAT_INSTRUCTIONS.INSTALL.OSX, - HEARTBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX, - heartbeatEnableInstructionsCloud().OSX, - HEARTBEAT_INSTRUCTIONS.START.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.DEB, - instructions: [ - HEARTBEAT_INSTRUCTIONS.INSTALL.DEB, - HEARTBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB, - heartbeatEnableInstructionsCloud().DEB, - HEARTBEAT_INSTRUCTIONS.START.DEB, - ], - }, - { - id: INSTRUCTION_VARIANT.RPM, - instructions: [ - HEARTBEAT_INSTRUCTIONS.INSTALL.RPM, - HEARTBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM, - heartbeatEnableInstructionsCloud().RPM, - HEARTBEAT_INSTRUCTIONS.START.RPM, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - HEARTBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - HEARTBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS, - heartbeatEnableInstructionsCloud().WINDOWS, - HEARTBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: heartbeatStatusCheck(), - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/common/tutorials/instruction_variant.js b/src/legacy/core_plugins/kibana/common/tutorials/instruction_variant.js deleted file mode 100644 index 0c3be210442419..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/instruction_variant.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export const INSTRUCTION_VARIANT = { - ESC: 'esc', - OSX: 'osx', - DEB: 'deb', - RPM: 'rpm', - DOCKER: 'docker', - WINDOWS: 'windows', - NODE: 'node', - DJANGO: 'django', - FLASK: 'flask', - RAILS: 'rails', - RACK: 'rack', - JS: 'js', - GO: 'go', - JAVA: 'java', - DOTNET: 'dotnet', - LINUX: 'linux', -}; - -const DISPLAY_MAP = { - [INSTRUCTION_VARIANT.ESC]: 'Elastic Cloud', - [INSTRUCTION_VARIANT.OSX]: 'macOS', - [INSTRUCTION_VARIANT.DEB]: 'DEB', - [INSTRUCTION_VARIANT.RPM]: 'RPM', - [INSTRUCTION_VARIANT.DOCKER]: 'Docker', - [INSTRUCTION_VARIANT.WINDOWS]: 'Windows', - [INSTRUCTION_VARIANT.NODE]: 'Node.js', - [INSTRUCTION_VARIANT.DJANGO]: 'Django', - [INSTRUCTION_VARIANT.FLASK]: 'Flask', - [INSTRUCTION_VARIANT.RAILS]: 'Ruby on Rails', - [INSTRUCTION_VARIANT.RACK]: 'Rack', - [INSTRUCTION_VARIANT.JS]: 'RUM (JS)', - [INSTRUCTION_VARIANT.GO]: 'Go', - [INSTRUCTION_VARIANT.JAVA]: 'Java', - [INSTRUCTION_VARIANT.DOTNET]: '.NET', - [INSTRUCTION_VARIANT.LINUX]: 'Linux', -}; - -/** - * Convert instruction variant id into display text. - * - * @params {String} id - instruction variant id as defined from INSTRUCTION_VARIANT - * @return {String} display name - */ -export function getDisplayText(id) { - if (id in DISPLAY_MAP) { - return DISPLAY_MAP[id]; - } - return id; -} diff --git a/src/legacy/core_plugins/kibana/common/tutorials/logstash_instructions.js b/src/legacy/core_plugins/kibana/common/tutorials/logstash_instructions.js deleted file mode 100644 index 9e25402abe1832..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/logstash_instructions.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -export const createLogstashInstructions = () => ({ - INSTALL: { - OSX: [ - { - title: i18n.translate('kbn.common.tutorials.logstashInstructions.install.java.osxTitle', { - defaultMessage: 'Download and install the Java Runtime Environment', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.logstashInstructions.install.java.osxTextPre', - { - defaultMessage: 'Follow the installation instructions [here]({link}).', - values: { - link: 'https://docs.oracle.com/javase/8/docs/technotes/guides/install/mac_jre.html', - }, - } - ), - }, - { - title: i18n.translate( - 'kbn.common.tutorials.logstashInstructions.install.logstash.osxTitle', - { - defaultMessage: 'Download and install Logstash', - } - ), - textPre: i18n.translate( - 'kbn.common.tutorials.logstashInstructions.install.logstash.osxTextPre', - { - defaultMessage: 'First time using Logstash? See the [Getting Started Guide]({link}).', - values: { - link: - '{config.docs.base_url}guide/en/logstash/current/getting-started-with-logstash.html', - }, - } - ), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/logstash/logstash-{config.kibana.version}.tar.gz', - 'tar xzvf logstash-{config.kibana.version}.tar.gz', - ], - }, - ], - WINDOWS: [ - { - title: i18n.translate( - 'kbn.common.tutorials.logstashInstructions.install.java.windowsTitle', - { - defaultMessage: 'Download and install the Java Runtime Environment', - } - ), - textPre: i18n.translate( - 'kbn.common.tutorials.logstashInstructions.install.java.windowsTextPre', - { - defaultMessage: 'Follow the installation instructions [here]({link}).', - values: { - link: - 'https://docs.oracle.com/javase/8/docs/technotes/guides/install/windows_jre_install.html', - }, - } - ), - }, - { - title: i18n.translate( - 'kbn.common.tutorials.logstashInstructions.install.logstash.windowsTitle', - { - defaultMessage: 'Download and install Logstash', - } - ), - textPre: i18n.translate( - 'kbn.common.tutorials.logstashInstructions.install.logstash.windowsTextPre', - { - defaultMessage: - 'First time using Logstash? See the [Getting Started Guide]({logstashLink}).\n\ - 1. [Download]({elasticLink}) the Logstash Windows zip file.\n\ - 2. Extract the contents of the zip file.', - values: { - logstashLink: - '{config.docs.base_url}guide/en/logstash/current/getting-started-with-logstash.html', - elasticLink: - 'https://artifacts.elastic.co/downloads/logstash/logstash-{config.kibana.version}.zip', - }, - } - ), - }, - ], - }, -}); diff --git a/src/legacy/core_plugins/kibana/common/tutorials/metricbeat_instructions.js b/src/legacy/core_plugins/kibana/common/tutorials/metricbeat_instructions.js deleted file mode 100644 index b7b1bec851e948..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/metricbeat_instructions.js +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { INSTRUCTION_VARIANT } from './instruction_variant'; -import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; -import { getSpaceIdForBeatsTutorial } from '../lib/get_space_id_for_beats_tutorial'; - -export const createMetricbeatInstructions = context => ({ - INSTALL: { - OSX: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.osxTitle', { - defaultMessage: 'Download and install Metricbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.osxTextPre', { - defaultMessage: 'First time using Metricbeat? See the [Getting Started Guide]({link}).', - values: { link: '{config.docs.beats.metricbeat}/metricbeat-getting-started.html' }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'tar xzvf metricbeat-{config.kibana.version}-darwin-x86_64.tar.gz', - 'cd metricbeat-{config.kibana.version}-darwin-x86_64/', - ], - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.debTitle', { - defaultMessage: 'Download and install Metricbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.debTextPre', { - defaultMessage: 'First time using Metricbeat? See the [Getting Started Guide]({link}).', - values: { link: '{config.docs.beats.metricbeat}/metricbeat-getting-started.html' }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-amd64.deb', - 'sudo dpkg -i metricbeat-{config.kibana.version}-amd64.deb', - ], - textPost: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.debTextPost', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({link}).', - values: { link: 'https://www.elastic.co/downloads/beats/metricbeat' }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.rpmTitle', { - defaultMessage: 'Download and install Metricbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.rpmTextPre', { - defaultMessage: 'First time using Metricbeat? See the [Getting Started Guide]({link}).', - values: { link: '{config.docs.beats.metricbeat}/metricbeat-getting-started.html' }, - }), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-x86_64.rpm', - 'sudo rpm -vi metricbeat-{config.kibana.version}-x86_64.rpm', - ], - textPost: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.debTextPost', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({link}).', - values: { link: 'https://www.elastic.co/downloads/beats/metricbeat' }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.install.windowsTitle', { - defaultMessage: 'Download and install Metricbeat', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.metricbeatInstructions.install.windowsTextPre', - { - defaultMessage: - 'First time using Metricbeat? See the [Getting Started Guide]({metricbeatLink}).\n\ - 1. Download the Metricbeat Windows zip file from the [Download]({elasticLink}) page.\n\ - 2. Extract the contents of the zip file into {folderPath}.\n\ - 3. Rename the {directoryName} directory to `Metricbeat`.\n\ - 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ -**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ - 5. From the PowerShell prompt, run the following commands to install Metricbeat as a Windows service.', - values: { - directoryName: '`metricbeat-{config.kibana.version}-windows`', - folderPath: '`C:\\Program Files`', - metricbeatLink: '{config.docs.beats.metricbeat}/metricbeat-getting-started.html', - elasticLink: 'https://www.elastic.co/downloads/beats/metricbeat', - }, - } - ), - commands: ['cd "C:\\Program Files\\Metricbeat"', '.\\install-service-metricbeat.ps1'], - textPost: i18n.translate( - 'kbn.common.tutorials.metricbeatInstructions.install.windowsTextPost', - { - defaultMessage: - 'Modify the settings under `output.elasticsearch` in the {path} file to point to your Elasticsearch installation.', - values: { path: '`C:\\Program Files\\Metricbeat\\metricbeat.yml`' }, - } - ), - }, - }, - START: { - OSX: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.start.osxTitle', { - defaultMessage: 'Start Metricbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.start.osxTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['./metricbeat setup', './metricbeat -e'], - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.start.debTitle', { - defaultMessage: 'Start Metricbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.start.debTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['sudo metricbeat setup', 'sudo service metricbeat start'], - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.start.rpmTitle', { - defaultMessage: 'Start Metricbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.start.rpmTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['sudo metricbeat setup', 'sudo service metricbeat start'], - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.start.windowsTitle', { - defaultMessage: 'Start Metricbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.start.windowsTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['.\\metricbeat.exe setup', 'Start-Service metricbeat'], - }, - }, - CONFIG: { - OSX: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.osxTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`metricbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.osxTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.debTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.debTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`/etc/metricbeat/metricbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.debTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.rpmTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.rpmTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`/etc/metricbeat/metricbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.rpmTextPost', { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatInstructions.config.windowsTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`C:\\Program Files\\Metricbeat\\metricbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate( - 'kbn.common.tutorials.metricbeatInstructions.config.windowsTextPost', - { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - } - ), - }, - }, -}); - -export const createMetricbeatCloudInstructions = () => ({ - CONFIG: { - OSX: { - title: i18n.translate('kbn.common.tutorials.metricbeatCloudInstructions.config.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.osxTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`metricbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.metricbeatCloudInstructions.config.debTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.debTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`/etc/metricbeat/metricbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.debTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`/etc/metricbeat/metricbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - WINDOWS: { - title: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`C:\\Program Files\\Metricbeat\\metricbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - }, -}); - -export function metricbeatEnableInstructions(moduleName) { - return { - OSX: { - title: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.osxTitle', { - defaultMessage: 'Enable and configure the {moduleName} module', - values: { moduleName }, - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.osxTextPre', { - defaultMessage: 'From the installation directory, run:', - }), - commands: ['./metricbeat modules enable ' + moduleName], - textPost: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.osxTextPost', { - defaultMessage: 'Modify the settings in the `modules.d/{moduleName}.yml` file.', - values: { moduleName }, - }), - }, - DEB: { - title: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.debTitle', { - defaultMessage: 'Enable and configure the {moduleName} module', - values: { moduleName }, - }), - commands: ['sudo metricbeat modules enable ' + moduleName], - textPost: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.debTextPost', { - defaultMessage: - 'Modify the settings in the `/etc/metricbeat/modules.d/{moduleName}.yml` file.', - values: { moduleName }, - }), - }, - RPM: { - title: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.rpmTitle', { - defaultMessage: 'Enable and configure the {moduleName} module', - values: { moduleName }, - }), - commands: ['sudo metricbeat modules enable ' + moduleName], - textPost: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.rpmTextPost', { - defaultMessage: - 'Modify the settings in the `/etc/metricbeat/modules.d/{moduleName}.yml` file.', - values: { moduleName }, - }), - }, - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.windowsTitle', { - defaultMessage: 'Enable and configure the {moduleName} module', - values: { moduleName }, - }), - textPre: i18n.translate('kbn.common.tutorials.metricbeatEnableInstructions.windowsTextPre', { - defaultMessage: 'From the {path} folder, run:', - values: { path: `C:\\Program Files\\Metricbeat` }, - }), - commands: ['.\\metricbeat.exe modules enable ' + moduleName], - textPost: i18n.translate( - 'kbn.common.tutorials.metricbeatEnableInstructions.windowsTextPost', - { - defaultMessage: 'Modify the settings in the `modules.d/{moduleName}.yml` file.', - values: { moduleName }, - } - ), - }, - }; -} - -export function metricbeatStatusCheck(moduleName) { - return { - title: i18n.translate('kbn.common.tutorials.metricbeatStatusCheck.title', { - defaultMessage: 'Module status', - }), - text: i18n.translate('kbn.common.tutorials.metricbeatStatusCheck.text', { - defaultMessage: 'Check that data is received from the Metricbeat `{moduleName}` module', - values: { moduleName }, - }), - btnLabel: i18n.translate('kbn.common.tutorials.metricbeatStatusCheck.buttonLabel', { - defaultMessage: 'Check data', - }), - success: i18n.translate('kbn.common.tutorials.metricbeatStatusCheck.successText', { - defaultMessage: 'Data successfully received from this module', - }), - error: i18n.translate('kbn.common.tutorials.metricbeatStatusCheck.errorText', { - defaultMessage: 'No data has been received from this module yet', - }), - esHitsCheck: { - index: 'metricbeat-*', - query: { - bool: { - filter: { - term: { - 'event.module': moduleName, - }, - }, - }, - }, - }, - }; -} - -export function onPremInstructions(moduleName, platforms, context) { - const METRICBEAT_INSTRUCTIONS = createMetricbeatInstructions(context); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.metricbeat.premInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - METRICBEAT_INSTRUCTIONS.INSTALL.OSX, - METRICBEAT_INSTRUCTIONS.CONFIG.OSX, - metricbeatEnableInstructions(moduleName).OSX, - METRICBEAT_INSTRUCTIONS.START.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.DEB, - instructions: [ - METRICBEAT_INSTRUCTIONS.INSTALL.DEB, - METRICBEAT_INSTRUCTIONS.CONFIG.DEB, - metricbeatEnableInstructions(moduleName).DEB, - METRICBEAT_INSTRUCTIONS.START.DEB, - ], - }, - { - id: INSTRUCTION_VARIANT.RPM, - instructions: [ - METRICBEAT_INSTRUCTIONS.INSTALL.RPM, - METRICBEAT_INSTRUCTIONS.CONFIG.RPM, - metricbeatEnableInstructions(moduleName).RPM, - METRICBEAT_INSTRUCTIONS.START.RPM, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS, - metricbeatEnableInstructions(moduleName).WINDOWS, - METRICBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: metricbeatStatusCheck(moduleName), - }, - ], - }; -} - -export function onPremCloudInstructions(moduleName) { - const TRYCLOUD_OPTION1 = createTrycloudOption1(); - const TRYCLOUD_OPTION2 = createTrycloudOption2(); - const METRICBEAT_INSTRUCTIONS = createMetricbeatInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.metricbeat.premCloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - METRICBEAT_INSTRUCTIONS.INSTALL.OSX, - METRICBEAT_INSTRUCTIONS.CONFIG.OSX, - metricbeatEnableInstructions(moduleName).OSX, - METRICBEAT_INSTRUCTIONS.START.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.DEB, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - METRICBEAT_INSTRUCTIONS.INSTALL.DEB, - METRICBEAT_INSTRUCTIONS.CONFIG.DEB, - metricbeatEnableInstructions(moduleName).DEB, - METRICBEAT_INSTRUCTIONS.START.DEB, - ], - }, - { - id: INSTRUCTION_VARIANT.RPM, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - METRICBEAT_INSTRUCTIONS.INSTALL.RPM, - METRICBEAT_INSTRUCTIONS.CONFIG.RPM, - metricbeatEnableInstructions(moduleName).RPM, - METRICBEAT_INSTRUCTIONS.START.RPM, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS, - metricbeatEnableInstructions(moduleName).WINDOWS, - METRICBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: metricbeatStatusCheck(moduleName), - }, - ], - }; -} - -export function cloudInstructions(moduleName) { - const METRICBEAT_INSTRUCTIONS = createMetricbeatInstructions(); - const METRICBEAT_CLOUD_INSTRUCTIONS = createMetricbeatCloudInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.metricbeat.cloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - METRICBEAT_INSTRUCTIONS.INSTALL.OSX, - METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX, - metricbeatEnableInstructions(moduleName).OSX, - METRICBEAT_INSTRUCTIONS.START.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.DEB, - instructions: [ - METRICBEAT_INSTRUCTIONS.INSTALL.DEB, - METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB, - metricbeatEnableInstructions(moduleName).DEB, - METRICBEAT_INSTRUCTIONS.START.DEB, - ], - }, - { - id: INSTRUCTION_VARIANT.RPM, - instructions: [ - METRICBEAT_INSTRUCTIONS.INSTALL.RPM, - METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM, - metricbeatEnableInstructions(moduleName).RPM, - METRICBEAT_INSTRUCTIONS.START.RPM, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS, - metricbeatEnableInstructions(moduleName).WINDOWS, - METRICBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: metricbeatStatusCheck(moduleName), - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/common/tutorials/onprem_cloud_instructions.js b/src/legacy/core_plugins/kibana/common/tutorials/onprem_cloud_instructions.js deleted file mode 100644 index ec66d9037eaee4..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/onprem_cloud_instructions.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -export const createTrycloudOption1 = () => ({ - title: i18n.translate('kbn.common.tutorials.premCloudInstructions.option1.title', { - defaultMessage: 'Option 1: Try in Elastic Cloud', - }), - textPre: i18n.translate('kbn.common.tutorials.premCloudInstructions.option1.textPre', { - defaultMessage: - 'Go to [Elastic Cloud]({link}). Register if you \ -do not already have an account. Free 14-day trial available.\n\n\ -Log into the Elastic Cloud console\n\n\ -To create a cluster, in Elastic Cloud console:\n\ - 1. Select **Create Deployment** and specify the **Deployment Name**\n\ - 2. Modify the other deployment options as needed (or not, the defaults are great to get started)\n\ - 3. Click **Create Deployment**\n\ - 4. Wait until deployment creation completes\n\ - 5. Go to the new Cloud Kibana instance and follow the Kibana Home instructions', - values: { - link: 'https://www.elastic.co/cloud/as-a-service/signup?blade=kib', - }, - }), -}); - -export const createTrycloudOption2 = () => ({ - title: i18n.translate('kbn.common.tutorials.premCloudInstructions.option2.title', { - defaultMessage: 'Option 2: Connect local Kibana to a Cloud instance', - }), - textPre: i18n.translate('kbn.common.tutorials.premCloudInstructions.option2.textPre', { - defaultMessage: - 'If you are running this Kibana instance against a hosted Elasticsearch instance, \ -proceed with manual setup.\n\n\ -Save the **Elasticsearch** endpoint as {urlTemplate} and the cluster **Password** as {passwordTemplate} for your records', - values: { - urlTemplate: '``', - passwordTemplate: '``', - }, - }), -}); diff --git a/src/legacy/core_plugins/kibana/common/tutorials/tutorial_category.js b/src/legacy/core_plugins/kibana/common/tutorials/tutorial_category.js deleted file mode 100644 index 8ac4d2490c17fb..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/tutorial_category.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export const TUTORIAL_CATEGORY = { - LOGGING: 'logging', - SIEM: 'siem', - METRICS: 'metrics', - OTHER: 'other', -}; diff --git a/src/legacy/core_plugins/kibana/common/tutorials/tutorial_schema.js b/src/legacy/core_plugins/kibana/common/tutorials/tutorial_schema.js deleted file mode 100644 index 1d04e0d83fa31c..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/tutorial_schema.js +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Joi from 'joi'; -import { PARAM_TYPES } from './param_types'; -import { TUTORIAL_CATEGORY } from './tutorial_category'; - -const dashboardSchema = Joi.object({ - id: Joi.string().required(), // Dashboard saved object id - linkLabel: Joi.string().when('isOverview', { - is: true, - then: Joi.required(), - }), - // Is this an Overview / Entry Point dashboard? - isOverview: Joi.boolean().required(), -}); - -const artifactsSchema = Joi.object({ - // Fields present in Elasticsearch documents created by this product. - exportedFields: Joi.object({ - documentationUrl: Joi.string().required(), - }), - // Kibana dashboards created by this product. - dashboards: Joi.array() - .items(dashboardSchema) - .required(), - application: Joi.object({ - path: Joi.string().required(), - label: Joi.string().required(), - }), -}); - -const statusCheckSchema = Joi.object({ - title: Joi.string(), - text: Joi.string(), - btnLabel: Joi.string(), - success: Joi.string(), - error: Joi.string(), - esHitsCheck: Joi.object({ - index: Joi.alternatives() - .try(Joi.string(), Joi.array().items(Joi.string())) - .required(), - query: Joi.object().required(), - }).required(), -}); - -const instructionSchema = Joi.object({ - title: Joi.string(), - textPre: Joi.string(), - commands: Joi.array().items(Joi.string().allow('')), - textPost: Joi.string(), -}); - -const instructionVariantSchema = Joi.object({ - id: Joi.string().required(), - instructions: Joi.array() - .items(instructionSchema) - .required(), -}); - -const instructionSetSchema = Joi.object({ - title: Joi.string(), - callOut: Joi.object({ - title: Joi.string().required(), - message: Joi.string(), - iconType: Joi.string(), - }), - // Variants (OSes, languages, etc.) for which tutorial instructions are specified. - instructionVariants: Joi.array() - .items(instructionVariantSchema) - .required(), - statusCheck: statusCheckSchema, -}); - -const paramSchema = Joi.object({ - defaultValue: Joi.required(), - id: Joi.string() - .regex(/^[a-zA-Z_]+$/) - .required(), - label: Joi.string().required(), - type: Joi.string() - .valid(Object.values(PARAM_TYPES)) - .required(), -}); - -const instructionsSchema = Joi.object({ - instructionSets: Joi.array() - .items(instructionSetSchema) - .required(), - params: Joi.array().items(paramSchema), -}); - -export const tutorialSchema = { - id: Joi.string() - .regex(/^[a-zA-Z0-9-]+$/) - .required(), - category: Joi.string() - .valid(Object.values(TUTORIAL_CATEGORY)) - .required(), - name: Joi.string().required(), - isBeta: Joi.boolean().default(false), - shortDescription: Joi.string().required(), - euiIconType: Joi.string(), //EUI icon type string, one of https://elastic.github.io/eui/#/icons - longDescription: Joi.string().required(), - completionTimeMinutes: Joi.number().integer(), - previewImagePath: Joi.string(), - - // kibana and elastic cluster running on prem - onPrem: instructionsSchema.required(), - - // kibana and elastic cluster running in elastic's cloud - elasticCloud: instructionsSchema, - - // kibana running on prem and elastic cluster running in elastic's cloud - onPremElasticCloud: instructionsSchema, - - // Elastic stack artifacts produced by product when it is setup and run. - artifacts: artifactsSchema, - - // saved objects used by data module. - savedObjects: Joi.array().items(), - savedObjectsInstallMsg: Joi.string(), -}; diff --git a/src/legacy/core_plugins/kibana/common/tutorials/winlogbeat_instructions.js b/src/legacy/core_plugins/kibana/common/tutorials/winlogbeat_instructions.js deleted file mode 100644 index 509ab0e6aba2de..00000000000000 --- a/src/legacy/core_plugins/kibana/common/tutorials/winlogbeat_instructions.js +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { INSTRUCTION_VARIANT } from './instruction_variant'; -import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; -import { getSpaceIdForBeatsTutorial } from '../lib/get_space_id_for_beats_tutorial'; - -export const createWinlogbeatInstructions = context => ({ - INSTALL: { - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.winlogbeatInstructions.install.windowsTitle', { - defaultMessage: 'Download and install Winlogbeat', - }), - textPre: i18n.translate( - 'kbn.common.tutorials.winlogbeatInstructions.install.windowsTextPre', - { - defaultMessage: - 'First time using Winlogbeat? See the [Getting Started Guide]({winlogbeatLink}).\n\ - 1. Download the Winlogbeat Windows zip file from the [Download]({elasticLink}) page.\n\ - 2. Extract the contents of the zip file into {folderPath}.\n\ - 3. Rename the {directoryName} directory to `Winlogbeat`.\n\ - 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ -**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ - 5. From the PowerShell prompt, run the following commands to install Winlogbeat as a Windows service.', - values: { - directoryName: '`winlogbeat-{config.kibana.version}-windows`', - folderPath: '`C:\\Program Files`', - winlogbeatLink: '{config.docs.beats.winlogbeat}/winlogbeat-getting-started.html', - elasticLink: 'https://www.elastic.co/downloads/beats/winlogbeat', - }, - } - ), - commands: ['cd "C:\\Program Files\\Winlogbeat"', '.\\install-service-winlogbeat.ps1'], - textPost: i18n.translate( - 'kbn.common.tutorials.winlogbeatInstructions.install.windowsTextPost', - { - defaultMessage: - 'Modify the settings under `output.elasticsearch` in the {path} file to point to your Elasticsearch installation.', - values: { path: '`C:\\Program Files\\Winlogbeat\\winlogbeat.yml`' }, - } - ), - }, - }, - START: { - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.winlogbeatInstructions.start.windowsTitle', { - defaultMessage: 'Start Winlogbeat', - }), - textPre: i18n.translate('kbn.common.tutorials.winlogbeatInstructions.start.windowsTextPre', { - defaultMessage: - 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', - }), - commands: ['.\\winlogbeat.exe setup', 'Start-Service winlogbeat'], - }, - }, - CONFIG: { - WINDOWS: { - title: i18n.translate('kbn.common.tutorials.winlogbeatInstructions.config.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.common.tutorials.winlogbeatInstructions.config.windowsTextPre', { - defaultMessage: 'Modify {path} to set the connection information:', - values: { - path: '`C:\\Program Files\\Winlogbeat\\winlogbeat.yml`', - }, - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: "elastic"', - ' password: ""', - 'setup.kibana:', - ' host: ""', - getSpaceIdForBeatsTutorial(context), - ], - textPost: i18n.translate( - 'kbn.common.tutorials.winlogbeatInstructions.config.windowsTextPost', - { - defaultMessage: - 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ -and {kibanaUrlTemplate} is the URL of Kibana.', - values: { - passwordTemplate: '``', - esUrlTemplate: '``', - kibanaUrlTemplate: '``', - }, - } - ), - }, - }, -}); - -export const createWinlogbeatCloudInstructions = () => ({ - CONFIG: { - WINDOWS: { - title: i18n.translate( - 'kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTextPre', - { - defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', - values: { - path: '`C:\\Program Files\\Winlogbeat\\winlogbeat.yml`', - }, - } - ), - commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), - }, - }, -}); - -export function winlogbeatStatusCheck() { - return { - title: i18n.translate('kbn.common.tutorials.winlogbeatStatusCheck.title', { - defaultMessage: 'Module status', - }), - text: i18n.translate('kbn.common.tutorials.winlogbeatStatusCheck.text', { - defaultMessage: 'Check that data is received from Winlogbeat', - }), - btnLabel: i18n.translate('kbn.common.tutorials.winlogbeatStatusCheck.buttonLabel', { - defaultMessage: 'Check data', - }), - success: i18n.translate('kbn.common.tutorials.winlogbeatStatusCheck.successText', { - defaultMessage: 'Data successfully received', - }), - error: i18n.translate('kbn.common.tutorials.winlogbeatStatusCheck.errorText', { - defaultMessage: 'No data has been received yet', - }), - esHitsCheck: { - index: 'winlogbeat-*', - query: { - bool: { - filter: { - term: { - 'agent.type': 'winlogbeat', - }, - }, - }, - }, - }, - }; -} - -export function onPremInstructions(platforms, context) { - const WINLOGBEAT_INSTRUCTIONS = createWinlogbeatInstructions(context); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.winlogbeat.premInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - WINLOGBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - WINLOGBEAT_INSTRUCTIONS.CONFIG.WINDOWS, - WINLOGBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: winlogbeatStatusCheck(), - }, - ], - }; -} - -export function onPremCloudInstructions() { - const TRYCLOUD_OPTION1 = createTrycloudOption1(); - const TRYCLOUD_OPTION2 = createTrycloudOption2(); - const WINLOGBEAT_INSTRUCTIONS = createWinlogbeatInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.winlogbeat.premCloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - WINLOGBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - WINLOGBEAT_INSTRUCTIONS.CONFIG.WINDOWS, - WINLOGBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: winlogbeatStatusCheck(), - }, - ], - }; -} - -export function cloudInstructions() { - const WINLOGBEAT_INSTRUCTIONS = createWinlogbeatInstructions(); - const WINLOGBEAT_CLOUD_INSTRUCTIONS = createWinlogbeatCloudInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate( - 'kbn.common.tutorials.winlogbeat.cloudInstructions.gettingStarted.title', - { - defaultMessage: 'Getting Started', - } - ), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - WINLOGBEAT_INSTRUCTIONS.INSTALL.WINDOWS, - WINLOGBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS, - WINLOGBEAT_INSTRUCTIONS.START.WINDOWS, - ], - }, - ], - statusCheck: winlogbeatStatusCheck(), - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index e6a0420534ef25..8e0497732e2305 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -24,16 +24,14 @@ import { promisify } from 'util'; import { migrations } from './migrations'; import { importApi } from './server/routes/api/import'; import { exportApi } from './server/routes/api/export'; -import { homeApi } from './server/routes/api/home'; import { managementApi } from './server/routes/api/management'; -import { registerFieldFormats } from './server/field_formats/register'; -import { registerTutorials } from './server/tutorials/register'; import * as systemApi from './server/lib/system_api'; import mappings from './mappings.json'; import { getUiSettingDefaults } from './ui_setting_defaults'; import { registerCspCollector } from './server/lib/csp_usage_collector'; import { injectVars } from './inject_vars'; import { i18n } from '@kbn/i18n'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; const mkdirAsync = promisify(Fs.mkdir); @@ -60,8 +58,12 @@ export default function(kibana) { }, uiExports: { - hacks: ['plugins/kibana/discover', 'plugins/kibana/dev_tools', 'plugins/kibana/visualize'], - savedObjectTypes: ['plugins/kibana/dashboard/saved_dashboard/saved_dashboard_register'], + hacks: [ + 'plugins/kibana/discover/legacy', + 'plugins/kibana/dev_tools', + 'plugins/kibana/visualize/legacy', + 'plugins/kibana/dashboard/legacy', + ], app: { id: 'kibana', title: 'Kibana', @@ -78,6 +80,7 @@ export default function(kibana) { order: -1003, url: `${kbnBaseUrl}#/discover`, euiIconType: 'discoverApp', + category: DEFAULT_APP_CATEGORIES.analyze, }, { id: 'kibana:visualize', @@ -87,6 +90,7 @@ export default function(kibana) { order: -1002, url: `${kbnBaseUrl}#/visualize`, euiIconType: 'visualizeApp', + category: DEFAULT_APP_CATEGORIES.analyze, }, { id: 'kibana:dashboard', @@ -102,6 +106,7 @@ export default function(kibana) { // to determine what url to use for the app link. subUrlBase: `${kbnBaseUrl}#/dashboard`, euiIconType: 'dashboardApp', + category: DEFAULT_APP_CATEGORIES.analyze, }, { id: 'kibana:dev_tools', @@ -111,16 +116,18 @@ export default function(kibana) { order: 9001, url: '/app/kibana#/dev_tools', euiIconType: 'devToolsApp', + category: DEFAULT_APP_CATEGORIES.management, }, { - id: 'kibana:management', + id: 'kibana:stack_management', title: i18n.translate('kbn.managementTitle', { - defaultMessage: 'Management', + defaultMessage: 'Stack Management', }), order: 9003, url: `${kbnBaseUrl}#/management`, euiIconType: 'managementApp', linkToLastSubUrl: false, + category: DEFAULT_APP_CATEGORIES.management, }, ], @@ -321,10 +328,7 @@ export default function(kibana) { // routes importApi(server); exportApi(server); - homeApi(server); managementApi(server); - registerFieldFormats(server); - registerTutorials(server); registerCspCollector(usageCollection, server); server.expose('systemApi', systemApi); server.injectUiAppVars('kibana', () => injectVars(server)); diff --git a/src/legacy/core_plugins/kibana/public/.eslintrc.js b/src/legacy/core_plugins/kibana/public/.eslintrc.js index 160adcc5b63f1b..9b45217287dc8c 100644 --- a/src/legacy/core_plugins/kibana/public/.eslintrc.js +++ b/src/legacy/core_plugins/kibana/public/.eslintrc.js @@ -51,6 +51,7 @@ function buildRestrictedPaths(shimmedPlugins) { from: [ `src/legacy/core_plugins/kibana/public/${shimmedPlugin}/**/*`, `!src/legacy/core_plugins/kibana/public/${shimmedPlugin}/index.ts`, + `!src/legacy/core_plugins/kibana/public/${shimmedPlugin}/legacy.ts`, ], allowSameFolder: false, errorMessage: `kibana/public/${shimmedPlugin} is behaving like a NP plugin and does not allow deep imports. If you need something from within ${shimmedPlugin} in another plugin, consider re-exporting it from the top level index module`, diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_app_state_mock.ts b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_app_state_mock.ts deleted file mode 100644 index d9dea35a8a1c03..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_app_state_mock.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { AppStateClass } from '../legacy_imports'; - -/** - * A poor excuse for a mock just to get some basic tests to run in jest without requiring the injector. - * This could be improved if we extract the appState and state classes externally of their angular providers. - * @return {AppStateMock} - */ -export function getAppStateMock(): AppStateClass { - class AppStateMock { - constructor(defaults: any) { - Object.assign(this, defaults); - } - - on() {} - off() {} - toJSON() { - return ''; - } - save() {} - translateHashToRison(stateHashOrRison: string | string[]) { - return stateHashOrRison; - } - getQueryParamName() { - return ''; - } - } - - return AppStateMock; -} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_saved_dashboard_mock.ts b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_saved_dashboard_mock.ts index 1c2405b5824f23..baf5bad510ce19 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_saved_dashboard_mock.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/get_saved_dashboard_mock.ts @@ -17,7 +17,8 @@ * under the License. */ -import { searchSourceMock } from 'ui/courier/search_source/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { searchSourceMock } from '../../../../../../plugins/data/public/search/search_source/mocks'; import { SavedObjectDashboard } from '../saved_dashboard/saved_dashboard'; export function getSavedDashboardMock( diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/index.ts b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/index.ts index ab8dfe81163e48..2b992f95695f38 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/index.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/index.ts @@ -17,6 +17,5 @@ * under the License. */ -export { getAppStateMock } from './get_app_state_mock'; export { getSavedDashboardMock } from './get_saved_dashboard_mock'; export { getEmbeddableFactoryMock } from './get_embeddable_factories_mock'; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/saved_dashboards.js b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/saved_dashboards.js deleted file mode 100644 index b387467189385e..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/saved_dashboards.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; - -describe('SavedDashboards Service', function() { - let savedDashboardLoader; - - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(savedDashboards) { - savedDashboardLoader = savedDashboards; - }) - ); - - it('delete returns a native promise', function() { - expect(savedDashboardLoader.delete(['1', '2'])).to.be.a(Promise); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/index.ts b/src/legacy/core_plugins/kibana/public/dashboard/index.ts index fd39f28a7673a1..d0157882689d39 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/index.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/index.ts @@ -17,40 +17,13 @@ * under the License. */ -import { npSetup, npStart, legacyChrome } from './legacy_imports'; -import { DashboardPlugin, LegacyAngularInjectedDependencies } from './plugin'; -import { start as data } from '../../../data/public/legacy'; -import { start as embeddables } from '../../../embeddable_api/public/np_ready/public/legacy'; -import './saved_dashboard/saved_dashboard_register'; -import './dashboard_config'; +import { PluginInitializerContext } from 'kibana/public'; +import { DashboardPlugin } from './plugin'; export * from './np_ready/dashboard_constants'; +export { createSavedDashboardLoader } from './saved_dashboard/saved_dashboards'; -/** - * Get dependencies relying on the global angular context. - * They also have to get resolved together with the legacy imports above - */ -async function getAngularDependencies(): Promise { - const injector = await legacyChrome.dangerouslyGetActiveInjector(); - - return { - dashboardConfig: injector.get('dashboardConfig'), - }; -} - -(async () => { - const instance = new DashboardPlugin(); - instance.setup(npSetup.core, { - ...npSetup.plugins, - __LEGACY: { - getAngularDependencies, - }, - }); - instance.start(npStart.core, { - ...npStart.plugins, - data, - npData: npStart.plugins.data, - embeddables, - navigation: npStart.plugins.navigation, - }); -})(); +// Core will be looking for this when loading our plugin in the new platform +export const plugin = (context: PluginInitializerContext) => { + return new DashboardPlugin(); +}; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy.ts new file mode 100644 index 00000000000000..acbc4c4b6c47ff --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy.ts @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PluginInitializerContext } from 'kibana/public'; +import { npSetup, npStart, legacyChrome } from './legacy_imports'; +import { LegacyAngularInjectedDependencies } from './plugin'; +import { start as data } from '../../../data/public/legacy'; +import { start as embeddables } from '../../../embeddable_api/public/np_ready/public/legacy'; +import './dashboard_config'; +import { plugin } from './index'; + +/** + * Get dependencies relying on the global angular context. + * They also have to get resolved together with the legacy imports above + */ +async function getAngularDependencies(): Promise { + const injector = await legacyChrome.dangerouslyGetActiveInjector(); + + return { + dashboardConfig: injector.get('dashboardConfig'), + }; +} + +(async () => { + const instance = plugin({} as PluginInitializerContext); + instance.setup(npSetup.core, { + ...npSetup.plugins, + __LEGACY: { + getAngularDependencies, + }, + }); + instance.start(npStart.core, { + ...npStart.plugins, + data, + npData: npStart.plugins.data, + embeddables, + navigation: npStart.plugins.navigation, + }); +})(); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts index b44d1993db23a4..97d165b6b5c23e 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts @@ -27,9 +27,6 @@ import chrome from 'ui/chrome'; export const legacyChrome = chrome; -export { State } from 'ui/state_management/state'; -export { AppState } from 'ui/state_management/app_state'; -export { AppStateClass } from 'ui/state_management/app_state'; export { SavedObjectSaveOpts } from 'ui/saved_objects/types'; export { npSetup, npStart } from 'ui/new_platform'; export { IPrivate } from 'ui/private'; @@ -45,8 +42,6 @@ export { GlobalStateProvider } from 'ui/state_management/global_state'; // @ts-ignore export { StateManagementConfigProvider } from 'ui/state_management/config_provider'; // @ts-ignore -export { AppStateProvider } from 'ui/state_management/app_state'; -// @ts-ignore export { PrivateProvider } from 'ui/private/private'; // @ts-ignore export { EventsProvider } from 'ui/events'; @@ -60,9 +55,7 @@ export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url/index'; // @ts-ignore export { confirmModalFactory } from 'ui/modals/confirm_modal'; export { configureAppAngularModule } from 'ui/legacy_compat'; -export { stateMonitorFactory, StateMonitor } from 'ui/state_management/state_monitor_factory'; export { ensureDefaultIndexPattern } from 'ui/legacy_compat'; -export { unhashUrl } from '../../../../../plugins/kibana_utils/public'; export { IInjector } from 'ui/chrome'; export { SavedObjectLoader } from 'ui/saved_objects'; export { VISUALIZE_EMBEDDABLE_TYPE } from '../../../visualizations/public/embeddable'; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts index 7f7bf7cf47bdaf..d9c05796380477 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts @@ -19,33 +19,31 @@ import { EuiConfirmModal, EuiIcon } from '@elastic/eui'; import angular, { IModule } from 'angular'; +import { History } from 'history'; import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; import { AppMountContext, ChromeStart, + IUiSettingsClient, LegacyCoreStart, SavedObjectsClientContract, - IUiSettingsClient, } from 'kibana/public'; -import { Storage } from '../../../../../../plugins/kibana_utils/public'; +import { IKbnUrlStateStorage, Storage } from '../../../../../../plugins/kibana_utils/public'; import { - GlobalStateProvider, - StateManagementConfigProvider, - AppStateProvider, - PrivateProvider, - EventsProvider, - PersistedState, + configureAppAngularModule, + confirmModalFactory, createTopNavDirective, createTopNavHelper, - PromiseServiceCreator, + EventsProvider, + IPrivate, KbnUrlProvider, + PersistedState, + PrivateProvider, + PromiseServiceCreator, RedirectWhenMissingProvider, - confirmModalFactory, - configureAppAngularModule, SavedObjectLoader, - IPrivate, + StateManagementConfigProvider, } from '../legacy_imports'; - // @ts-ignore import { initDashboardApp } from './legacy_app'; import { IEmbeddableStart } from '../../../../../../plugins/embeddable/public'; @@ -68,6 +66,8 @@ export interface RenderDeps { embeddables: IEmbeddableStart; localStorage: Storage; share: SharePluginStart; + history: History; + kbnUrlStateStorage: IKbnUrlStateStorage; } let angularModuleInstance: IModule | null = null; @@ -80,7 +80,9 @@ export const renderApp = (element: HTMLElement, appBasePath: string, deps: Rende // custom routing stuff initDashboardApp(angularModuleInstance, deps); } + const $injector = mountDashboardApp(appBasePath, element); + return () => { $injector.get('$rootScope').$destroy(); }; @@ -147,23 +149,13 @@ function createLocalConfirmModalModule() { } function createLocalStateModule() { - angular - .module('app/dashboard/State', [ - 'app/dashboard/Private', - 'app/dashboard/Config', - 'app/dashboard/KbnUrl', - 'app/dashboard/Promise', - 'app/dashboard/PersistedState', - ]) - .factory('AppState', function(Private: any) { - return Private(AppStateProvider); - }) - .service('getAppState', function(Private: any) { - return Private(AppStateProvider).getAppState; - }) - .service('globalState', function(Private: any) { - return Private(GlobalStateProvider); - }); + angular.module('app/dashboard/State', [ + 'app/dashboard/Private', + 'app/dashboard/Config', + 'app/dashboard/KbnUrl', + 'app/dashboard/Promise', + 'app/dashboard/PersistedState', + ]); } function createLocalPersistedStateModule() { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app.tsx b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app.tsx index e9fdc335ba5729..367db6644ff57b 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app.tsx @@ -20,12 +20,7 @@ import moment from 'moment'; import { Subscription } from 'rxjs'; -import { - AppStateClass as TAppStateClass, - AppState as TAppState, - IInjector, - KbnUrl, -} from '../legacy_imports'; +import { IInjector } from '../legacy_imports'; import { ViewMode } from '../../../../embeddable_api/public/np_ready/public'; import { SavedObjectDashboard } from '../saved_dashboard/saved_dashboard'; @@ -43,7 +38,7 @@ import { RenderDeps } from './application'; export interface DashboardAppScope extends ng.IScope { dash: SavedObjectDashboard; - appState: TAppState; + appState: DashboardAppState; screenTitle: string; model: { query: Query; @@ -60,7 +55,6 @@ export interface DashboardAppScope extends ng.IScope { refreshInterval: any; panels: SavedDashboardPanel[]; indexPatterns: IIndexPattern[]; - $evalAsync: any; dashboardViewMode: ViewMode; expandedPanel?: string; getShouldShowEditHelp: () => boolean; @@ -91,8 +85,6 @@ export interface DashboardAppScope extends ng.IScope { export function initDashboardAppDirective(app: any, deps: RenderDeps) { app.directive('dashboardApp', function($injector: IInjector) { - const AppState = $injector.get>('AppState'); - const kbnUrl = $injector.get('kbnUrl'); const confirmModal = $injector.get('confirmModal'); const config = deps.uiSettings; @@ -104,18 +96,12 @@ export function initDashboardAppDirective(app: any, deps: RenderDeps) { $route: any, $routeParams: { id?: string; - }, - getAppState: any, - globalState: any + } ) => new DashboardAppController({ $route, $scope, $routeParams, - getAppState, - globalState, - kbnUrl, - AppStateClass: AppState, config, confirmModal, indexPatterns: deps.npDataStart.indexPatterns, diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app_controller.tsx index 2706b588a2ec4f..e85054cd7fb34f 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app_controller.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_app_controller.tsx @@ -17,57 +17,56 @@ * under the License. */ -import _ from 'lodash'; +import _, { uniq } from 'lodash'; import { i18n } from '@kbn/i18n'; import React from 'react'; import angular from 'angular'; -import { uniq } from 'lodash'; import { Subscription } from 'rxjs'; +import { map } from 'rxjs/operators'; import { DashboardEmptyScreen, DashboardEmptyScreenProps } from './dashboard_empty_screen'; import { - subscribeWithScope, ConfirmationButtonTypes, - showSaveModal, - SaveResult, migrateLegacyQuery, - State, - AppStateClass as TAppStateClass, - KbnUrl, SavedObjectSaveOpts, - unhashUrl, + SaveResult, + showSaveModal, + subscribeWithScope, } from '../legacy_imports'; -import { FilterStateManager } from '../../../../data/public'; import { + COMPARE_ALL_OPTIONS, + compareFilters, IndexPattern, + IndexPatternsContract, Query, SavedQuery, - IndexPatternsContract, + syncAppFilters, + syncQuery, } from '../../../../../../plugins/data/public'; import { - DashboardContainer, DASHBOARD_CONTAINER_TYPE, + DashboardContainer, DashboardContainerFactory, DashboardContainerInput, DashboardPanelState, } from '../../../../dashboard_embeddable_container/public/np_ready/public'; import { - isErrorEmbeddable, + EmbeddableFactoryNotFoundError, ErrorEmbeddable, - ViewMode, + isErrorEmbeddable, openAddPanelFlyout, - EmbeddableFactoryNotFoundError, + ViewMode, } from '../../../../embeddable_api/public/np_ready/public'; -import { DashboardAppState, NavAction, ConfirmModalFn, SavedDashboardPanel } from './types'; +import { ConfirmModalFn, NavAction, SavedDashboardPanel } from './types'; import { showOptionsPopover } from './top_nav/show_options_popover'; import { DashboardSaveModal } from './top_nav/save_modal'; import { showCloneModal } from './top_nav/show_clone_modal'; import { saveDashboard } from './lib'; import { DashboardStateManager } from './dashboard_state_manager'; -import { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; +import { createDashboardEditUrl, DashboardConstants } from './dashboard_constants'; import { getTopNavConfig } from './top_nav/get_top_nav_config'; import { TopNavIds } from './top_nav/top_nav_ids'; import { getDashboardTitle } from './dashboard_strings'; @@ -78,17 +77,14 @@ import { SavedObjectFinderProps, SavedObjectFinderUi, } from '../../../../../../plugins/kibana_react/public'; +import { removeQueryParam, unhashUrl } from '../../../../../../plugins/kibana_utils/public'; export interface DashboardAppControllerDependencies extends RenderDeps { $scope: DashboardAppScope; $route: any; $routeParams: any; - getAppState: any; - globalState: State; indexPatterns: IndexPatternsContract; dashboardConfig: any; - kbnUrl: KbnUrl; - AppStateClass: TAppStateClass; config: any; confirmModal: ConfirmModalFn; } @@ -103,12 +99,8 @@ export class DashboardAppController { $scope, $route, $routeParams, - getAppState, - globalState, dashboardConfig, localStorage, - kbnUrl, - AppStateClass, indexPatterns, config, confirmModal, @@ -116,16 +108,21 @@ export class DashboardAppController { embeddables, share, dashboardCapabilities, - npDataStart: { - query: { - filterManager, - timefilter: { timefilter }, - }, - }, + npDataStart: { query: queryService }, core: { notifications, overlays, chrome, injectedMetadata, uiSettings, savedObjects, http }, + history, + kbnUrlStateStorage, }: DashboardAppControllerDependencies) { - new FilterStateManager(globalState, getAppState, filterManager); + const filterManager = queryService.filterManager; const queryFilter = filterManager; + const timefilter = queryService.timefilter.timefilter; + + // starts syncing `_g` portion of url with query services + // note: dashboard_state_manager.ts syncs `_a` portion of url + const { + stop: stopSyncingGlobalStateWithUrl, + hasInheritedQueryFromUrl: hasInheritedGlobalStateFromUrl, + } = syncQuery(queryService, kbnUrlStateStorage); let lastReloadRequestTime = 0; @@ -136,16 +133,21 @@ export class DashboardAppController { const dashboardStateManager = new DashboardStateManager({ savedDashboard: dash, - AppStateClass, hideWriteControls: dashboardConfig.getHideWriteControls(), kibanaVersion: injectedMetadata.getKibanaVersion(), + kbnUrlStateStorage, + history, }); - $scope.appState = dashboardStateManager.getAppState(); + const stopSyncingAppFilters = syncAppFilters(filterManager, { + set: filters => dashboardStateManager.setFilters(filters), + get: () => dashboardStateManager.appState.filters, + state$: dashboardStateManager.appState$.pipe(map(state => state.filters)), + }); // The hash check is so we only update the time filter on dashboard open, not during // normal cross app navigation. - if (dashboardStateManager.getIsTimeSavedWithDashboard() && !globalState.$inheritedGlobalState) { + if (dashboardStateManager.getIsTimeSavedWithDashboard() && !hasInheritedGlobalStateFromUrl) { dashboardStateManager.syncTimefilterWithDashboard(timefilter); } $scope.showSaveQuery = dashboardCapabilities.saveQuery as boolean; @@ -308,16 +310,22 @@ export class DashboardAppController { // This has to be first because handleDashboardContainerChanges causes // appState.save which will cause refreshDashboardContainer to be called. - // Add filters modifies the object passed to it, hence the clone deep. - if (!_.isEqual(container.getInput().filters, queryFilter.getFilters())) { + if ( + !compareFilters( + container.getInput().filters, + queryFilter.getFilters(), + COMPARE_ALL_OPTIONS + ) + ) { + // Add filters modifies the object passed to it, hence the clone deep. queryFilter.addFilters(_.cloneDeep(container.getInput().filters)); dashboardStateManager.applyFilters($scope.model.query, container.getInput().filters); dirty = true; } + dashboardStateManager.handleDashboardContainerChanges(container); $scope.$evalAsync(() => { - dashboardStateManager.handleDashboardContainerChanges(container); if (dirty) { updateState(); } @@ -337,8 +345,8 @@ export class DashboardAppController { const type = $routeParams[DashboardConstants.ADD_EMBEDDABLE_TYPE]; const id = $routeParams[DashboardConstants.ADD_EMBEDDABLE_ID]; container.addSavedObjectEmbeddable(type, id); - kbnUrl.removeParam(DashboardConstants.ADD_EMBEDDABLE_TYPE); - kbnUrl.removeParam(DashboardConstants.ADD_EMBEDDABLE_ID); + removeQueryParam(history, DashboardConstants.ADD_EMBEDDABLE_TYPE); + removeQueryParam(history, DashboardConstants.ADD_EMBEDDABLE_ID); } } @@ -403,7 +411,15 @@ export class DashboardAppController { const containerInput = dashboardContainer.getInput(); const differences: Partial = {}; - Object.keys(containerInput).forEach(key => { + + // Filters shouldn't be compared using regular isEqual + if ( + !compareFilters(containerInput.filters, appStateDashboardInput.filters, COMPARE_ALL_OPTIONS) + ) { + differences.filters = appStateDashboardInput.filters; + } + + Object.keys(_.omit(containerInput, 'filters')).forEach(key => { const containerValue = (containerInput as { [key: string]: unknown })[key]; const appStateValue = ((appStateDashboardInput as unknown) as { [key: string]: unknown })[ key @@ -413,7 +429,9 @@ export class DashboardAppController { } }); - return Object.values(differences).length === 0 ? undefined : differences; + // cloneDeep hack is needed, as there are multiple place, where container's input mutated, + // but values from appStateValue are deeply frozen, as they can't be mutated directly + return Object.values(differences).length === 0 ? undefined : _.cloneDeep(differences); }; const refreshDashboardContainer = () => { @@ -470,18 +488,21 @@ export class DashboardAppController { language: localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage'), }, - [] + queryFilter.getGlobalFilters() ); // Making this method sync broke the updates. // Temporary fix, until we fix the complex state in this file. - setTimeout(queryFilter.removeAll, 0); + setTimeout(() => { + queryFilter.setFilters(queryFilter.getGlobalFilters()); + }, 0); }; const updateStateFromSavedQuery = (savedQuery: SavedQuery) => { - dashboardStateManager.applyFilters( - savedQuery.attributes.query, - savedQuery.attributes.filters || [] - ); + const savedQueryFilters = savedQuery.attributes.filters || []; + const globalFilters = queryFilter.getGlobalFilters(); + const allFilters = [...globalFilters, ...savedQueryFilters]; + + dashboardStateManager.applyFilters(savedQuery.attributes.query, allFilters); if (savedQuery.attributes.timefilter) { timefilter.setTime({ from: savedQuery.attributes.timefilter.from, @@ -494,7 +515,7 @@ export class DashboardAppController { // Making this method sync broke the updates. // Temporary fix, until we fix the complex state in this file. setTimeout(() => { - queryFilter.setFilters(savedQuery.attributes.filters || []); + queryFilter.setFilters(allFilters); }, 0); }; @@ -560,11 +581,6 @@ export class DashboardAppController { ); function updateViewMode(newMode: ViewMode) { - $scope.topNavMenu = getTopNavConfig( - newMode, - navActions, - dashboardConfig.getHideWriteControls() - ); // eslint-disable-line no-use-before-define dashboardStateManager.switchViewMode(newMode); } @@ -580,17 +596,28 @@ export class DashboardAppController { function revertChangesAndExitEditMode() { dashboardStateManager.resetState(); - kbnUrl.change( - dash.id ? createDashboardEditUrl(dash.id) : DashboardConstants.CREATE_NEW_DASHBOARD_URL - ); // This is only necessary for new dashboards, which will default to Edit mode. updateViewMode(ViewMode.VIEW); + // Angular's $location skips this update because of history updates from syncState which happen simultaneously + // when calling kbnUrl.change() angular schedules url update and when angular finally starts to process it, + // the update is considered outdated and angular skips it + // so have to use implementation of dashboardStateManager.changeDashboardUrl, which workarounds those issues + dashboardStateManager.changeDashboardUrl( + dash.id ? createDashboardEditUrl(dash.id) : DashboardConstants.CREATE_NEW_DASHBOARD_URL + ); + // We need to do a hard reset of the timepicker. appState will not reload like // it does on 'open' because it's been saved to the url and the getAppState.previouslyStored() check on // reload will cause it not to sync. if (dashboardStateManager.getIsTimeSavedWithDashboard()) { - dashboardStateManager.syncTimefilterWithDashboard(timefilter); + // have to use $evalAsync here until '_g' is migrated from $location to state sync utility ('history') + // When state sync utility changes url, angular's $location is missing it's own updates which happen during the same digest cycle + // temporary solution is to delay $location updates to next digest cycle + // unfortunately, these causes 2 browser history entries, but this is temporary and will be fixed after migrating '_g' to state_sync utilities + $scope.$evalAsync(() => { + dashboardStateManager.syncTimefilterWithDashboard(timefilter); + }); } } @@ -642,7 +669,11 @@ export class DashboardAppController { }); if (dash.id !== $routeParams.id) { - kbnUrl.change(createDashboardEditUrl(dash.id)); + // Angular's $location skips this update because of history updates from syncState which happen simultaneously + // when calling kbnUrl.change() angular schedules url update and when angular finally starts to process it, + // the update is considered outdated and angular skips it + // so have to use implementation of dashboardStateManager.changeDashboardUrl, which workarounds those issues + dashboardStateManager.changeDashboardUrl(createDashboardEditUrl(dash.id)); } else { chrome.docTitle.change(dash.lastSavedTitle); updateViewMode(ViewMode.VIEW); @@ -844,8 +875,19 @@ export class DashboardAppController { }); }); + dashboardStateManager.registerChangeListener(() => { + // view mode could have changed, so trigger top nav update + $scope.topNavMenu = getTopNavConfig( + dashboardStateManager.getViewMode(), + navActions, + dashboardConfig.getHideWriteControls() + ); + }); + $scope.$on('$destroy', () => { updateSubscription.unsubscribe(); + stopSyncingGlobalStateWithUrl(); + stopSyncingAppFilters(); visibleSubscription.unsubscribe(); $scope.timefilterSubscriptions$.unsubscribe(); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state.test.ts index d9a93b2ceedc31..152cd84b7c38d5 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state.test.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state.test.ts @@ -18,16 +18,13 @@ */ import './np_core.test.mocks'; +import { createBrowserHistory } from 'history'; import { DashboardStateManager } from './dashboard_state_manager'; -import { getAppStateMock, getSavedDashboardMock } from '../__tests__'; -import { AppStateClass } from '../legacy_imports'; -import { DashboardAppState } from './types'; -import { TimeRange, TimefilterContract, InputTimeRange } from 'src/plugins/data/public'; +import { getSavedDashboardMock } from '../__tests__'; +import { InputTimeRange, TimefilterContract, TimeRange } from 'src/plugins/data/public'; import { ViewMode } from 'src/plugins/embeddable/public'; +import { createKbnUrlStateStorage } from 'src/plugins/kibana_utils/public'; -jest.mock('ui/state_management/state', () => ({ - State: {}, -})); jest.mock('ui/agg_types', () => ({ aggTypes: { metrics: [], @@ -52,9 +49,10 @@ describe('DashboardState', function() { function initDashboardState() { dashboardState = new DashboardStateManager({ savedDashboard, - AppStateClass: getAppStateMock() as AppStateClass, hideWriteControls: false, kibanaVersion: '7.0.0', + kbnUrlStateStorage: createKbnUrlStateStorage(), + history: createBrowserHistory(), }); } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state_manager.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state_manager.ts index 6df18757da6f51..987afd65bb67bf 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state_manager.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state_manager.ts @@ -19,20 +19,16 @@ import { i18n } from '@kbn/i18n'; import _ from 'lodash'; - +import { Observable, Subscription } from 'rxjs'; import { Moment } from 'moment'; +import { History } from 'history'; import { DashboardContainer } from 'src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public'; import { ViewMode } from '../../../../../../plugins/embeddable/public'; +import { migrateLegacyQuery } from '../legacy_imports'; import { - stateMonitorFactory, - StateMonitor, - AppStateClass as TAppStateClass, - migrateLegacyQuery, -} from '../legacy_imports'; -import { - Query, esFilters, + Query, TimefilterContract as Timefilter, } from '../../../../../../plugins/data/public'; @@ -41,7 +37,19 @@ import { convertPanelStateToSavedDashboardPanel } from './lib/embeddable_saved_o import { FilterUtils } from './lib/filter_utils'; import { SavedObjectDashboard } from '../saved_dashboard/saved_dashboard'; -import { SavedDashboardPanel, DashboardAppState, DashboardAppStateDefaults } from './types'; +import { + DashboardAppState, + DashboardAppStateDefaults, + DashboardAppStateTransitions, + SavedDashboardPanel, +} from './types'; +import { + createStateContainer, + IKbnUrlStateStorage, + ISyncStateRef, + ReduxLikeStateContainer, + syncState, +} from '../../../../../../plugins/kibana_utils/public'; /** * Dashboard state manager handles connecting angular and redux state between the angular and react portions of the @@ -51,7 +59,6 @@ import { SavedDashboardPanel, DashboardAppState, DashboardAppStateDefaults } fro */ export class DashboardStateManager { public savedDashboard: SavedObjectDashboard; - public appState: DashboardAppState; public lastSavedDashboardFilters: { timeTo?: string | Moment; timeFrom?: string | Moment; @@ -63,38 +70,82 @@ export class DashboardStateManager { private kibanaVersion: string; public isDirty: boolean; private changeListeners: Array<(status: { dirty: boolean }) => void>; - private stateMonitor: StateMonitor; + + public get appState(): DashboardAppState { + return this.stateContainer.get(); + } + + public get appState$(): Observable { + return this.stateContainer.state$; + } + + private readonly stateContainer: ReduxLikeStateContainer< + DashboardAppState, + DashboardAppStateTransitions + >; + private readonly stateContainerChangeSub: Subscription; + private readonly STATE_STORAGE_KEY = '_a'; + private readonly kbnUrlStateStorage: IKbnUrlStateStorage; + private readonly stateSyncRef: ISyncStateRef; + private readonly history: History; /** * * @param savedDashboard - * @param AppState The AppState class to use when instantiating a new AppState instance. * @param hideWriteControls true if write controls should be hidden. + * @param kibanaVersion current kibanaVersion + * @param */ constructor({ savedDashboard, - AppStateClass, hideWriteControls, kibanaVersion, + kbnUrlStateStorage, + history, }: { savedDashboard: SavedObjectDashboard; - AppStateClass: TAppStateClass; hideWriteControls: boolean; kibanaVersion: string; + kbnUrlStateStorage: IKbnUrlStateStorage; + history: History; }) { + this.history = history; this.kibanaVersion = kibanaVersion; this.savedDashboard = savedDashboard; this.hideWriteControls = hideWriteControls; - this.stateDefaults = getAppStateDefaults(this.savedDashboard, this.hideWriteControls); + // get state defaults from saved dashboard, make sure it is migrated + this.stateDefaults = migrateAppState( + getAppStateDefaults(this.savedDashboard, this.hideWriteControls), + kibanaVersion + ); - this.appState = new AppStateClass(this.stateDefaults); + this.kbnUrlStateStorage = kbnUrlStateStorage; - // Initializing appState does two things - first it translates the defaults into AppState, second it updates - // appState based on the URL (the url trumps the defaults). This means if we update the state format at all and - // want to handle BWC, we must not only migrate the data stored with saved Dashboard, but also any old state in the - // url. - migrateAppState(this.appState, kibanaVersion); + // setup initial state by merging defaults with state from url + // also run migration, as state in url could be of older version + const initialState = migrateAppState( + { + ...this.stateDefaults, + ...this.kbnUrlStateStorage.get(this.STATE_STORAGE_KEY), + }, + kibanaVersion + ); + + // setup state container using initial state both from defaults and from url + this.stateContainer = createStateContainer( + initialState, + { + set: state => (prop, value) => ({ ...state, [prop]: value }), + setOption: state => (option, value) => ({ + ...state, + options: { + ...state.options, + [option]: value, + }, + }), + } + ); this.isDirty = false; @@ -104,29 +155,35 @@ export class DashboardStateManager { // in the 'lose changes' warning message. this.lastSavedDashboardFilters = this.getFilterState(); - /** - * Creates a state monitor and saves it to this.stateMonitor. Used to track unsaved changes made to appState. - */ - this.stateMonitor = stateMonitorFactory.create( - this.appState, - this.stateDefaults - ); - - this.stateMonitor.ignoreProps('viewMode'); - // Filters need to be compared manually because they sometimes have a $$hashkey stored on the object. - this.stateMonitor.ignoreProps('filters'); - // Query needs to be compared manually because saved legacy queries get migrated in app state automatically - this.stateMonitor.ignoreProps('query'); + this.changeListeners = []; - this.stateMonitor.onChange((status: { dirty: boolean }) => { - this.isDirty = status.dirty; + this.stateContainerChangeSub = this.stateContainer.state$.subscribe(() => { + this.isDirty = this.checkIsDirty(); + this.changeListeners.forEach(listener => listener({ dirty: this.isDirty })); }); - this.changeListeners = []; - - this.stateMonitor.onChange((status: { dirty: boolean }) => { - this.changeListeners.forEach(listener => listener(status)); + // make sure url ('_a') matches initial state + this.kbnUrlStateStorage.set(this.STATE_STORAGE_KEY, initialState, { replace: true }); + + // setup state syncing utils. state container will be synched with url into `this.STATE_STORAGE_KEY` query param + this.stateSyncRef = syncState({ + storageKey: this.STATE_STORAGE_KEY, + stateContainer: { + ...this.stateContainer, + set: (state: DashboardAppState | null) => { + // sync state required state container to be able to handle null + // overriding set() so it could handle null coming from url + this.stateContainer.set({ + ...this.stateDefaults, + ...state, + }); + }, + }, + stateStorage: this.kbnUrlStateStorage, }); + + // actually start syncing state with container + this.stateSyncRef.start(); } public registerChangeListener(callback: (status: { dirty: boolean }) => void) { @@ -172,7 +229,7 @@ export class DashboardStateManager { }); if (dirty) { - this.appState.panels = Object.values(convertedPanelStateMap); + this.stateContainer.transitions.set('panels', Object.values(convertedPanelStateMap)); } if (input.isFullScreenMode !== this.getFullScreenMode()) { @@ -184,7 +241,6 @@ export class DashboardStateManager { } this.changeListeners.forEach(listener => listener({ dirty })); - this.saveState(); } public getFullScreenMode() { @@ -192,8 +248,11 @@ export class DashboardStateManager { } public setFullScreenMode(fullScreenMode: boolean) { - this.appState.fullScreenMode = fullScreenMode; - this.saveState(); + this.stateContainer.transitions.set('fullScreenMode', fullScreenMode); + } + + public setFilters(filters: esFilters.Filter[]) { + this.stateContainer.transitions.set('filters', filters); } /** @@ -210,7 +269,10 @@ export class DashboardStateManager { // The right way to fix this might be to ensure the defaults object stored on state is a deep // clone, but given how much code uses the state object, I determined that to be too risky of a change for // now. TODO: revisit this! - this.stateDefaults = getAppStateDefaults(this.savedDashboard, this.hideWriteControls); + this.stateDefaults = migrateAppState( + getAppStateDefaults(this.savedDashboard, this.hideWriteControls), + this.kibanaVersion + ); // The original query won't be restored by the above because the query on this.savedDashboard is applied // in place in order for it to affect the visualizations. this.stateDefaults.query = this.lastSavedDashboardFilters.query; @@ -218,9 +280,7 @@ export class DashboardStateManager { this.stateDefaults.filters = [...this.getLastSavedFilterBars()]; this.isDirty = false; - this.appState.setDefaults(this.stateDefaults); - this.appState.reset(); - this.stateMonitor.setInitialState(this.appState.toJSON()); + this.stateContainer.set(this.stateDefaults); } /** @@ -252,31 +312,28 @@ export class DashboardStateManager { } public setDescription(description: string) { - this.appState.description = description; - this.saveState(); + this.stateContainer.transitions.set('description', description); } public setTitle(title: string) { - this.appState.title = title; this.savedDashboard.title = title; - this.saveState(); + this.stateContainer.transitions.set('title', title); } public getAppState() { - return this.appState; + return this.stateContainer.get(); } public getQuery(): Query { - return migrateLegacyQuery(this.appState.query); + return migrateLegacyQuery(this.stateContainer.get().query); } public getSavedQueryId() { - return this.appState.savedQuery; + return this.stateContainer.get().savedQuery; } public setSavedQueryId(id?: string) { - this.appState.savedQuery = id; - this.saveState(); + this.stateContainer.transitions.set('savedQuery', id); } public getUseMargins() { @@ -287,8 +344,7 @@ export class DashboardStateManager { } public setUseMargins(useMargins: boolean) { - this.appState.options.useMargins = useMargins; - this.saveState(); + this.stateContainer.transitions.setOption('useMargins', useMargins); } public getHidePanelTitles() { @@ -296,8 +352,7 @@ export class DashboardStateManager { } public setHidePanelTitles(hidePanelTitles: boolean) { - this.appState.options.hidePanelTitles = hidePanelTitles; - this.saveState(); + this.stateContainer.transitions.setOption('hidePanelTitles', hidePanelTitles); } public getTimeRestore() { @@ -305,8 +360,7 @@ export class DashboardStateManager { } public setTimeRestore(timeRestore: boolean) { - this.appState.timeRestore = timeRestore; - this.saveState(); + this.stateContainer.transitions.set('timeRestore', timeRestore); } public getIsTimeSavedWithDashboard() { @@ -397,7 +451,6 @@ export class DashboardStateManager { (panel: SavedDashboardPanel) => panel.panelIndex === panelIndex ); Object.assign(foundPanel, panelAttributes); - this.saveState(); return foundPanel; } @@ -456,15 +509,37 @@ export class DashboardStateManager { } /** - * Saves the current application state to the URL. + * Synchronously writes current state to url + * returned boolean indicates whether the update happened and if history was updated */ - public saveState() { - this.appState.save(); + private saveState({ replace }: { replace: boolean }): boolean { + // schedules setting current state to url + this.kbnUrlStateStorage.set( + this.STATE_STORAGE_KEY, + this.stateContainer.get() + ); + // immediately forces scheduled updates and changes location + return this.kbnUrlStateStorage.flush({ replace }); + } + + // TODO: find nicer solution for this + // this function helps to make just 1 browser history update, when we imperatively changing the dashboard url + // It could be that there is pending *dashboardStateManager* updates, which aren't flushed yet to the url. + // So to prevent 2 browser updates: + // 1. Force flush any pending state updates (syncing state to query) + // 2. If url was updated, then apply path change with replace + public changeDashboardUrl(pathname: string) { + // synchronously persist current state to url with push() + const updated = this.saveState({ replace: false }); + // change pathname + this.history[updated ? 'replace' : 'push']({ + ...this.history.location, + pathname, + }); } public setQuery(query: Query) { - this.appState.query = query; - this.saveState(); + this.stateContainer.transitions.set('query', query); } /** @@ -472,24 +547,33 @@ export class DashboardStateManager { * @param filter An array of filter bar filters. */ public applyFilters(query: Query, filters: esFilters.Filter[]) { - this.appState.query = query; this.savedDashboard.searchSource.setField('query', query); this.savedDashboard.searchSource.setField('filter', filters); - this.saveState(); + this.stateContainer.transitions.set('query', query); } public switchViewMode(newMode: ViewMode) { - this.appState.viewMode = newMode; - this.saveState(); + this.stateContainer.transitions.set('viewMode', newMode); } /** * Destroys and cleans up this object when it's no longer used. */ public destroy() { - if (this.stateMonitor) { - this.stateMonitor.destroy(); - } + this.stateContainerChangeSub.unsubscribe(); this.savedDashboard.destroy(); + if (this.stateSyncRef) { + this.stateSyncRef.stop(); + } + } + + private checkIsDirty() { + // Filters need to be compared manually because they sometimes have a $$hashkey stored on the object. + // Query needs to be compared manually because saved legacy queries get migrated in app state automatically + const propsToIgnore: Array = ['viewMode', 'filters', 'query']; + + const initial = _.omit(this.stateDefaults, propsToIgnore); + const current = _.omit(this.stateContainer.get(), propsToIgnore); + return !_.isEqual(initial, current); } } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/global_state_sync.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/global_state_sync.ts deleted file mode 100644 index 1a6c2b09ee3fc2..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/global_state_sync.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { State } from '../legacy_imports'; -import { DataPublicPluginStart as NpDataStart } from '../../../../../../plugins/data/public'; - -/** - * Helper function to sync the global state with the various state providers - * when a local angular application mounts. There are three different ways - * global state can be passed into the application: - * * parameter in the URL hash - e.g. shared link - * * in-memory state in the data plugin exports (timefilter and filterManager) - e.g. default values - * - * This function looks up the three sources (earlier in the list means it takes precedence), - * puts it into the globalState object and syncs it with the url. - * - * Currently the legacy chrome takes care of restoring the global state when navigating from - * one app to another - to migrate away from that it will become necessary to also write the current - * state to local storage - */ -export function syncOnMount( - globalState: State, - { - query: { - filterManager, - timefilter: { timefilter }, - }, - }: NpDataStart -) { - // pull in global state information from the URL - globalState.fetch(); - // remember whether there were info in the URL - const hasGlobalURLState = Boolean(Object.keys(globalState.toObject()).length); - - // sync kibana platform state with the angular global state - if (!globalState.time) { - globalState.time = timefilter.getTime(); - } - if (!globalState.refreshInterval) { - globalState.refreshInterval = timefilter.getRefreshInterval(); - } - if (!globalState.filters && filterManager.getGlobalFilters().length > 0) { - globalState.filters = filterManager.getGlobalFilters(); - } - // only inject cross app global state if there is none in the url itself (that takes precedence) - if (hasGlobalURLState) { - // set flag the global state is set from the URL - globalState.$inheritedGlobalState = true; - } - globalState.save(); -} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js index 540bfcf5aa6847..7ba404d52d9a61 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js @@ -22,19 +22,16 @@ import { i18n } from '@kbn/i18n'; import dashboardTemplate from './dashboard_app.html'; import dashboardListingTemplate from './listing/dashboard_listing_ng_wrapper.html'; -import { - ensureDefaultIndexPattern, - registerTimefilterWithGlobalStateFactory, -} from '../legacy_imports'; +import { ensureDefaultIndexPattern } from '../legacy_imports'; import { initDashboardAppDirective } from './dashboard_app'; -import { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; +import { createDashboardEditUrl, DashboardConstants } from './dashboard_constants'; import { InvalidJSONProperty, SavedObjectNotFound, } from '../../../../../../plugins/kibana_utils/public'; import { DashboardListing, EMPTY_FILTER } from './listing/dashboard_listing'; import { addHelpMenuToAppChrome } from './help_menu/help_menu_util'; -import { syncOnMount } from './global_state_sync'; +import { syncQuery } from '../../../../../../plugins/data/public'; export function initDashboardApp(app, deps) { initDashboardAppDirective(app, deps); @@ -60,16 +57,9 @@ export function initDashboardApp(app, deps) { addHelpMenuToAppChrome(deps.chrome, deps.core.docLinks); } - app.run(globalState => { - syncOnMount(globalState, deps.npDataStart); - }); - - app.run((globalState, $rootScope) => { - registerTimefilterWithGlobalStateFactory( - deps.npDataStart.query.timefilter.timefilter, - globalState, - $rootScope - ); + app.config(stateManagementConfigProvider => { + // Dashboard state management is handled by state containers and state_sync utilities + stateManagementConfigProvider.disable(); }); app.config(function($routeProvider) { @@ -99,10 +89,15 @@ export function initDashboardApp(app, deps) { template: dashboardListingTemplate, controller($injector, $location, $scope) { const service = deps.savedDashboards; - const kbnUrl = $injector.get('kbnUrl'); const dashboardConfig = deps.dashboardConfig; + // syncs `_g` portion of url with query services + const { stop: stopSyncingGlobalStateWithUrl } = syncQuery( + deps.npDataStart.query, + deps.kbnUrlStateStorage + ); + $scope.listingLimit = deps.uiSettings.get('savedObjects:listingLimit'); $scope.create = () => { kbnUrl.redirect(DashboardConstants.CREATE_NEW_DASHBOARD_URL); @@ -130,6 +125,10 @@ export function initDashboardApp(app, deps) { ]); addHelpMenuToAppChrome(deps.chrome, deps.core.docLinks); $scope.core = deps.core; + + $scope.$on('$destroy', () => { + stopSyncingGlobalStateWithUrl(); + }); }, resolve: { dash: function($rootScope, $route, redirectWhenMissing, kbnUrl) { @@ -190,7 +189,7 @@ export function initDashboardApp(app, deps) { template: dashboardTemplate, controller: createNewDashboardCtrl, resolve: { - dash: function($rootScope, $route, redirectWhenMissing, kbnUrl, AppState) { + dash: function($rootScope, $route, redirectWhenMissing, kbnUrl) { const id = $route.current.params.id; return ensureDefaultIndexPattern(deps.core, deps.npDataStart, $rootScope, kbnUrl) @@ -216,8 +215,13 @@ export function initDashboardApp(app, deps) { // Preserve BWC of v5.3.0 links for new, unsaved dashboards. // See https://github.com/elastic/kibana/issues/10951 for more context. if (error instanceof SavedObjectNotFound && id === 'create') { - // Note "new AppState" is necessary so the state in the url is preserved through the redirect. - kbnUrl.redirect(DashboardConstants.CREATE_NEW_DASHBOARD_URL, {}, new AppState()); + // Note preserve querystring part is necessary so the state is preserved through the redirect. + const history = deps.history; + history.replace({ + ...history.location, // preserve query, + pathname: DashboardConstants.CREATE_NEW_DASHBOARD_URL, + }); + deps.toastNotifications.addWarning( i18n.translate('kbn.dashboard.urlWasRemovedInSixZeroWarningMessage', { defaultMessage: diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/migrate_app_state.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/migrate_app_state.test.ts index 4aa2461bb65930..73336ec951894e 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/migrate_app_state.test.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/migrate_app_state.test.ts @@ -23,7 +23,6 @@ import { SavedDashboardPanel } from '../types'; import { migrateAppState } from './migrate_app_state'; test('migrate app state from 6.0', async () => { - const mockSave = jest.fn(); const appState = { uiState: { 'P-1': { vis: { defaultColors: { '0+-+100': 'rgb(0,104,55)' } } }, @@ -39,11 +38,8 @@ test('migrate app state from 6.0', async () => { type: 'visualization', }, ], - translateHashToRison: () => 'a', - getQueryParamName: () => 'a', - save: mockSave, }; - migrateAppState(appState, '8.0'); + migrateAppState(appState as any, '8.0'); expect(appState.uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -54,12 +50,10 @@ test('migrate app state from 6.0', async () => { expect(newPanel.gridData.y).toBe(0); expect((newPanel.embeddableConfig as any).vis.defaultColors['0+-+100']).toBe('rgb(0,104,55)'); - expect(mockSave).toBeCalledTimes(1); }); test('migrate sort from 6.1', async () => { const TARGET_VERSION = '8.0'; - const mockSave = jest.fn(); const appState = { uiState: { 'P-1': { vis: { defaultColors: { '0+-+100': 'rgb(0,104,55)' } } }, @@ -76,12 +70,9 @@ test('migrate sort from 6.1', async () => { sort: 'sort', }, ], - translateHashToRison: () => 'a', - getQueryParamName: () => 'a', - save: mockSave, useMargins: false, }; - migrateAppState(appState, TARGET_VERSION); + migrateAppState(appState as any, TARGET_VERSION); expect(appState.uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -91,11 +82,9 @@ test('migrate sort from 6.1', async () => { expect((newPanel.embeddableConfig as any).sort).toBe('sort'); expect((newPanel.embeddableConfig as any).vis.defaultColors['0+-+100']).toBe('rgb(0,104,55)'); - expect(mockSave).toBeCalledTimes(1); }); test('migrates 6.0 even when uiState does not exist', async () => { - const mockSave = jest.fn(); const appState = { panels: [ { @@ -109,11 +98,8 @@ test('migrates 6.0 even when uiState does not exist', async () => { sort: 'sort', }, ], - translateHashToRison: () => 'a', - getQueryParamName: () => 'a', - save: mockSave, }; - migrateAppState(appState, '8.0'); + migrateAppState(appState as any, '8.0'); expect((appState as any).uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -122,11 +108,9 @@ test('migrates 6.0 even when uiState does not exist', async () => { expect((newPanel as any).sort).toBeUndefined(); expect((newPanel.embeddableConfig as any).sort).toBe('sort'); - expect(mockSave).toBeCalledTimes(1); }); test('6.2 migration adjusts w & h without margins', async () => { - const mockSave = jest.fn(); const appState = { panels: [ { @@ -143,12 +127,9 @@ test('6.2 migration adjusts w & h without margins', async () => { version: '6.2.0', }, ], - translateHashToRison: () => 'a', - getQueryParamName: () => 'a', - save: mockSave, useMargins: false, }; - migrateAppState(appState, '8.0'); + migrateAppState(appState as any, '8.0'); expect((appState as any).uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -159,11 +140,9 @@ test('6.2 migration adjusts w & h without margins', async () => { expect((newPanel as any).sort).toBeUndefined(); expect((newPanel.embeddableConfig as any).sort).toBe('sort'); - expect(mockSave).toBeCalledTimes(1); }); test('6.2 migration adjusts w & h with margins', async () => { - const mockSave = jest.fn(); const appState = { panels: [ { @@ -180,12 +159,9 @@ test('6.2 migration adjusts w & h with margins', async () => { version: '6.2.0', }, ], - translateHashToRison: () => 'a', - getQueryParamName: () => 'a', - save: mockSave, useMargins: true, }; - migrateAppState(appState, '8.0'); + migrateAppState(appState as any, '8.0'); expect((appState as any).uiState).toBeUndefined(); const newPanel = (appState.panels[0] as unknown) as SavedDashboardPanel; @@ -196,5 +172,4 @@ test('6.2 migration adjusts w & h with margins', async () => { expect((newPanel as any).sort).toBeUndefined(); expect((newPanel.embeddableConfig as any).sort).toBe('sort'); - expect(mockSave).toBeCalledTimes(1); }); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/migrate_app_state.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/migrate_app_state.ts index 4083900c7ede7e..0cd958ced0eb1c 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/migrate_app_state.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/migrate_app_state.ts @@ -28,6 +28,7 @@ import { SavedDashboardPanel630, SavedDashboardPanel640To720, SavedDashboardPanel620, + SavedDashboardPanel, } from '../types'; import { migratePanelsTo730 } from '../../migrations/migrate_to_730_panels'; @@ -37,9 +38,9 @@ import { migratePanelsTo730 } from '../../migrations/migrate_to_730_panels'; * Once we hit a major version, we can remove support for older style URLs and get rid of this logic. */ export function migrateAppState( - appState: { [key: string]: unknown } | DashboardAppState, + appState: { [key: string]: unknown } & DashboardAppState, kibanaVersion: string -) { +): DashboardAppState { if (!appState.panels) { throw new Error( i18n.translate('kbn.dashboard.panel.invalidData', { @@ -76,11 +77,11 @@ export function migrateAppState( | SavedDashboardPanel640To720 >, kibanaVersion, - appState.useMargins, - appState.uiState - ); + appState.useMargins as boolean, + appState.uiState as Record> + ) as SavedDashboardPanel[]; delete appState.uiState; - - appState.save(); } + + return appState; } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/save_dashboard.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/save_dashboard.ts index 691c87122564f6..d80208ce27ffe4 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/save_dashboard.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/save_dashboard.ts @@ -36,16 +36,19 @@ export function saveDashboard( dashboardStateManager: DashboardStateManager, saveOptions: SavedObjectSaveOpts ): Promise { - dashboardStateManager.saveState(); - const savedDashboard = dashboardStateManager.savedDashboard; const appState = dashboardStateManager.appState; updateSavedDashboard(savedDashboard, appState, timeFilter, toJson); return savedDashboard.save(saveOptions).then((id: string) => { - dashboardStateManager.lastSavedDashboardFilters = dashboardStateManager.getFilterState(); - dashboardStateManager.resetState(); + if (id) { + // reset state only when save() was successful + // e.g. save() could be interrupted if title is duplicated and not confirmed + dashboardStateManager.lastSavedDashboardFilters = dashboardStateManager.getFilterState(); + dashboardStateManager.resetState(); + } + return id; }); } diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/update_saved_dashboard.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/update_saved_dashboard.ts index 2072b5d4f6eb06..ec8073c0f72f74 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/update_saved_dashboard.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/lib/update_saved_dashboard.ts @@ -19,13 +19,13 @@ import _ from 'lodash'; import { RefreshInterval, TimefilterContract } from 'src/plugins/data/public'; -import { AppState } from '../../legacy_imports'; import { FilterUtils } from './filter_utils'; import { SavedObjectDashboard } from '../../saved_dashboard/saved_dashboard'; +import { DashboardAppState } from '../types'; export function updateSavedDashboard( savedDashboard: SavedObjectDashboard, - appState: AppState, + appState: DashboardAppState, timeFilter: TimefilterContract, toJson: (object: T) => string ) { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/types.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/types.ts index e3eb25a208856f..3151fbf821b9fe 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/types.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/types.ts @@ -18,7 +18,6 @@ */ import { ViewMode } from 'src/plugins/embeddable/public'; -import { AppState } from '../legacy_imports'; import { RawSavedDashboardPanelTo60, RawSavedDashboardPanel610, @@ -93,11 +92,7 @@ export type SavedDashboardPanelTo60 = Pick< readonly type: string; }; -export type DashboardAppStateDefaults = DashboardAppStateParameters & { - description?: string; -}; - -export interface DashboardAppStateParameters { +export interface DashboardAppState { panels: SavedDashboardPanel[]; fullScreenMode: boolean; title: string; @@ -113,9 +108,24 @@ export interface DashboardAppStateParameters { savedQuery?: string; } -// This could probably be improved if we flesh out AppState more... though AppState will be going away -// so maybe not worth too much time atm. -export type DashboardAppState = DashboardAppStateParameters & AppState; +export type DashboardAppStateDefaults = DashboardAppState & { + description?: string; +}; + +export interface DashboardAppStateTransitions { + set: ( + state: DashboardAppState + ) => ( + prop: T, + value: DashboardAppState[T] + ) => DashboardAppState; + setOption: ( + state: DashboardAppState + ) => ( + prop: T, + value: DashboardAppState['options'][T] + ) => DashboardAppState; +} export interface SavedDashboardPanelMap { [key: string]: SavedDashboardPanel; @@ -139,18 +149,3 @@ export type ConfirmModalFn = ( title: string; } ) => void; - -export type AddFilterFn = ( - { - field, - value, - operator, - index, - }: { - field: string; - value: string; - operator: string; - index: string; - }, - appState: AppState -) => void; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts b/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts index ca4b18a37504c6..732fbd525ae373 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/plugin.ts @@ -25,12 +25,13 @@ import { Plugin, SavedObjectsClientContract, } from 'kibana/public'; +import { createHashHistory } from 'history'; import { i18n } from '@kbn/i18n'; import { RenderDeps } from './np_ready/application'; import { DataStart } from '../../../data/public'; import { DataPublicPluginStart as NpDataStart } from '../../../../../plugins/data/public'; import { IEmbeddableStart } from '../../../../../plugins/embeddable/public'; -import { Storage } from '../../../../../plugins/kibana_utils/public'; +import { createKbnUrlStateStorage, Storage } from '../../../../../plugins/kibana_utils/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; import { DashboardConstants } from './np_ready/dashboard_constants'; import { @@ -96,6 +97,12 @@ export class DashboardPlugin implements Plugin { overlays: contextCore.overlays, }); + const history = createHashHistory(); + const kbnUrlStateStorage = createKbnUrlStateStorage({ + history, + useHash: core.uiSettings.get('state:storeInSessionStorage'), + }); + const deps: RenderDeps = { core: contextCore as LegacyCoreStart, ...angularDependencies, @@ -111,6 +118,8 @@ export class DashboardPlugin implements Plugin { embeddables, dashboardCapabilities: contextCore.application.capabilities.dashboard, localStorage: new Storage(localStorage), + history, + kbnUrlStateStorage, }; const { renderApp } = await import('./np_ready/application'); return renderApp(params.element, params.appBasePath, deps); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.ts b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.ts index 18e15b215523e4..08a6f067d20260 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard.ts @@ -16,12 +16,16 @@ * specific language governing permissions and limitations * under the License. */ -import { ISearchSource } from 'ui/courier'; import { SavedObject, SavedObjectKibanaServices } from 'ui/saved_objects/types'; import { createSavedObjectClass } from 'ui/saved_objects/saved_object'; import { extractReferences, injectReferences } from './saved_dashboard_references'; -import { esFilters, Query, RefreshInterval } from '../../../../../../plugins/data/public'; +import { + esFilters, + ISearchSource, + Query, + RefreshInterval, +} from '../../../../../../plugins/data/public'; import { createDashboardEditUrl } from '..'; export interface SavedObjectDashboard extends SavedObject { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard_register.ts b/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard_register.ts deleted file mode 100644 index b9ea49ca4fd441..00000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/saved_dashboard/saved_dashboard_register.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; -// @ts-ignore -import { uiModules } from 'ui/modules'; -// @ts-ignore -import { savedObjectManagementRegistry } from '../../management/saved_object_registry'; -import { createSavedDashboardLoader } from './saved_dashboards'; - -const module = uiModules.get('app/dashboard'); - -// Register this service with the saved object registry so it can be -// edited by the object editor. -savedObjectManagementRegistry.register({ - service: 'savedDashboards', - title: i18n.translate('kbn.dashboard.savedDashboardsTitle', { - defaultMessage: 'dashboards', - }), -}); - -// this is no longer used in the conroller, but just here for savedObjectManagementRegistry -module.service('savedDashboards', () => - createSavedDashboardLoader({ - savedObjectsClient: npStart.core.savedObjects.client, - indexPatterns: npStart.plugins.data.indexPatterns, - chrome: npStart.core.chrome, - overlays: npStart.core.overlays, - }) -); diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js index 18d83595f8fa30..6ffda87ac2be8d 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js @@ -22,7 +22,7 @@ import _ from 'lodash'; import sinon from 'sinon'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; // Load the kibana app dependencies. diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js index 378a9e93256557..f302d684135f6c 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import ngMock from 'ng_mock'; import { fieldCalculator } from '../../np_ready/components/field_chooser/lib/field_calculator'; import expect from '@kbn/expect'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js index 5f6898ae2bd164..f74e145865475d 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js @@ -23,7 +23,7 @@ import _ from 'lodash'; import sinon from 'sinon'; import expect from '@kbn/expect'; import $ from 'jquery'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import FixturesHitsProvider from 'fixtures/hits'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { SimpleSavedObject } from '../../../../../../../core/public'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/doc_table.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/doc_table.js index b57f452b637afa..6b97da79fc5893 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/doc_table.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/doc_table.js @@ -22,7 +22,7 @@ import expect from '@kbn/expect'; import _ from 'lodash'; import ngMock from 'ng_mock'; import 'ui/private'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import hits from 'fixtures/real_hits'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/get_sort.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/get_sort.js index d9fdcc48608d22..d5485bca33cf50 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/get_sort.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/get_sort.js @@ -23,7 +23,6 @@ import ngMock from 'ng_mock'; import { getSort } from '../../../np_ready/angular/doc_table/lib/get_sort'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -const defaultSort = [{ time: 'desc' }]; let indexPattern; describe('docTable', function() { @@ -51,26 +50,26 @@ describe('docTable', function() { expect(getSort([{ bytes: 'desc' }], indexPattern)).to.eql([{ bytes: 'desc' }]); }); - it('should sort by the default when passed an unsortable field', function() { - expect(getSort(['non-sortable', 'asc'], indexPattern)).to.eql(defaultSort); - expect(getSort(['lol_nope', 'asc'], indexPattern)).to.eql(defaultSort); + it('should return an empty array when passed an unsortable field', function() { + expect(getSort(['non-sortable', 'asc'], indexPattern)).to.eql([]); + expect(getSort(['lol_nope', 'asc'], indexPattern)).to.eql([]); delete indexPattern.timeFieldName; - expect(getSort(['non-sortable', 'asc'], indexPattern)).to.eql([{ _score: 'desc' }]); + expect(getSort(['non-sortable', 'asc'], indexPattern)).to.eql([]); }); - it('should sort in reverse chrono order otherwise on time based patterns', function() { - expect(getSort([], indexPattern)).to.eql(defaultSort); - expect(getSort(['foo'], indexPattern)).to.eql(defaultSort); - expect(getSort({ foo: 'bar' }, indexPattern)).to.eql(defaultSort); + it('should return an empty array ', function() { + expect(getSort([], indexPattern)).to.eql([]); + expect(getSort(['foo'], indexPattern)).to.eql([]); + expect(getSort({ foo: 'bar' }, indexPattern)).to.eql([]); }); - it('should sort by score on non-time patterns', function() { + it('should return an empty array on non-time patterns', function() { delete indexPattern.timeFieldName; - expect(getSort([], indexPattern)).to.eql([{ _score: 'desc' }]); - expect(getSort(['foo'], indexPattern)).to.eql([{ _score: 'desc' }]); - expect(getSort({ foo: 'bar' }, indexPattern)).to.eql([{ _score: 'desc' }]); + expect(getSort([], indexPattern)).to.eql([]); + expect(getSort(['foo'], indexPattern)).to.eql([]); + expect(getSort({ foo: 'bar' }, indexPattern)).to.eql([]); }); }); @@ -87,19 +86,19 @@ describe('docTable', function() { expect(getSort.array([{ bytes: 'desc' }], indexPattern)).to.eql([['bytes', 'desc']]); }); - it('should sort by the default when passed an unsortable field', function() { - expect(getSort.array([{ 'non-sortable': 'asc' }], indexPattern)).to.eql([['time', 'desc']]); - expect(getSort.array([{ lol_nope: 'asc' }], indexPattern)).to.eql([['time', 'desc']]); + it('should sort by an empty array when an unsortable field is given', function() { + expect(getSort.array([{ 'non-sortable': 'asc' }], indexPattern)).to.eql([]); + expect(getSort.array([{ lol_nope: 'asc' }], indexPattern)).to.eql([]); delete indexPattern.timeFieldName; - expect(getSort.array([{ 'non-sortable': 'asc' }], indexPattern)).to.eql([['_score', 'desc']]); + expect(getSort.array([{ 'non-sortable': 'asc' }], indexPattern)).to.eql([]); }); - it('should sort by the default when passed an empty sort', () => { - expect(getSort.array([], indexPattern)).to.eql([['time', 'desc']]); + it('should return an empty array when passed an empty sort array', () => { + expect(getSort.array([], indexPattern)).to.eql([]); delete indexPattern.timeFieldName; - expect(getSort.array([], indexPattern)).to.eql([['_score', 'desc']]); + expect(getSort.array([], indexPattern)).to.eql([]); }); }); }); diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/rows_headers.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/rows_headers.js index 012f2b6061ee42..c19e033ccb72df 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/rows_headers.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/rows_headers.js @@ -24,7 +24,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { getFakeRow, getFakeRowVals } from 'fixtures/fake_row'; import $ from 'jquery'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; describe('Doc Table', function() { diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_add_filter.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_add_filter.js index 90614cf3c132c2..f2acbf363d825d 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_add_filter.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_add_filter.js @@ -22,7 +22,7 @@ import ngMock from 'ng_mock'; import { createStateStub } from './_utils'; import { getQueryParameterActions } from '../../np_ready/angular/context/query_parameters/actions'; import { createIndexPatternsStub } from '../../np_ready/angular/context/api/__tests__/_stubs'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import { npStart } from 'ui/new_platform'; describe('context app', function() { diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_predecessor_count.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_predecessor_count.js index 1ad4bdbea210db..9ba425bb0e489e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_predecessor_count.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_predecessor_count.js @@ -19,7 +19,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import { createStateStub } from './_utils'; import { getQueryParameterActions } from '../../np_ready/angular/context/query_parameters/actions'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_query_parameters.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_query_parameters.js index e9ec2c300faa11..39dde2d8bb7cf0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_query_parameters.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_query_parameters.js @@ -19,7 +19,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import { createStateStub } from './_utils'; import { getQueryParameterActions } from '../../np_ready/angular/context/query_parameters/actions'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_successor_count.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_successor_count.js index 15f3eefac3fd1a..c05f5b4aff3bc7 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_successor_count.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/query_parameters/action_set_successor_count.js @@ -19,7 +19,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import { createStateStub } from './_utils'; import { getQueryParameterActions } from '../../np_ready/angular/context/query_parameters/actions'; diff --git a/src/legacy/core_plugins/kibana/public/discover/build_services.ts b/src/legacy/core_plugins/kibana/public/discover/build_services.ts index 1fb8b4abb21c4d..bc2436ecdf5ea8 100644 --- a/src/legacy/core_plugins/kibana/public/discover/build_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/build_services.ts @@ -30,7 +30,7 @@ import { IndexPatternsContract, DataPublicPluginStart, } from 'src/plugins/data/public'; -import { createSavedSearchesService } from './saved_searches'; +import { createSavedSearchesLoader } from './saved_searches'; import { DiscoverStartPlugins } from './plugin'; import { EuiUtilsStart } from '../../../../../plugins/eui_utils/public'; import { SharePluginStart } from '../../../../../plugins/share/public'; @@ -68,7 +68,7 @@ export async function buildServices( chrome: core.chrome, overlays: core.overlays, }; - const savedObjectService = createSavedSearchesService(services); + const savedObjectService = createSavedSearchesLoader(services); return { addBasePath: core.http.basePath.prepend, capabilities: core.application.capabilities, diff --git a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts index 1cefabe08c2d57..fea834686eb4f0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts +++ b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts @@ -31,8 +31,6 @@ import { EventsProvider } from 'ui/events'; import { PersistedState } from 'ui/persisted_state'; // @ts-ignore import { PromiseServiceCreator } from 'ui/promises/promises'; -// @ts-ignore -import { createEsService } from 'ui/es'; import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; // @ts-ignore import { PrivateProvider } from 'ui/private/private'; @@ -66,7 +64,7 @@ import { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; // @ts-ignore import { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; import { configureAppAngularModule } from 'ui/legacy_compat'; -import { IndexPatterns } from '../../../../../plugins/data/public'; +import { IndexPatterns, DataPublicPluginStart } from '../../../../../plugins/data/public'; import { Storage } from '../../../../../plugins/kibana_utils/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; import { createDocTableDirective } from './np_ready/angular/doc_table/doc_table'; @@ -94,7 +92,7 @@ import { DiscoverStartPlugins } from './plugin'; * needs to render, so in the end the current 'kibana' angular module is no longer necessary */ export function getInnerAngularModule(name: string, core: CoreStart, deps: DiscoverStartPlugins) { - const module = initializeInnerAngularModule(name, core, deps.navigation); + const module = initializeInnerAngularModule(name, core, deps.navigation, deps.data); configureAppAngularModule(module, core as LegacyCoreStart, true); return module; } @@ -107,7 +105,7 @@ export function getInnerAngularModuleEmbeddable( core: CoreStart, deps: DiscoverStartPlugins ) { - const module = initializeInnerAngularModule(name, core, deps.navigation, true); + const module = initializeInnerAngularModule(name, core, deps.navigation, deps.data, true); configureAppAngularModule(module, core as LegacyCoreStart, true); return module; } @@ -118,6 +116,7 @@ export function initializeInnerAngularModule( name = 'app/discover', core: CoreStart, navigation: NavigationStart, + data: DataPublicPluginStart, embeddable = false ) { if (!initialized) { @@ -131,7 +130,7 @@ export function initializeInnerAngularModule( createLocalGlobalStateModule(); createLocalAppStateModule(); createLocalStorageModule(); - createElasticSearchModule(); + createElasticSearchModule(data); createIndexPatternsModule(); createPagerFactoryModule(); createDocTableModule(); @@ -163,7 +162,6 @@ export function initializeInnerAngularModule( 'ngRoute', 'react', 'ui.bootstrap', - 'elasticsearch', 'discoverConfig', 'discoverI18n', 'discoverPrivate', @@ -298,11 +296,13 @@ const createLocalStorageService = function(type: string) { }; }; -function createElasticSearchModule() { +function createElasticSearchModule(data: DataPublicPluginStart) { angular - .module('discoverEs', ['elasticsearch', 'discoverConfig']) + .module('discoverEs', ['discoverConfig']) // Elasticsearch client used for requesting data. Connects to the /elasticsearch proxy - .service('es', createEsService); + .service('es', () => { + return data.search.__LEGACY.esClient; + }); } function createIndexPatternsModule() { diff --git a/src/legacy/core_plugins/kibana/public/discover/index.ts b/src/legacy/core_plugins/kibana/public/discover/index.ts index 7bde30e0d0f0ef..33b2ad4bf81719 100644 --- a/src/legacy/core_plugins/kibana/public/discover/index.ts +++ b/src/legacy/core_plugins/kibana/public/discover/index.ts @@ -16,24 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import chrome from 'ui/chrome'; + import { PluginInitializerContext } from 'kibana/public'; -import { npSetup, npStart } from 'ui/new_platform'; import { DiscoverPlugin } from './plugin'; +export { createSavedSearchesLoader } from './saved_searches/saved_searches'; + // Core will be looking for this when loading our plugin in the new platform export const plugin = (context: PluginInitializerContext) => { return new DiscoverPlugin(); }; - -// Legacy compatiblity part - to be removed at cutover, replaced by a kibana.json file -export const pluginInstance = plugin({} as PluginInitializerContext); -export const setup = pluginInstance.setup(npSetup.core, { - ...npSetup.plugins, - __LEGACY: { - chrome, - }, -}); -export const start = pluginInstance.start(npStart.core, npStart.plugins); - -export { createSavedSearchesService } from './saved_searches/saved_searches'; diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts index d2eefba2cecdd9..27aa920c98aad2 100644 --- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -57,16 +57,7 @@ export { wrapInI18nContext } from 'ui/i18n'; export { buildVislibDimensions } from '../../../visualizations/public'; // @ts-ignore export { callAfterBindingsWorkaround } from 'ui/compat'; -export { - getRequestInspectorStats, - getResponseInspectorStats, - hasSearchStategyForIndexPattern, - isDefaultTypeIndexPattern, - SearchSource, - EsQuerySortValue, - SortDirection, - ISearchSource, -} from 'ui/courier'; +export { getRequestInspectorStats, getResponseInspectorStats } from '../../../data/public'; // @ts-ignore export { intervalOptions } from 'ui/agg_types/buckets/_interval_options'; // @ts-ignore @@ -81,8 +72,6 @@ export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; export { timezoneProvider } from 'ui/vis/lib/timezone'; // @ts-ignore export { tabifyAggResponse } from 'ui/agg_response/tabify'; -// @ts-ignore -export { vislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; export { ensureDefaultIndexPattern } from 'ui/legacy_compat'; export { unhashUrl } from '../../../../../plugins/kibana_utils/public'; // @ts-ignore @@ -95,10 +84,17 @@ export { IIndexPattern, IndexPattern, indexPatterns, + hasSearchStategyForIndexPattern, IFieldType, + SearchSource, + ISearchSource, + EsQuerySortValue, + SortDirection, } from '../../../../../plugins/data/public'; export { ElasticSearchHit } from './np_ready/doc_views/doc_views_types'; export { Adapters } from 'ui/inspector/types'; -export { Chrome, IInjector } from 'ui/chrome'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; export { FieldName } from 'ui/directives/field_name/field_name'; +export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; +// @ts-ignore +export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series'; diff --git a/src/legacy/core_plugins/kibana/public/discover/legacy.ts b/src/legacy/core_plugins/kibana/public/discover/legacy.ts new file mode 100644 index 00000000000000..ff44fbbe115d50 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/legacy.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PluginInitializerContext } from 'kibana/public'; +import { npSetup, npStart } from 'ui/new_platform'; +import { plugin } from './index'; + +// Legacy compatibility part - to be removed at cutover, replaced by a kibana.json file +export const pluginInstance = plugin({} as PluginInitializerContext); +export const setup = pluginInstance.setup(npSetup.core, { + ...npSetup.plugins, +}); +export const start = pluginInstance.start(npStart.core, npStart.plugins); diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/anchor.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/anchor.js index 45ce6cc9d0af2e..debcccebbd11c0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/anchor.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/anchor.js @@ -19,7 +19,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import { createIndexPatternsStub, createSearchSourceStub } from './_stubs'; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/predecessors.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/predecessors.js index 266a505f6be14b..c24b6ac6307ffd 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/predecessors.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/predecessors.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import moment from 'moment'; import * as _ from 'lodash'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import { createIndexPatternsStub, createContextSearchSourceStub } from './_stubs'; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/successors.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/successors.js index e06d414ba260ce..d4c00930c93839 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/successors.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/__tests__/successors.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import moment from 'moment'; import * as _ from 'lodash'; -import { pluginInstance } from 'plugins/kibana/discover/index'; +import { pluginInstance } from 'plugins/kibana/discover/legacy'; import { createIndexPatternsStub, createContextSearchSourceStub } from './_stubs'; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index 2bf554860f7434..dd782f97b075d8 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -36,6 +36,7 @@ import { showOpenSearchPanel } from '../components/top_nav/show_open_search_pane import { addHelpMenuToAppChrome } from '../components/help_menu/help_menu_util'; import '../components/fetch_error'; import { getPainlessError } from './get_painless_error'; +import { discoverResponseHandler } from './response_handler'; import { angular, buildVislibDimensions, @@ -44,7 +45,6 @@ import { getServices, hasSearchStategyForIndexPattern, intervalOptions, - isDefaultTypeIndexPattern, migrateLegacyQuery, RequestAdapter, showSaveModal, @@ -52,7 +52,6 @@ import { stateMonitorFactory, subscribeWithScope, tabifyAggResponse, - vislibSeriesResponseHandlerProvider, Vis, SavedObjectSaveModal, getAngularModule, @@ -73,7 +72,10 @@ const { } = getServices(); import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../helpers/breadcrumbs'; -import { generateFilters } from '../../../../../../../plugins/data/public'; +import { + generateFilters, + indexPatterns as indexPatternsUtils, +} from '../../../../../../../plugins/data/public'; import { getIndexPatternId } from '../helpers/get_index_pattern_id'; import { FilterStateManager } from '../../../../../data/public'; @@ -187,7 +189,6 @@ function discoverController( $timeout, $window, AppState, - Private, Promise, config, kbnUrl, @@ -196,7 +197,6 @@ function discoverController( getAppState, globalState ) { - const responseHandler = vislibSeriesResponseHandlerProvider().handler; const filterStateManager = new FilterStateManager(globalState, getAppState, filterManager); const inspectorAdapters = { @@ -402,7 +402,8 @@ function discoverController( // searchSource which applies time range const timeRangeSearchSource = savedSearch.searchSource.create(); - if (isDefaultTypeIndexPattern($scope.indexPattern)) { + + if (indexPatternsUtils.isDefault($scope.indexPattern)) { timeRangeSearchSource.setField('filter', () => { return timefilter.createFilter($scope.indexPattern); }); @@ -486,7 +487,14 @@ function discoverController( const { searchFields, selectFields } = await getSharingDataFields(); searchSource.setField('fields', searchFields); - searchSource.setField('sort', getSortForSearchSource($state.sort, $scope.indexPattern)); + searchSource.setField( + 'sort', + getSortForSearchSource( + $state.sort, + $scope.indexPattern, + config.get('discover:sort:defaultOrder') + ) + ); searchSource.setField('highlight', null); searchSource.setField('highlightAll', null); searchSource.setField('aggs', null); @@ -517,11 +525,7 @@ function discoverController( language: localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage'), }, - sort: getSort.array( - savedSearch.sort, - $scope.indexPattern, - config.get('discover:sort:defaultOrder') - ), + sort: getSort.array(savedSearch.sort, $scope.indexPattern), columns: savedSearch.columns.length > 0 ? savedSearch.columns : config.get('defaultColumns').slice(), index: $scope.indexPattern.id, @@ -560,7 +564,8 @@ function discoverController( $scope.opts = { // number of records to fetch, then paginate through sampleSize: config.get('discover:sampleSize'), - timefield: isDefaultTypeIndexPattern($scope.indexPattern) && $scope.indexPattern.timeFieldName, + timefield: + indexPatternsUtils.isDefault($scope.indexPattern) && $scope.indexPattern.timeFieldName, savedSearch: savedSearch, indexPatternList: $route.current.locals.savedObjects.ip.list, }; @@ -847,11 +852,9 @@ function discoverController( timeRange: $scope.timeRange, searchSource: $scope.searchSource, }) - ) - .then(resp => responseHandler(tabifiedData, resp)) - .then(resp => { - $scope.histogramData = resp; - }); + ).then(resp => { + $scope.histogramData = discoverResponseHandler(tabifiedData, resp); + }); } $scope.hits = resp.hits.total; @@ -934,7 +937,10 @@ function discoverController( const { indexPattern, searchSource } = $scope; searchSource .setField('size', $scope.opts.sampleSize) - .setField('sort', getSortForSearchSource($state.sort, indexPattern)) + .setField( + 'sort', + getSortForSearchSource($state.sort, indexPattern, config.get('discover:sort:defaultOrder')) + ) .setField('query', !$state.query ? null : $state.query) .setField('filter', filterManager.getFilters()); }); @@ -1000,7 +1006,7 @@ function discoverController( query: '', language: localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage'), }; - filterManager.removeAll(); + filterManager.setFilters(filterManager.getGlobalFilters()); $state.save(); $scope.fetch(); }; @@ -1008,7 +1014,9 @@ function discoverController( const updateStateFromSavedQuery = savedQuery => { $state.query = savedQuery.attributes.query; $state.save(); - filterManager.setFilters(savedQuery.attributes.filters || []); + const savedQueryFilters = savedQuery.attributes.filters || []; + const globalFilters = filterManager.getGlobalFilters(); + filterManager.setFilters([...globalFilters, ...savedQueryFilters]); if (savedQuery.attributes.timefilter) { timefilter.setTime({ @@ -1158,7 +1166,7 @@ function discoverController( // Block the UI from loading if the user has loaded a rollup index pattern but it isn't // supported. $scope.isUnsupportedIndexPattern = - !isDefaultTypeIndexPattern($route.current.locals.savedObjects.ip.loaded) && + !indexPatternsUtils.isDefault($route.current.locals.savedObjects.ip.loaded) && !hasSearchStategyForIndexPattern($route.current.locals.savedObjects.ip.loaded); if ($scope.isUnsupportedIndexPattern) { diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header.ts index a5cb9180333a4a..32174984c1dfb4 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header.ts @@ -37,6 +37,7 @@ export function createTableHeaderDirective(reactDirective: any, config: IUiSetti { hideTimeColumn: config.get('doc_table:hideTimeColumn'), isShortDots: config.get('shortDots:enable'), + defaultSortOrder: config.get('discover:sort:defaultOrder'), } ); } diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx index 13833d724967a0..990ace32e64491 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx @@ -20,7 +20,7 @@ import { IndexPattern } from '../../../../../kibana_services'; // @ts-ignore import { shortenDottedString } from '../../../../../../../common/utils/shorten_dotted_string'; -export type SortOrder = [string, 'asc' | 'desc']; +export type SortOrder = [string, string]; export interface ColumnProps { name: string; displayName: string; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.test.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.test.tsx index ef3d4ecc4b18fc..b201bea26503ea 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.test.tsx @@ -59,6 +59,7 @@ function getMockProps(props = {}) { indexPattern: getMockIndexPattern(), hideTimeColumn: false, columns: ['first', 'middle', 'last'], + defaultSortOrder: 'desc', sortOrder: [['time', 'asc']] as SortOrder[], isShortDots: true, onRemoveColumn: jest.fn(), diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.tsx index 17b961dbe68326..2ca53d5a34b039 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.tsx @@ -21,9 +21,11 @@ import { IndexPattern } from '../../../../../kibana_services'; // @ts-ignore import { TableHeaderColumn } from './table_header_column'; import { SortOrder, getDisplayedColumns } from './helpers'; +import { getDefaultSort } from '../../lib/get_default_sort'; interface Props { columns: string[]; + defaultSortOrder: string; hideTimeColumn: boolean; indexPattern: IndexPattern; isShortDots: boolean; @@ -35,6 +37,7 @@ interface Props { export function TableHeader({ columns, + defaultSortOrder, hideTimeColumn, indexPattern, isShortDots, @@ -53,7 +56,9 @@ export function TableHeader({ = { desc: 'fa fa-sort-down', asc: 'fa fa-sort-up', '': 'fa fa-sort', diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_default_sort.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_default_sort.ts new file mode 100644 index 00000000000000..634e3cfec3a0bd --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_default_sort.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { IndexPattern } from '../../../../kibana_services'; +// @ts-ignore +import { isSortable } from './get_sort'; +import { SortOrder } from '../components/table_header/helpers'; + +/** + * use in case the user didn't manually sort. + * the default sort is returned depending of the index pattern + */ +export function getDefaultSort( + indexPattern: IndexPattern, + defaultSortOrder: string = 'desc' +): SortOrder[] { + if (indexPattern.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) { + return [[indexPattern.timeFieldName, defaultSortOrder]]; + } else { + return [['_score', defaultSortOrder]]; + } +} diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort.js index 0da53f088e7626..ce32fdaeda2375 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort.js @@ -19,7 +19,7 @@ import _ from 'lodash'; -function isSortable(field, indexPattern) { +export function isSortable(field, indexPattern) { return indexPattern.fields.getByName(field) && indexPattern.fields.getByName(field).sortable; } @@ -41,7 +41,7 @@ function createSortObject(sortPair, indexPattern) { * @param {object} indexPattern used for determining default sort * @returns {object} a sort object suitable for returning to elasticsearch */ -export function getSort(sort, indexPattern, defaultSortOrder = 'desc') { +export function getSort(sort, indexPattern) { let sortObjects; if (Array.isArray(sort)) { sortObjects = _.compact(sort.map(sortPair => createSortObject(sortPair, indexPattern))); @@ -49,15 +49,12 @@ export function getSort(sort, indexPattern, defaultSortOrder = 'desc') { if (!_.isEmpty(sortObjects)) { return sortObjects; - } else if (indexPattern.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) { - return [{ [indexPattern.timeFieldName]: defaultSortOrder }]; - } else { - return [{ _score: 'desc' }]; } + return []; } -getSort.array = function(sort, indexPattern, defaultSortOrder) { - return getSort(sort, indexPattern, defaultSortOrder).map(sortPair => +getSort.array = function(sort, indexPattern) { + return getSort(sort, indexPattern).map(sortPair => _(sortPair) .pairs() .pop() diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort_for_search_source.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort_for_search_source.ts index 26bba4589cf6a5..62a44d30adfd55 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort_for_search_source.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort_for_search_source.ts @@ -19,16 +19,24 @@ import { IndexPattern } from '../../../../kibana_services'; import { SortOrder } from '../components/table_header/helpers'; import { getSort } from './get_sort'; +import { getDefaultSort } from './get_default_sort'; /** - * prepares sort for search source, that's sending the request to ES - * handles the special case when there's sorting by date_nanos typed fields - * the addon of the numeric_type guarantees the right sort order - * when there are indices with date and indices with date_nanos field + * Prepares sort for search source, that's sending the request to ES + * - Adds default sort if necessary + * - Handles the special case when there's sorting by date_nanos typed fields + * the addon of the numeric_type guarantees the right sort order + * when there are indices with date and indices with date_nanos field */ -export function getSortForSearchSource(sort?: SortOrder[], indexPattern?: IndexPattern) { +export function getSortForSearchSource( + sort?: SortOrder[], + indexPattern?: IndexPattern, + defaultDirection: 'asc' | 'desc' = 'desc' +) { if (!sort || !indexPattern) { return []; + } else if (Array.isArray(sort) && sort.length === 0) { + sort = getDefaultSort(indexPattern, defaultDirection); } const { timeFieldName } = indexPattern; return getSort(sort, indexPattern).map((sortPair: Record) => { diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts index 212fd870a5aeb8..2bbeea9d675c7e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts @@ -25,6 +25,7 @@ export function getPainlessError(error: Error) { error, 'resp.error.root_cause' ); + const message: string = get(error, 'message'); if (!rootCause) { return; @@ -43,6 +44,6 @@ export function getPainlessError(error: Error) { defaultMessage: "Error with Painless scripted field '{script}'.", values: { script }, }), - error: error.message, + error: message, }; } diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js new file mode 100644 index 00000000000000..e49f43a443719d --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js @@ -0,0 +1,119 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { buildPointSeriesData, getFormat } from '../../kibana_services'; + +function tableResponseHandler(table, dimensions) { + const converted = { tables: [] }; + const split = dimensions.splitColumn || dimensions.splitRow; + + if (split) { + converted.direction = dimensions.splitRow ? 'row' : 'column'; + const splitColumnIndex = split[0].accessor; + const splitColumnFormatter = getFormat(split[0].format); + const splitColumn = table.columns[splitColumnIndex]; + const splitMap = {}; + let splitIndex = 0; + + table.rows.forEach((row, rowIndex) => { + const splitValue = row[splitColumn.id]; + + if (!splitMap.hasOwnProperty(splitValue)) { + splitMap[splitValue] = splitIndex++; + const tableGroup = { + $parent: converted, + title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`, + name: splitColumn.name, + key: splitValue, + column: splitColumnIndex, + row: rowIndex, + table, + tables: [], + }; + tableGroup.tables.push({ + $parent: tableGroup, + columns: table.columns, + rows: [], + }); + + converted.tables.push(tableGroup); + } + + const tableIndex = splitMap[splitValue]; + converted.tables[tableIndex].tables[0].rows.push(row); + }); + } else { + converted.tables.push({ + columns: table.columns, + rows: table.rows, + }); + } + + return converted; +} + +function convertTableGroup(tableGroup, convertTable) { + const tables = tableGroup.tables; + + if (!tables.length) return; + + const firstChild = tables[0]; + if (firstChild.columns) { + const chart = convertTable(firstChild); + // if chart is within a split, assign group title to its label + if (tableGroup.$parent) { + chart.label = tableGroup.title; + } + return chart; + } + + const out = {}; + let outList; + + tables.forEach(function(table) { + if (!outList) { + const direction = tableGroup.direction === 'row' ? 'rows' : 'columns'; + outList = out[direction] = []; + } + + let output; + if ((output = convertTableGroup(table, convertTable))) { + outList.push(output); + } + }); + + return out; +} + +export const discoverResponseHandler = (response, dimensions) => { + const tableGroup = tableResponseHandler(response, dimensions); + + let converted = convertTableGroup(tableGroup, table => { + return buildPointSeriesData(table, dimensions); + }); + if (!converted) { + // mimic a row of tables that doesn't have any tables + // https://github.com/elastic/kibana/blob/7bfb68cd24ed42b1b257682f93c50cd8d73e2520/src/kibana/components/vislib/components/zero_injection/inject_zeros.js#L32 + converted = { rows: [] }; + } + + converted.hits = response.rows.length; + + return converted; +}; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/fetch_error/fetch_error.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/fetch_error/fetch_error.tsx index d2dda32f318fe5..1aad7e953b8de0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/fetch_error/fetch_error.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/fetch_error/fetch_error.tsx @@ -39,7 +39,7 @@ const DiscoverFetchError = ({ fetchError }: Props) => { if (fetchError.lang === 'painless') { const { chrome } = getServices(); - const mangagementUrlObj = chrome.navLinks.get('kibana:management'); + const mangagementUrlObj = chrome.navLinks.get('kibana:stack_management'); const managementUrl = mangagementUrlObj ? mangagementUrlObj.url : ''; const url = `${managementUrl}/kibana/index_patterns`; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_helpers.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_helpers.tsx index fb4f0c6056a832..b9932da0523f8f 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_helpers.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_helpers.tsx @@ -16,17 +16,13 @@ * specific language governing permissions and limitations * under the License. */ + +import { auto, IController } from 'angular'; import React from 'react'; import { render } from 'react-dom'; import angular, { ICompileService } from 'angular'; -import { - DocViewRenderProps, - AngularScope, - AngularController, - AngularDirective, -} from './doc_views_types'; +import { DocViewRenderProps, AngularScope, AngularDirective } from './doc_views_types'; import { DocViewerError } from '../components/doc_viewer/doc_viewer_render_error'; -import { Chrome } from '../../kibana_services'; /** * Compiles and injects the give angular template into the given dom node @@ -36,10 +32,10 @@ export async function injectAngularElement( domNode: Element, template: string, scopeProps: DocViewRenderProps, - Controller: AngularController, - chrome: Chrome + Controller: IController, + getInjector: () => Promise ): Promise<() => void> { - const $injector = await chrome.dangerouslyGetActiveInjector(); + const $injector = await getInjector(); const rootScope: AngularScope = $injector.get('$rootScope'); const $compile: ICompileService = $injector.get('$compile'); const newScope = Object.assign(rootScope.$new(), scopeProps); @@ -69,7 +65,10 @@ export async function injectAngularElement( * Converts a given legacy angular directive to a render function * for usage in a react component. Note that the rendering is async */ -export function convertDirectiveToRenderFn(directive: AngularDirective, chrome: Chrome) { +export function convertDirectiveToRenderFn( + directive: AngularDirective, + getInjector: () => Promise +) { return (domNode: Element, props: DocViewRenderProps) => { let rejected = false; @@ -78,7 +77,7 @@ export function convertDirectiveToRenderFn(directive: AngularDirective, chrome: directive.template, props, directive.controller, - chrome + getInjector ); cleanupFnPromise.catch(e => { rejected = true; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_registry.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_registry.ts index 1952ec3af2f6cd..91acf1c7ac4aef 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_registry.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_registry.ts @@ -16,14 +16,15 @@ * specific language governing permissions and limitations * under the License. */ + +import { auto } from 'angular'; import { convertDirectiveToRenderFn } from './doc_views_helpers'; import { DocView, DocViewInput, ElasticSearchHit, DocViewInputFn } from './doc_views_types'; -import { Chrome } from '../../kibana_services'; export class DocViewsRegistry { private docViews: DocView[] = []; - constructor(private legacyChrome: Chrome) {} + constructor(private getInjector: () => Promise) {} /** * Extends and adds the given doc view to the registry array @@ -32,7 +33,7 @@ export class DocViewsRegistry { const docView = typeof docViewRaw === 'function' ? docViewRaw() : docViewRaw; if (docView.directive) { // convert angular directive to render function for backwards compatibility - docView.render = convertDirectiveToRenderFn(docView.directive, this.legacyChrome); + docView.render = convertDirectiveToRenderFn(docView.directive, this.getInjector); } if (typeof docView.shouldShow !== 'function') { docView.shouldShow = () => true; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_types.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_types.ts index 92e18e7ea7b888..a7828f9f0e7ed1 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_types.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/doc_views/doc_views_types.ts @@ -27,8 +27,6 @@ export interface AngularDirective { export type AngularScope = IScope; -export type AngularController = (scope: AngularScope) => void; - export type ElasticSearchHit = Record>; export interface FieldMapping { diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable.ts index 3aa8dea816694f..c840f1fbd87ed1 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable.ts @@ -266,7 +266,11 @@ export class SearchEmbeddable extends Embeddable searchSource.setField('size', getServices().uiSettings.get('discover:sampleSize')); searchSource.setField( 'sort', - getSortForSearchSource(this.searchScope.sort, this.searchScope.indexPattern) + getSortForSearchSource( + this.searchScope.sort, + this.searchScope.indexPattern, + getServices().uiSettings.get('discover:sort:defaultOrder') + ) ); // Log request to inspector diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable_factory.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable_factory.ts index 3226b3af93cee6..842ef2bf9c825e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable_factory.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable_factory.ts @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ + +import { auto } from 'angular'; import { i18n } from '@kbn/i18n'; import { TExecuteTriggerActions } from 'src/plugins/ui_actions/public'; -import { getServices, IInjector } from '../../kibana_services'; +import { getServices } from '../../kibana_services'; import { EmbeddableFactory, ErrorEmbeddable, @@ -36,13 +38,13 @@ export class SearchEmbeddableFactory extends EmbeddableFactory< SearchEmbeddable > { public readonly type = SEARCH_EMBEDDABLE_TYPE; - private $injector: IInjector | null; - private getInjector: () => Promise | null; + private $injector: auto.IInjectorService | null; + private getInjector: () => Promise | null; public isEditable: () => boolean; constructor( private readonly executeTriggerActions: TExecuteTriggerActions, - getInjector: () => Promise, + getInjector: () => Promise, isEditable: () => boolean ) { super({ @@ -77,7 +79,7 @@ export class SearchEmbeddableFactory extends EmbeddableFactory< if (!this.$injector) { this.$injector = await this.getInjector(); } - const $injector = this.$injector as IInjector; + const $injector = this.$injector as auto.IInjectorService; const $compile = $injector.get('$compile'); const $rootScope = $injector.get('$rootScope'); diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts index 8f1eb7ef755597..0897f62574e935 100644 --- a/src/legacy/core_plugins/kibana/public/discover/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -18,14 +18,14 @@ */ import { i18n } from '@kbn/i18n'; import { AppMountParameters, CoreSetup, CoreStart, Plugin } from 'kibana/public'; -import angular from 'angular'; +import angular, { auto } from 'angular'; import { IUiActionsSetup, IUiActionsStart } from 'src/plugins/ui_actions/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { registerFeature } from './np_ready/register_feature'; import './kibana_services'; import { IEmbeddableStart, IEmbeddableSetup } from '../../../../../plugins/embeddable/public'; import { getInnerAngularModule, getInnerAngularModuleEmbeddable } from './get_inner_angular'; -import { Chrome, setAngularModule, setServices } from './kibana_services'; +import { setAngularModule, setServices } from './kibana_services'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; import { EuiUtilsStart } from '../../../../../plugins/eui_utils/public'; import { buildServices } from './build_services'; @@ -50,9 +50,6 @@ export interface DiscoverSetupPlugins { uiActions: IUiActionsSetup; embeddable: IEmbeddableSetup; kibana_legacy: KibanaLegacySetup; - __LEGACY: { - chrome: Chrome; - }; home: HomePublicPluginSetup; } export interface DiscoverStartPlugins { @@ -76,15 +73,18 @@ export class DiscoverPlugin implements Plugin { private servicesInitialized: boolean = false; private innerAngularInitialized: boolean = false; private docViewsRegistry: DocViewsRegistry | null = null; + private embeddableInjector: auto.IInjectorService | null = null; + private getEmbeddableInjector: (() => Promise) | null = null; /** * why are those functions public? they are needed for some mocha tests * can be removed once all is Jest */ public initializeInnerAngular?: () => void; - public initializeServices?: () => void; + public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>; setup(core: CoreSetup, plugins: DiscoverSetupPlugins): DiscoverSetup { - this.docViewsRegistry = new DocViewsRegistry(plugins.__LEGACY.chrome); + this.getEmbeddableInjector = this.getInjector.bind(this); + this.docViewsRegistry = new DocViewsRegistry(this.getEmbeddableInjector); this.docViewsRegistry.addDocView({ title: i18n.translate('kbn.discover.docViews.table.tableTitle', { defaultMessage: 'Table', @@ -113,6 +113,7 @@ export class DiscoverPlugin implements Plugin { } await this.initializeServices(); await this.initializeInnerAngular(); + const { renderApp } = await import('./np_ready/application'); return renderApp(innerAngularName, params.element); }, @@ -141,11 +142,13 @@ export class DiscoverPlugin implements Plugin { this.initializeServices = async () => { if (this.servicesInitialized) { - return; + return { core, plugins }; } const services = await buildServices(core, plugins, this.docViewsRegistry!); setServices(services); this.servicesInitialized = true; + + return { core, plugins }; }; this.registerEmbeddable(core, plugins); @@ -156,22 +159,31 @@ export class DiscoverPlugin implements Plugin { */ private async registerEmbeddable(core: CoreStart, plugins: DiscoverStartPlugins) { const { SearchEmbeddableFactory } = await import('./np_ready/embeddable'); - const getInjector = async () => { - if (!this.initializeServices) { - throw Error('Discover plugin registerEmbeddable: initializeServices is undefined'); - } - await this.initializeServices(); - getInnerAngularModuleEmbeddable(embeddableAngularName, core, plugins); - const mountpoint = document.createElement('div'); - return angular.bootstrap(mountpoint, [embeddableAngularName]); - }; const isEditable = () => core.application.capabilities.discover.save as boolean; + if (!this.getEmbeddableInjector) { + throw Error('Discover plugin method getEmbeddableInjector is undefined'); + } + const factory = new SearchEmbeddableFactory( plugins.uiActions.executeTriggerActions, - getInjector, + this.getEmbeddableInjector, isEditable ); plugins.embeddable.registerEmbeddableFactory(factory.type, factory); } + + private async getInjector() { + if (!this.embeddableInjector) { + if (!this.initializeServices) { + throw Error('Discover plugin getEmbeddableInjector: initializeServices is undefined'); + } + const { core, plugins } = await this.initializeServices(); + getInnerAngularModuleEmbeddable(embeddableAngularName, core, plugins); + const mountpoint = document.createElement('div'); + this.embeddableInjector = angular.bootstrap(mountpoint, [embeddableAngularName]); + } + + return this.embeddableInjector; + } } diff --git a/src/legacy/core_plugins/kibana/public/discover/saved_searches/index.ts b/src/legacy/core_plugins/kibana/public/discover/saved_searches/index.ts index 1dd99025b4b70e..24832df308a3ed 100644 --- a/src/legacy/core_plugins/kibana/public/discover/saved_searches/index.ts +++ b/src/legacy/core_plugins/kibana/public/discover/saved_searches/index.ts @@ -18,4 +18,3 @@ */ export * from './saved_searches'; -import './saved_searches_register'; diff --git a/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_searches.ts b/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_searches.ts index abd3d46820c185..0b346524610262 100644 --- a/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_searches.ts +++ b/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_searches.ts @@ -20,7 +20,7 @@ import { SavedObjectLoader } from 'ui/saved_objects'; import { SavedObjectKibanaServices } from 'ui/saved_objects/types'; import { createSavedSearchClass } from './_saved_search'; -export function createSavedSearchesService(services: SavedObjectKibanaServices) { +export function createSavedSearchesLoader(services: SavedObjectKibanaServices) { const SavedSearchClass = createSavedSearchClass(services); const savedSearchLoader = new SavedObjectLoader( SavedSearchClass, diff --git a/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_searches_register.ts b/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_searches_register.ts deleted file mode 100644 index ab7894fd5e730b..00000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_searches_register.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { npStart } from 'ui/new_platform'; -// @ts-ignore -import { uiModules } from 'ui/modules'; -// @ts-ignore -import { savedObjectManagementRegistry } from '../../management/saved_object_registry'; - -import { createSavedSearchesService } from './saved_searches'; - -// this is needed for saved object management -// Register this service with the saved object registry so it can be -// edited by the object editor. -savedObjectManagementRegistry.register({ - service: 'savedSearches', - title: 'searches', -}); -const services = { - savedObjectsClient: npStart.core.savedObjects.client, - indexPatterns: npStart.plugins.data.indexPatterns, - chrome: npStart.core.chrome, - overlays: npStart.core.overlays, -}; -const savedSearches = createSavedSearchesService(services); - -const module = uiModules.get('discover/saved_searches'); -module.service('savedSearches', () => savedSearches); diff --git a/src/legacy/core_plugins/kibana/public/home/index.ts b/src/legacy/core_plugins/kibana/public/home/index.ts index b2d90f1444654a..27d09a53ba20dc 100644 --- a/src/legacy/core_plugins/kibana/public/home/index.ts +++ b/src/legacy/core_plugins/kibana/public/home/index.ts @@ -22,11 +22,8 @@ import { npSetup, npStart } from 'ui/new_platform'; import chrome from 'ui/chrome'; import { IPrivate } from 'ui/private'; import { HomePlugin, LegacyAngularInjectedDependencies } from './plugin'; -import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public'; import { TelemetryOptInProvider } from '../../../telemetry/public/services'; -export const trackUiMetric = createUiStatsReporter('Kibana_home'); - /** * Get dependencies relying on the global angular context. * They also have to get resolved together with the legacy imports above @@ -54,9 +51,7 @@ let copiedLegacyCatalogue = false; instance.setup(npSetup.core, { ...npSetup.plugins, __LEGACY: { - trackUiMetric, metadata: npStart.core.injectedMetadata.getLegacyMetadata(), - METRIC_TYPE, getFeatureCatalogueEntries: async () => { if (!copiedLegacyCatalogue) { const injector = await chrome.dangerouslyGetActiveInjector(); diff --git a/src/legacy/core_plugins/kibana/public/home/kibana_services.ts b/src/legacy/core_plugins/kibana/public/home/kibana_services.ts index 0eb55a3902edac..4d9177735556df 100644 --- a/src/legacy/core_plugins/kibana/public/home/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/home/kibana_services.ts @@ -55,7 +55,6 @@ export interface HomeKibanaServices { savedObjectsClient: SavedObjectsClientContract; toastNotifications: NotificationsSetup['toasts']; banners: OverlayStart['banners']; - METRIC_TYPE: any; trackUiMetric: (type: UiStatsMetricType, eventNames: string | string[], count?: number) => void; getBasePath: () => string; shouldShowTelemetryOptIn: boolean; diff --git a/src/legacy/core_plugins/kibana/public/home/np_ready/components/home.test.js b/src/legacy/core_plugins/kibana/public/home/np_ready/components/home.test.js index be2ceb66f69d03..27d4f1a8b1c1fa 100644 --- a/src/legacy/core_plugins/kibana/public/home/np_ready/components/home.test.js +++ b/src/legacy/core_plugins/kibana/public/home/np_ready/components/home.test.js @@ -129,8 +129,8 @@ describe('home', () => { test('should not render directory entry when showOnHomePage is false', async () => { const directoryEntry = { - id: 'management', - title: 'Management', + id: 'stack-management', + title: 'Stack Management', description: 'Your center console for managing the Elastic Stack.', icon: 'managementApp', path: 'management_landing_page', diff --git a/src/legacy/core_plugins/kibana/public/home/np_ready/components/tutorial/instruction_set.js b/src/legacy/core_plugins/kibana/public/home/np_ready/components/tutorial/instruction_set.js index 4f60de00819e71..15bda335341858 100644 --- a/src/legacy/core_plugins/kibana/public/home/np_ready/components/tutorial/instruction_set.js +++ b/src/legacy/core_plugins/kibana/public/home/np_ready/components/tutorial/instruction_set.js @@ -22,7 +22,7 @@ import PropTypes from 'prop-types'; import { Instruction } from './instruction'; import { ParameterForm } from './parameter_form'; import { Content } from './content'; -import { getDisplayText } from '../../../../../common/tutorials/instruction_variant'; +import { getDisplayText } from '../../../../../../../../plugins/home/server/tutorials/instructions/instruction_variant'; import { EuiTabs, EuiTab, diff --git a/src/legacy/core_plugins/kibana/public/home/np_ready/components/welcome.test.tsx b/src/legacy/core_plugins/kibana/public/home/np_ready/components/welcome.test.tsx index 28bdab14193c40..55c469fa58fc61 100644 --- a/src/legacy/core_plugins/kibana/public/home/np_ready/components/welcome.test.tsx +++ b/src/legacy/core_plugins/kibana/public/home/np_ready/components/welcome.test.tsx @@ -25,10 +25,6 @@ jest.mock('../../kibana_services', () => ({ getServices: () => ({ addBasePath: (path: string) => `root${path}`, trackUiMetric: () => {}, - METRIC_TYPE: { - LOADED: 'loaded', - CLICK: 'click', - }, }), })); diff --git a/src/legacy/core_plugins/kibana/public/home/np_ready/components/welcome.tsx b/src/legacy/core_plugins/kibana/public/home/np_ready/components/welcome.tsx index 9bbb7aaceb915b..1b7761d068d2f2 100644 --- a/src/legacy/core_plugins/kibana/public/home/np_ready/components/welcome.tsx +++ b/src/legacy/core_plugins/kibana/public/home/np_ready/components/welcome.tsx @@ -35,6 +35,7 @@ import { EuiIcon, EuiPortal, } from '@elastic/eui'; +import { METRIC_TYPE } from '@kbn/analytics'; import { FormattedMessage } from '@kbn/i18n/react'; import { getServices } from '../../kibana_services'; @@ -64,17 +65,17 @@ export class Welcome extends React.Component { } private onSampleDataDecline = () => { - this.services.trackUiMetric(this.services.METRIC_TYPE.CLICK, 'sampleDataDecline'); + this.services.trackUiMetric(METRIC_TYPE.CLICK, 'sampleDataDecline'); this.props.onSkip(); }; private onSampleDataConfirm = () => { - this.services.trackUiMetric(this.services.METRIC_TYPE.CLICK, 'sampleDataConfirm'); + this.services.trackUiMetric(METRIC_TYPE.CLICK, 'sampleDataConfirm'); this.redirecToSampleData(); }; componentDidMount() { - this.services.trackUiMetric(this.services.METRIC_TYPE.LOADED, 'welcomeScreenMount'); + this.services.trackUiMetric(METRIC_TYPE.LOADED, 'welcomeScreenMount'); this.props.onOptInSeen(); document.addEventListener('keydown', this.hideOnEsc); } diff --git a/src/legacy/core_plugins/kibana/public/home/np_ready/load_tutorials.js b/src/legacy/core_plugins/kibana/public/home/np_ready/load_tutorials.js index 6a0a01ebda8db9..2f6d4d631baf58 100644 --- a/src/legacy/core_plugins/kibana/public/home/np_ready/load_tutorials.js +++ b/src/legacy/core_plugins/kibana/public/home/np_ready/load_tutorials.js @@ -21,7 +21,6 @@ import _ from 'lodash'; import { getServices } from '../kibana_services'; import { i18n } from '@kbn/i18n'; -const baseUrlLP = getServices().addBasePath('/api/kibana/home/tutorials_LP'); const baseUrl = getServices().addBasePath('/api/kibana/home/tutorials'); const headers = new Headers(); headers.append('Accept', 'application/json'); @@ -29,42 +28,25 @@ headers.append('Content-Type', 'application/json'); headers.append('kbn-xsrf', 'kibana'); let tutorials = []; -let tutorialsLegacyPlatform = []; -let tutorialsNewPlatform = []; let tutorialsLoaded = false; async function loadTutorials() { try { - const responseLegacyPlatform = await fetch(baseUrlLP, { + const response = await fetch(baseUrl, { method: 'get', credentials: 'include', headers: headers, }); - if (responseLegacyPlatform.status >= 300) { + if (response.status >= 300) { throw new Error( i18n.translate('kbn.home.loadTutorials.requestFailedErrorMessage', { defaultMessage: 'Request failed with status code: {status}', - values: { status: responseLegacyPlatform.status }, - }) - ); - } - const responseNewPlatform = await fetch(baseUrl, { - method: 'get', - credentials: 'include', - headers: headers, - }); - if (responseNewPlatform.status >= 300) { - throw new Error( - i18n.translate('kbn.home.loadTutorials.requestFailedErrorMessage', { - defaultMessage: 'Request failed with status code: {status}', - values: { status: responseNewPlatform.status }, + values: { status: response.status }, }) ); } - tutorialsLegacyPlatform = await responseLegacyPlatform.json(); - tutorialsNewPlatform = await responseNewPlatform.json(); - tutorials = tutorialsLegacyPlatform.concat(tutorialsNewPlatform); + tutorials = await response.json(); tutorialsLoaded = true; } catch (err) { getServices().toastNotifications.addDanger({ diff --git a/src/legacy/core_plugins/kibana/public/home/plugin.ts b/src/legacy/core_plugins/kibana/public/home/plugin.ts index 42ab049eb5b3a8..502c8f45646cf0 100644 --- a/src/legacy/core_plugins/kibana/public/home/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/home/plugin.ts @@ -18,11 +18,11 @@ */ import { CoreSetup, CoreStart, LegacyNavLink, Plugin, UiSettingsState } from 'kibana/public'; -import { UiStatsMetricType } from '@kbn/analytics'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { setServices } from './kibana_services'; import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public'; +import { UsageCollectionSetup } from '../../../../../plugins/usage_collection/public'; import { Environment, FeatureCatalogueEntry, @@ -41,8 +41,6 @@ export interface HomePluginStartDependencies { export interface HomePluginSetupDependencies { __LEGACY: { - trackUiMetric: (type: UiStatsMetricType, eventNames: string | string[], count?: number) => void; - METRIC_TYPE: any; metadata: { app: unknown; bundleId: string; @@ -59,6 +57,7 @@ export interface HomePluginSetupDependencies { getFeatureCatalogueEntries: () => Promise; getAngularDependencies: () => Promise; }; + usageCollection: UsageCollectionSetup; kibana_legacy: KibanaLegacySetup; } @@ -71,6 +70,7 @@ export class HomePlugin implements Plugin { core: CoreSetup, { kibana_legacy, + usageCollection, __LEGACY: { getAngularDependencies, ...legacyServices }, }: HomePluginSetupDependencies ) { @@ -78,9 +78,11 @@ export class HomePlugin implements Plugin { id: 'home', title: 'Home', mount: async ({ core: contextCore }, params) => { + const trackUiMetric = usageCollection.reportUiStats.bind(usageCollection, 'Kibana_home'); const angularDependencies = await getAngularDependencies(); setServices({ ...legacyServices, + trackUiMetric, http: contextCore.http, toastNotifications: core.notifications.toasts, banners: contextCore.overlays.banners, diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg new file mode 100644 index 00000000000000..f4458439fceb4b --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg @@ -0,0 +1,41 @@ + + + + + + + + + + diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/stan_metrics/screenshot.png b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/stan_metrics/screenshot.png new file mode 100644 index 00000000000000..a6ed419fe885b0 Binary files /dev/null and b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/stan_metrics/screenshot.png differ diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index 4100ae72058699..bd947b9cb9d7f1 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -47,9 +47,9 @@ import 'uiExports/interpreter'; import 'ui/autoload/all'; import 'ui/kbn_top_nav'; import './home'; -import './discover'; -import './visualize'; -import './dashboard'; +import './discover/legacy'; +import './visualize/legacy'; +import './dashboard/legacy'; import './management'; import './dev_tools'; import 'ui/color_maps'; diff --git a/src/legacy/core_plugins/kibana/public/management/index.js b/src/legacy/core_plugins/kibana/public/management/index.js index d62770956b88ef..1305310b6f6151 100644 --- a/src/legacy/core_plugins/kibana/public/management/index.js +++ b/src/legacy/core_plugins/kibana/public/management/index.js @@ -74,7 +74,7 @@ export function updateLandingPage(version) {

@@ -93,7 +93,7 @@ export function updateLandingPage(version) {

@@ -173,11 +173,11 @@ uiModules.get('apps/management').directive('kbnManagementLanding', function(kbnV FeatureCatalogueRegistryProvider.register(() => { return { - id: 'management', - title: i18n.translate('kbn.management.managementLabel', { - defaultMessage: 'Management', + id: 'stack-management', + title: i18n.translate('kbn.stackManagement.managementLabel', { + defaultMessage: 'Stack Management', }), - description: i18n.translate('kbn.management.managementDescription', { + description: i18n.translate('kbn.stackManagement.managementDescription', { defaultMessage: 'Your center console for managing the Elastic Stack.', }), icon: 'managementApp', diff --git a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.js b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.js deleted file mode 100644 index 978459dea7c2d6..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -const registry = []; -export const savedObjectManagementRegistry = { - register: function(service) { - registry.push(service); - }, - all: function() { - return registry; - }, - get: function(id) { - return _.find(registry, { service: id }); - }, -}; diff --git a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts new file mode 100644 index 00000000000000..0a6ac205026693 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts @@ -0,0 +1,80 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _ from 'lodash'; +import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; +import { SavedObjectLoader } from 'ui/saved_objects'; +import { createSavedDashboardLoader } from '../dashboard'; +import { createSavedSearchesLoader } from '../discover'; +import { TypesService, createSavedVisLoader } from '../../../visualizations/public'; + +/** + * This registry is used for the editing mode of Saved Searches, Visualizations, + * Dashboard and Time Lion saved objects. + */ +interface SavedObjectRegistryEntry { + id: string; + service: SavedObjectLoader; + title: string; +} + +const registry: SavedObjectRegistryEntry[] = []; + +export const savedObjectManagementRegistry = { + register: (service: SavedObjectRegistryEntry) => { + registry.push(service); + }, + all: () => { + return registry; + }, + get: (id: string) => { + return _.find(registry, { id }); + }, +}; + +const services = { + savedObjectsClient: npStart.core.savedObjects.client, + indexPatterns: npStart.plugins.data.indexPatterns, + chrome: npStart.core.chrome, + overlays: npStart.core.overlays, +}; + +savedObjectManagementRegistry.register({ + id: 'savedVisualizations', + service: createSavedVisLoader({ + ...services, + ...{ visualizationTypes: new TypesService().start() }, + }), + title: 'visualizations', +}); + +savedObjectManagementRegistry.register({ + id: 'savedDashboards', + service: createSavedDashboardLoader(services), + title: i18n.translate('kbn.dashboard.savedDashboardsTitle', { + defaultMessage: 'dashboards', + }), +}); + +savedObjectManagementRegistry.register({ + id: 'savedSearches', + service: createSavedSearchesLoader(services), + title: 'searches', +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js index 754fda2a6fe5ac..d1087b4575e828 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js @@ -17,7 +17,6 @@ * under the License. */ -import { SavedObjectsClientProvider } from 'ui/saved_objects'; import uiRoutes from 'ui/routes'; import angularTemplate from './angular_template.html'; import { npStart } from 'ui/new_platform'; @@ -32,18 +31,17 @@ uiRoutes.when('/management/kibana/index_pattern', { controller: function($scope, $injector) { // Wait for the directives to execute const kbnUrl = $injector.get('kbnUrl'); - const Private = $injector.get('Private'); $scope.$$postDigest(() => { const $routeParams = $injector.get('$routeParams'); const indexPatternCreationType = managementSetup.indexPattern.creation.getType( $routeParams.type ); const services = { - config: $injector.get('config'), - es: $injector.get('es'), + config: npStart.core.uiSettings, + es: npStart.plugins.data.search.__LEGACY.esClient, indexPatterns: npStart.plugins.data.indexPatterns, - $http: $injector.get('$http'), - savedObjectsClient: Private(SavedObjectsClientProvider), + $http: npStart.core.http, + savedObjectsClient: npStart.core.savedObjects.client, indexPatternCreationType, confirmModalPromise: $injector.get('confirmModalPromise'), changeUrl: url => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js index a663e9d626f88e..8ab26f8c0d1c83 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js @@ -26,7 +26,7 @@ import { uiModules } from 'ui/modules'; import indexTemplate from './index.html'; import indexPatternListTemplate from './list.html'; import { IndexPatternTable } from './index_pattern_table'; -import { SavedObjectsClientProvider } from 'ui/saved_objects'; +import { npStart } from 'ui/new_platform'; import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory, @@ -67,8 +67,8 @@ export const destroyIndexPatternList = () => { }; const indexPatternsResolutions = { - indexPatterns: function(Private) { - const savedObjectsClient = Private(SavedObjectsClientProvider); + indexPatterns: function() { + const savedObjectsClient = npStart.core.savedObjects.client; return savedObjectsClient .find({ diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js index 6d3980d9d53f91..c16e4cb00c2bdb 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js @@ -21,7 +21,6 @@ import { savedObjectManagementRegistry } from '../../saved_object_registry'; import objectIndexHTML from './_objects.html'; import uiRoutes from 'ui/routes'; import chrome from 'ui/chrome'; -import { SavedObjectsClientProvider } from 'ui/saved_objects'; import { uiModules } from 'ui/modules'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; @@ -35,15 +34,14 @@ import { getIndexBreadcrumbs } from './breadcrumbs'; const REACT_OBJECTS_TABLE_DOM_ELEMENT_ID = 'reactSavedObjectsTable'; function updateObjectsTable($scope, $injector) { - const Private = $injector.get('Private'); const indexPatterns = npStart.plugins.data.indexPatterns; const $http = $injector.get('$http'); const kbnUrl = $injector.get('kbnUrl'); const config = $injector.get('config'); const confirmModalPromise = $injector.get('confirmModalPromise'); - const savedObjectsClient = Private(SavedObjectsClientProvider); - const services = savedObjectManagementRegistry.all().map(obj => $injector.get(obj.service)); + const savedObjectsClient = npStart.core.savedObjects.client; + const services = savedObjectManagementRegistry.all().map(obj => obj.service); const uiCapabilites = npStart.core.application.capabilities; $scope.$$postDigest(() => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js index f7e654fd3c76dd..3205e28fe23142 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js @@ -28,9 +28,9 @@ import uiRoutes from 'ui/routes'; import { uiModules } from 'ui/modules'; import { fatalError, toastNotifications } from 'ui/notify'; import 'ui/accessibility/kbn_ui_ace_keyboard_mode'; -import { SavedObjectsClientProvider } from 'ui/saved_objects'; import { isNumeric } from './lib/numeric'; import { canViewInApp } from './lib/in_app_url'; +import { npStart } from 'ui/new_platform'; import { castEsToKbnFieldTypeName } from '../../../../../../../plugins/data/public'; @@ -49,19 +49,10 @@ uiModules .directive('kbnManagementObjectsView', function(kbnIndex, confirmModal) { return { restrict: 'E', - controller: function( - $scope, - $injector, - $routeParams, - $location, - $window, - $rootScope, - Private, - uiCapabilities - ) { + controller: function($scope, $routeParams, $location, $window, $rootScope, uiCapabilities) { const serviceObj = savedObjectManagementRegistry.get($routeParams.service); - const service = $injector.get(serviceObj.service); - const savedObjectsClient = Private(SavedObjectsClientProvider); + const service = serviceObj.service; + const savedObjectsClient = npStart.core.savedObjects.client; /** * Creates a field definition and pushes it to the memo stack. This function @@ -177,12 +168,15 @@ uiModules // sorts twice since we want numerical sort to prioritize over name, // and sortBy will do string comparison if trying to match against strings const nameSortedFields = _.sortBy(fields, 'name'); - $scope.fields = _.sortBy(nameSortedFields, field => { - const orderIndex = service.Class.fieldOrder - ? service.Class.fieldOrder.indexOf(field.name) - : -1; - return orderIndex > -1 ? orderIndex : Infinity; + $scope.$evalAsync(() => { + $scope.fields = _.sortBy(nameSortedFields, field => { + const orderIndex = service.Class.fieldOrder + ? service.Class.fieldOrder.indexOf(field.name) + : -1; + return orderIndex > -1 ? orderIndex : Infinity; + }); }); + $scope.$digest(); }) .catch(error => fatalError(error, location)); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/breadcrumbs.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/breadcrumbs.js index 49e57a7c40b16c..e9082bfeb680d0 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/breadcrumbs.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/breadcrumbs.js @@ -34,9 +34,9 @@ export function getIndexBreadcrumbs() { ]; } -export function getViewBreadcrumbs($routeParams, $injector) { +export function getViewBreadcrumbs($routeParams) { const serviceObj = savedObjectManagementRegistry.get($routeParams.service); - const service = $injector.get(serviceObj.service); + const { service } = serviceObj; return [ ...getIndexBreadcrumbs(), diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.js.snap deleted file mode 100644 index eef8f3fc93d90f..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.js.snap +++ /dev/null @@ -1,1022 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AdvancedSettings should render normally 1`] = ` -
- - - - - - - - - - - - - -
- -
-`; - -exports[`AdvancedSettings should render read-only when saving is disabled 1`] = ` -
- - - - - - - - - - - - - - - -
-`; - -exports[`AdvancedSettings should render specific setting if given setting key 1`] = ` -
- - - - - - - - - - - - - - - -
-`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.tsx.snap new file mode 100644 index 00000000000000..4814432c832e2f --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.tsx.snap @@ -0,0 +1,367 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AdvancedSettings should render read-only when saving is disabled 1`] = ` +
+ + + + + + + + + + + + + + + +
+`; + +exports[`AdvancedSettings should render specific setting if given setting key 1`] = ` +
+ + + + + + + + + + + + + + + +
+`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.js deleted file mode 100644 index 508e05bbf9bb40..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.js +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - -import { Comparators, EuiFlexGroup, EuiFlexItem, EuiSpacer, Query } from '@elastic/eui'; - -import { CallOuts } from './components/call_outs'; -import { Search } from './components/search'; -import { Form } from './components/form'; -import { AdvancedSettingsVoiceAnnouncement } from './components/advanced_settings_voice_announcement'; - -import { getAriaName, toEditableConfig, DEFAULT_CATEGORY } from './lib'; - -import { - registerDefaultComponents, - PAGE_TITLE_COMPONENT, - PAGE_SUBTITLE_COMPONENT, - PAGE_FOOTER_COMPONENT, -} from './components/default_component_registry'; -import { getSettingsComponent } from './components/component_registry'; - -export class AdvancedSettings extends Component { - static propTypes = { - config: PropTypes.object.isRequired, - query: PropTypes.string, - enableSaving: PropTypes.bool.isRequired, - }; - - constructor(props) { - super(props); - const { config, query } = this.props; - const parsedQuery = Query.parse(query ? `ariaName:"${getAriaName(query)}"` : ''); - this.init(config); - this.state = { - query: parsedQuery, - footerQueryMatched: false, - filteredSettings: this.mapSettings(Query.execute(parsedQuery, this.settings)), - }; - - registerDefaultComponents(); - } - - init(config) { - this.settings = this.mapConfig(config); - this.groupedSettings = this.mapSettings(this.settings); - - this.categories = Object.keys(this.groupedSettings).sort((a, b) => { - if (a === DEFAULT_CATEGORY) return -1; - if (b === DEFAULT_CATEGORY) return 1; - if (a > b) return 1; - return a === b ? 0 : -1; - }); - - this.categoryCounts = Object.keys(this.groupedSettings).reduce((counts, category) => { - counts[category] = this.groupedSettings[category].length; - return counts; - }, {}); - } - - UNSAFE_componentWillReceiveProps(nextProps) { - const { config } = nextProps; - const { query } = this.state; - - this.init(config); - this.setState({ - filteredSettings: this.mapSettings(Query.execute(query, this.settings)), - }); - } - - mapConfig(config) { - const all = config.getAll(); - return Object.entries(all) - .map(setting => { - return toEditableConfig({ - def: setting[1], - name: setting[0], - value: setting[1].userValue, - isCustom: config.isCustom(setting[0]), - isOverridden: config.isOverridden(setting[0]), - }); - }) - .filter(c => !c.readonly) - .sort(Comparators.property('name', Comparators.default('asc'))); - } - - mapSettings(settings) { - // Group settings by category - return settings.reduce((groupedSettings, setting) => { - // We will want to change this logic when we put each category on its - // own page aka allowing a setting to be included in multiple categories. - const category = setting.category[0]; - (groupedSettings[category] = groupedSettings[category] || []).push(setting); - return groupedSettings; - }, {}); - } - - saveConfig = (name, value) => { - return this.props.config.set(name, value); - }; - - clearConfig = name => { - return this.props.config.remove(name); - }; - - onQueryChange = ({ query }) => { - this.setState({ - query, - filteredSettings: this.mapSettings(Query.execute(query, this.settings)), - }); - }; - - clearQuery = () => { - this.setState({ - query: Query.parse(''), - footerQueryMatched: false, - filteredSettings: this.groupedSettings, - }); - }; - - onFooterQueryMatchChange = matched => { - this.setState({ - footerQueryMatched: matched, - }); - }; - - render() { - const { filteredSettings, query, footerQueryMatched } = this.state; - - const PageTitle = getSettingsComponent(PAGE_TITLE_COMPONENT); - const PageSubtitle = getSettingsComponent(PAGE_SUBTITLE_COMPONENT); - const PageFooter = getSettingsComponent(PAGE_FOOTER_COMPONENT); - - return ( -
- - - - - - - - - - - - - - - - - -
- ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.js deleted file mode 100644 index 94128dc5271de1..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.js +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { shallow } from 'enzyme'; -import dedent from 'dedent'; - -import { AdvancedSettings } from './advanced_settings'; - -jest.mock('./components/field', () => ({ - Field: () => { - return 'field'; - }, -})); - -jest.mock('./components/call_outs', () => ({ - CallOuts: () => { - return 'callOuts'; - }, -})); - -jest.mock('./components/search', () => ({ - Search: () => { - return 'search'; - }, -})); - -const config = { - set: () => {}, - remove: () => {}, - isCustom: setting => setting.isCustom, - isOverridden: key => Boolean(config.getAll()[key].isOverridden), - getAll: () => { - return { - 'test:array:setting': { - value: ['default_value'], - name: 'Test array setting', - description: 'Description for Test array setting', - category: ['elasticsearch'], - }, - 'test:boolean:setting': { - value: true, - name: 'Test boolean setting', - description: 'Description for Test boolean setting', - category: ['elasticsearch'], - }, - 'test:image:setting': { - value: null, - name: 'Test image setting', - description: 'Description for Test image setting', - type: 'image', - }, - 'test:json:setting': { - value: '{"foo": "bar"}', - name: 'Test json setting', - description: 'Description for Test json setting', - type: 'json', - }, - 'test:markdown:setting': { - value: '', - name: 'Test markdown setting', - description: 'Description for Test markdown setting', - type: 'markdown', - }, - 'test:number:setting': { - value: 5, - name: 'Test number setting', - description: 'Description for Test number setting', - }, - 'test:select:setting': { - value: 'orange', - name: 'Test select setting', - description: 'Description for Test select setting', - type: 'select', - options: ['apple', 'orange', 'banana'], - }, - 'test:string:setting': { - value: null, - name: 'Test string setting', - description: 'Description for Test string setting', - type: 'string', - isCustom: true, - }, - 'test:readonlystring:setting': { - value: null, - name: 'Test readonly string setting', - description: 'Description for Test readonly string setting', - type: 'string', - readonly: true, - }, - 'test:customstring:setting': { - value: null, - name: 'Test custom string setting', - description: 'Description for Test custom string setting', - type: 'string', - isCustom: true, - }, - 'test:isOverridden:string': { - isOverridden: true, - value: 'foo', - name: 'An overridden string', - description: 'Description for overridden string', - type: 'string', - }, - 'test:isOverridden:number': { - isOverridden: true, - value: 1234, - name: 'An overridden number', - description: 'Description for overridden number', - type: 'number', - }, - 'test:isOverridden:json': { - isOverridden: true, - value: dedent` - { - "foo": "bar" - } - `, - name: 'An overridden json', - description: 'Description for overridden json', - type: 'json', - }, - 'test:isOverridden:select': { - isOverridden: true, - value: 'orange', - name: 'Test overridden select setting', - description: 'Description for overridden select setting', - type: 'select', - options: ['apple', 'orange', 'banana'], - }, - }; - }, -}; - -describe('AdvancedSettings', () => { - it('should render normally', async () => { - const component = shallow(); - - expect(component).toMatchSnapshot(); - }); - - it('should render specific setting if given setting key', async () => { - const component = shallow( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should render read-only when saving is disabled', async () => { - const component = shallow( - - ); - - expect(component).toMatchSnapshot(); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.tsx new file mode 100644 index 00000000000000..2a75c98b721bca --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.tsx @@ -0,0 +1,237 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { Observable } from 'rxjs'; +import { shallow } from 'enzyme'; +import dedent from 'dedent'; +import { + UiSettingsParams, + UserProvidedValues, + UiSettingsType, +} from '../../../../../../../core/public'; +import { FieldSetting } from './types'; +import { AdvancedSettings } from './advanced_settings'; + +jest.mock('ui/new_platform', () => ({ + npStart: mockConfig(), +})); + +jest.mock('./components/field', () => ({ + Field: () => { + return 'field'; + }, +})); + +jest.mock('./components/call_outs', () => ({ + CallOuts: () => { + return 'callOuts'; + }, +})); + +jest.mock('./components/search', () => ({ + Search: () => { + return 'search'; + }, +})); + +function mockConfig() { + const defaultConfig: Partial = { + displayName: 'defaultName', + requiresPageReload: false, + isOverridden: false, + ariaName: 'ariaName', + readOnly: false, + isCustom: false, + defVal: 'defVal', + type: 'string' as UiSettingsType, + category: ['category'], + }; + + const config = { + set: (key: string, value: any) => Promise.resolve(true), + remove: (key: string) => Promise.resolve(true), + isCustom: (key: string) => false, + isOverridden: (key: string) => Boolean(config.getAll()[key].isOverridden), + getRegistered: () => ({} as Readonly>), + overrideLocalDefault: (key: string, value: any) => {}, + getUpdate$: () => + new Observable<{ + key: string; + newValue: any; + oldValue: any; + }>(), + isDeclared: (key: string) => true, + isDefault: (key: string) => true, + + getSaved$: () => + new Observable<{ + key: string; + newValue: any; + oldValue: any; + }>(), + + getUpdateErrors$: () => new Observable(), + get: (key: string, defaultOverride?: any): any => config.getAll()[key] || defaultOverride, + get$: (key: string) => new Observable(config.get(key)), + getAll: (): Readonly> => { + return { + 'test:array:setting': { + ...defaultConfig, + value: ['default_value'], + name: 'Test array setting', + description: 'Description for Test array setting', + category: ['elasticsearch'], + }, + 'test:boolean:setting': { + ...defaultConfig, + value: true, + name: 'Test boolean setting', + description: 'Description for Test boolean setting', + category: ['elasticsearch'], + }, + 'test:image:setting': { + ...defaultConfig, + value: null, + name: 'Test image setting', + description: 'Description for Test image setting', + type: 'image', + }, + 'test:json:setting': { + ...defaultConfig, + value: '{"foo": "bar"}', + name: 'Test json setting', + description: 'Description for Test json setting', + type: 'json', + }, + 'test:markdown:setting': { + ...defaultConfig, + value: '', + name: 'Test markdown setting', + description: 'Description for Test markdown setting', + type: 'markdown', + }, + 'test:number:setting': { + ...defaultConfig, + value: 5, + name: 'Test number setting', + description: 'Description for Test number setting', + }, + 'test:select:setting': { + ...defaultConfig, + value: 'orange', + name: 'Test select setting', + description: 'Description for Test select setting', + type: 'select', + options: ['apple', 'orange', 'banana'], + }, + 'test:string:setting': { + ...defaultConfig, + ...{ + value: null, + name: 'Test string setting', + description: 'Description for Test string setting', + type: 'string', + isCustom: true, + }, + }, + 'test:readonlystring:setting': { + ...defaultConfig, + ...{ + value: null, + name: 'Test readonly string setting', + description: 'Description for Test readonly string setting', + type: 'string', + readOnly: true, + }, + }, + 'test:customstring:setting': { + ...defaultConfig, + ...{ + value: null, + name: 'Test custom string setting', + description: 'Description for Test custom string setting', + type: 'string', + isCustom: true, + }, + }, + 'test:isOverridden:string': { + ...defaultConfig, + isOverridden: true, + value: 'foo', + name: 'An overridden string', + description: 'Description for overridden string', + type: 'string', + }, + 'test:isOverridden:number': { + ...defaultConfig, + isOverridden: true, + value: 1234, + name: 'An overridden number', + description: 'Description for overridden number', + type: 'number', + }, + 'test:isOverridden:json': { + ...defaultConfig, + isOverridden: true, + value: dedent` + { + "foo": "bar" + } + `, + name: 'An overridden json', + description: 'Description for overridden json', + type: 'json', + }, + 'test:isOverridden:select': { + ...defaultConfig, + isOverridden: true, + value: 'orange', + name: 'Test overridden select setting', + description: 'Description for overridden select setting', + type: 'select', + options: ['apple', 'orange', 'banana'], + }, + }; + }, + }; + return { + core: { + uiSettings: config, + }, + }; +} + +describe('AdvancedSettings', () => { + it('should render specific setting if given setting key', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render read-only when saving is disabled', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.tsx new file mode 100644 index 00000000000000..569ef73f2b4536 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/advanced_settings.tsx @@ -0,0 +1,209 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { Component } from 'react'; +import { Comparators, EuiFlexGroup, EuiFlexItem, EuiSpacer, Query } from '@elastic/eui'; + +import { npStart } from 'ui/new_platform'; +import { CallOuts } from './components/call_outs'; +import { Search } from './components/search'; +import { Form } from './components/form'; +import { AdvancedSettingsVoiceAnnouncement } from './components/advanced_settings_voice_announcement'; +import { IUiSettingsClient } from '../../../../../../../core/public/'; + +import { getAriaName, toEditableConfig, DEFAULT_CATEGORY } from './lib'; + +import { FieldSetting, IQuery } from './types'; + +import { + registerDefaultComponents, + PAGE_TITLE_COMPONENT, + PAGE_SUBTITLE_COMPONENT, + PAGE_FOOTER_COMPONENT, +} from './components/default_component_registry'; +import { getSettingsComponent } from './components/component_registry'; + +interface AdvancedSettingsProps { + queryText: string; + enableSaving: boolean; +} + +interface AdvancedSettingsState { + footerQueryMatched: boolean; + query: IQuery; + filteredSettings: Record; +} + +type GroupedSettings = Record; + +export class AdvancedSettings extends Component { + private config: IUiSettingsClient; + private settings: FieldSetting[]; + private groupedSettings: GroupedSettings; + private categoryCounts: Record; + private categories: string[] = []; + + constructor(props: AdvancedSettingsProps) { + super(props); + const { queryText } = this.props; + const parsedQuery = Query.parse(queryText ? `ariaName:"${getAriaName(queryText)}"` : ''); + + this.config = npStart.core.uiSettings; + this.settings = this.initSettings(this.config); + this.groupedSettings = this.initGroupedSettings(this.settings); + this.categories = this.initCategories(this.groupedSettings); + this.categoryCounts = this.initCategoryCounts(this.groupedSettings); + + this.state = { + query: parsedQuery, + footerQueryMatched: false, + filteredSettings: this.mapSettings(Query.execute(parsedQuery, this.settings)), + }; + + registerDefaultComponents(); + } + + init(config: IUiSettingsClient) { + this.settings = this.initSettings(config); + this.groupedSettings = this.initGroupedSettings(this.settings); + this.categories = this.initCategories(this.groupedSettings); + this.categoryCounts = this.initCategoryCounts(this.groupedSettings); + } + + initSettings = this.mapConfig; + initGroupedSettings = this.mapSettings; + initCategories(groupedSettings: GroupedSettings) { + return Object.keys(groupedSettings).sort((a, b) => { + if (a === DEFAULT_CATEGORY) return -1; + if (b === DEFAULT_CATEGORY) return 1; + if (a > b) return 1; + return a === b ? 0 : -1; + }); + } + initCategoryCounts(groupedSettings: GroupedSettings) { + return Object.keys(groupedSettings).reduce( + (counts: Record, category: string) => { + counts[category] = groupedSettings[category].length; + return counts; + }, + {} + ); + } + + componentDidMount() { + this.config.getUpdate$().subscribe(() => { + const { query } = this.state; + this.init(this.config); + this.setState({ + filteredSettings: this.mapSettings(Query.execute(query, this.settings)), + }); + }); + } + + mapConfig(config: IUiSettingsClient) { + const all = config.getAll(); + return Object.entries(all) + .map(setting => { + return toEditableConfig({ + def: setting[1], + name: setting[0], + value: setting[1].userValue, + isCustom: config.isCustom(setting[0]), + isOverridden: config.isOverridden(setting[0]), + }); + }) + .filter(c => !c.readonly) + .sort(Comparators.property('name', Comparators.default('asc'))); + } + + mapSettings(settings: FieldSetting[]) { + // Group settings by category + return settings.reduce((groupedSettings: GroupedSettings, setting) => { + // We will want to change this logic when we put each category on its + // own page aka allowing a setting to be included in multiple categories. + const category = setting.category[0]; + (groupedSettings[category] = groupedSettings[category] || []).push(setting); + return groupedSettings; + }, {}); + } + + onQueryChange = ({ query }: { query: IQuery }) => { + this.setState({ + query, + filteredSettings: this.mapSettings(Query.execute(query, this.settings)), + }); + }; + + clearQuery = () => { + this.setState({ + query: Query.parse(''), + footerQueryMatched: false, + filteredSettings: this.groupedSettings, + }); + }; + + onFooterQueryMatchChange = (matched: boolean) => { + this.setState({ + footerQueryMatched: matched, + }); + }; + + render() { + const { filteredSettings, query, footerQueryMatched } = this.state; + + const PageTitle = getSettingsComponent(PAGE_TITLE_COMPONENT); + const PageSubtitle = getSettingsComponent(PAGE_SUBTITLE_COMPONENT); + const PageFooter = getSettingsComponent(PAGE_FOOTER_COMPONENT); + + return ( +
+ + + + + + + + + + + + + + + + + +
+ ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/breadcrumbs.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/breadcrumbs.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/breadcrumbs.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/breadcrumbs.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/__snapshots__/component_registry.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/__snapshots__/component_registry.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/__snapshots__/component_registry.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/__snapshots__/component_registry.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.js.snap deleted file mode 100644 index 049e4530b795f9..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.js.snap +++ /dev/null @@ -1,51 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Advanced Settings: Voice Announcement should render announcement 1`] = ` - -
- - - -
-
-`; - -exports[`Advanced Settings: Voice Announcement should render nothing 1`] = ` - -
- - - -
-
-`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.tsx.snap new file mode 100644 index 00000000000000..e8c8184cf7e57c --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.tsx.snap @@ -0,0 +1,51 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Advanced Settings: Voice Announcement should render announcement 1`] = ` + +
+ + + +
+
+`; + +exports[`Advanced Settings: Voice Announcement should render nothing 1`] = ` + +
+ + + +
+
+`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.js deleted file mode 100644 index 34625e1ce5114f..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* - This component aims to insert assertive live region on the page, - to make sure that a screen reader announces layout changes. - - Due to the fact that it has a specific way of detecting what-and-when announce - as well as delay of announcement (which depends on what a user is doing at the moment) - I place a 500ms delay of re-render the text of anouncement. - That time period is best fits the time of screen reader reaction. - That anouncement depends on what user is typying into search box as well as - the speed of ordinary screen reader pronouns what user is typing before start reading this anouncement. - - The order of triggering functions: - 1: React trigs the component to be updated - 2: It places a timer and block render - 3: The time is over - 4: Component renders - - 5: If there is another component call, the timer is dropped (cleared). - */ - -import React, { Component } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiScreenReaderOnly, EuiDelayRender } from '@elastic/eui'; - -export class AdvancedSettingsVoiceAnnouncement extends Component { - shouldComponentUpdate = nextProps => { - /* - If a user typed smth new, we should clear the previous timer - and start another one + block component rendering. - - When it is reset and delaying is over as well as no new string came, - it's ready to be rendered. - */ - return nextProps.queryText !== this.props.queryText; - }; - - render() { - const filteredSections = Object.values(this.props.settings).map(setting => - setting.map(option => option.ariaName) - ); - const filteredOptions = [].concat(...filteredSections); - return ( - -
- - - -
-
- ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.test.js deleted file mode 100644 index 41b16c5cbda711..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.test.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { shallow } from 'enzyme'; - -import { AdvancedSettingsVoiceAnnouncement } from './advanced_settings_voice_announcement'; - -const testProps = { - nothing: { - query: '', - filteredSettings: [ - [ - { - ariaName: 'General', - }, - ], - ], - }, - searchResult: { - query: 'dark theme', - filteredSettings: [ - [ - { - ariaName: 'General', - }, - ], - ], - }, -}; - -describe('Advanced Settings: Voice Announcement', () => { - it('should render nothing', async () => { - const { query, filteredSettings } = testProps.nothing; - - const component = shallow( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should render announcement', async () => { - const { query, filteredSettings } = testProps.searchResult; - - const component = shallow( - - ); - - expect(component).toMatchSnapshot(); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.test.tsx new file mode 100644 index 00000000000000..66f2d4e784630f --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.test.tsx @@ -0,0 +1,84 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; +import { UiSettingsType } from '../../../../../../../../../core/public'; + +import { AdvancedSettingsVoiceAnnouncement } from './advanced_settings_voice_announcement'; + +const settingPartial = { + name: 'name', + isOverridden: false, + type: 'string' as UiSettingsType, + value: 'value', + defVal: 'defVal', + optionLabels: { label: 'label' }, + description: 'description', + displayName: 'displayName', + isCustom: false, + requiresPageReload: false, + options: [], + validation: { regex: /a/, message: 'message' }, + category: ['category'], + readOnly: false, +}; + +const testProps = { + nothing: { + query: '', + filteredSettings: [ + { + ariaName: 'General', + ...settingPartial, + }, + ], + }, + searchResult: { + query: 'dark theme', + filteredSettings: [ + { + ariaName: 'General', + ...settingPartial, + }, + ], + }, +}; + +describe('Advanced Settings: Voice Announcement', () => { + it('should render nothing', async () => { + const { query, filteredSettings } = testProps.nothing; + + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render announcement', async () => { + const { query, filteredSettings } = testProps.searchResult; + + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.tsx new file mode 100644 index 00000000000000..01f1388ba1eef5 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/advanced_settings_voice_announcement.tsx @@ -0,0 +1,87 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + This component aims to insert assertive live region on the page, + to make sure that a screen reader announces layout changes. + + Due to the fact that it has a specific way of detecting what-and-when announce + as well as delay of announcement (which depends on what a user is doing at the moment) + I place a 500ms delay of re-render the text of anouncement. + That time period is best fits the time of screen reader reaction. + That anouncement depends on what user is typying into search box as well as + the speed of ordinary screen reader pronouns what user is typing before start reading this anouncement. + + The order of triggering functions: + 1: React trigs the component to be updated + 2: It places a timer and block render + 3: The time is over + 4: Component renders + + 5: If there is another component call, the timer is dropped (cleared). + */ + +import React, { Component } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiScreenReaderOnly, EuiDelayRender } from '@elastic/eui'; +import { FieldSetting } from '../../types'; + +interface Props { + queryText: string; + settings: Record; +} + +export class AdvancedSettingsVoiceAnnouncement extends Component { + shouldComponentUpdate = (nextProps: Props) => { + /* + If a user typed smth new, we should clear the previous timer + and start another one + block component rendering. + + When it is reset and delaying is over as well as no new string came, + it's ready to be rendered. + */ + return nextProps.queryText !== this.props.queryText; + }; + + render() { + const filteredSections = Object.values(this.props.settings).map(setting => + setting.map(option => option.ariaName) + ); + const filteredOptions = [...filteredSections]; + return ( + +
+ + + +
+
+ ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/advanced_settings_voice_announcement/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/__snapshots__/call_outs.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/__snapshots__/call_outs.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/__snapshots__/call_outs.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/__snapshots__/call_outs.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/call_outs/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.js deleted file mode 100644 index 4b81b74d20aa48..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const registry = {}; - -/** - * Attempts to register the provided component. - * If a component with that ID is already registered, then the registration fails. - * - * @param {*} id the id of the component to register - * @param {*} component the component - */ -export function tryRegisterSettingsComponent(id, component) { - if (id in registry) { - return false; - } - - registerSettingsComponent(id, component); - return true; -} - -/** - * Attempts to register the provided component, with the ability to optionally allow - * the component to override an existing one. - * - * If the intent is to override, then `allowOverride` must be set to true, otherwise an exception is thrown. - * - * @param {*} id the id of the component to register - * @param {*} component the component - * @param {*} allowOverride (default: false) - optional flag to allow this component to override a previously registered component - */ -export function registerSettingsComponent(id, component, allowOverride = false) { - if (!allowOverride && id in registry) { - throw new Error(`Component with id ${id} is already registered.`); - } - - // Setting a display name if one does not already exist. - // This enhances the snapshots, as well as the debugging experience. - if (!component.displayName) { - component.displayName = id; - } - - registry[id] = component; -} - -/** - * Retrieve a registered component by its ID. - * If the component does not exist, then an exception is thrown. - * - * @param {*} id the ID of the component to retrieve - */ -export function getSettingsComponent(id) { - if (!(id in registry)) { - throw new Error(`Component not found with id ${id}`); - } - return registry[id]; -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.test.js deleted file mode 100644 index fb3365a102fde6..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.test.js +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { - tryRegisterSettingsComponent, - registerSettingsComponent, - getSettingsComponent, -} from './component_registry'; - -describe('tryRegisterSettingsComponent', () => { - it('should allow a component to be registered', () => { - const component = {}; - expect(tryRegisterSettingsComponent('tryTest1', component)).toEqual(true); - }); - - it('should return false if the component is already registered, and not allow an override', () => { - const component = {}; - expect(tryRegisterSettingsComponent('tryTest2', component)).toEqual(true); - - const updatedComponent = { updated: 'yay' }; - expect(tryRegisterSettingsComponent('tryTest2', updatedComponent)).toEqual(false); - expect(getSettingsComponent('tryTest2')).toBe(component); - }); -}); - -describe('registerSettingsComponent', () => { - it('should allow a component to be registered', () => { - const component = {}; - registerSettingsComponent('test', component); - }); - - it('should disallow registering a component with a duplicate id', () => { - const component = {}; - registerSettingsComponent('test2', component); - expect(() => - registerSettingsComponent('test2', 'some other component') - ).toThrowErrorMatchingSnapshot(); - }); - - it('should allow a component to be overriden', () => { - const component = {}; - registerSettingsComponent('test3', component); - - const anotherComponent = { anotherComponent: 'ok' }; - registerSettingsComponent('test3', anotherComponent, true); - - expect(getSettingsComponent('test3')).toBe(anotherComponent); - }); - - it('should set a displayName for the component if one does not exist', () => { - const component = {}; - registerSettingsComponent('display_name_component', component); - - expect(component.displayName).toEqual('display_name_component'); - }); - - it('should not set a displayName for the component if one already exists', () => { - const component = { - displayName: '', - }; - - registerSettingsComponent('another_display_name_component', component); - - expect(component.displayName).toEqual(''); - }); -}); - -describe('getSettingsComponent', () => { - it('should allow a component to be retrieved', () => { - const component = {}; - registerSettingsComponent('test4', component); - expect(getSettingsComponent('test4')).toBe(component); - }); - - it('should throw an error when requesting a component that does not exist', () => { - expect(() => getSettingsComponent('does not exist')).toThrowErrorMatchingSnapshot(); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.test.tsx new file mode 100644 index 00000000000000..24e9e5dd3809c8 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.test.tsx @@ -0,0 +1,82 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FunctionComponent } from 'react'; +import { + tryRegisterSettingsComponent, + registerSettingsComponent, + getSettingsComponent, +} from './component_registry'; + +describe('tryRegisterSettingsComponent', () => { + it('should allow a component to be registered', () => { + const component = () =>
; + expect(tryRegisterSettingsComponent('tryTest1', component)).toEqual(true); + }); + + it('should return false if the component is already registered, and not allow an override', () => { + const component = () =>
; + expect(tryRegisterSettingsComponent('tryTest2', component)).toEqual(true); + + const updatedComponent = () =>
; + expect(tryRegisterSettingsComponent('tryTest2', updatedComponent)).toEqual(false); + expect(getSettingsComponent('tryTest2')).toBe(component); + }); +}); + +describe('registerSettingsComponent', () => { + it('should allow a component to be registered', () => { + const component = () =>
; + registerSettingsComponent('test', component); + }); + + it('should disallow registering a component with a duplicate id', () => { + const component = () =>
; + registerSettingsComponent('test2', component); + expect(() => registerSettingsComponent('test2', () => )).toThrowErrorMatchingSnapshot(); + }); + + it('should allow a component to be overriden', () => { + const component = () =>
; + registerSettingsComponent('test3', component); + + const anotherComponent = () => ; + registerSettingsComponent('test3', anotherComponent, true); + + expect(getSettingsComponent('test3')).toBe(anotherComponent); + }); + + it('should set a displayName for the component', () => { + const component = () =>
; + registerSettingsComponent('display_name_component', component); + expect((component as FunctionComponent).displayName).toEqual('display_name_component'); + }); +}); + +describe('getSettingsComponent', () => { + it('should allow a component to be retrieved', () => { + const component = () =>
; + registerSettingsComponent('test4', component); + expect(getSettingsComponent('test4')).toBe(component); + }); + + it('should throw an error when requesting a component that does not exist', () => { + expect(() => getSettingsComponent('does not exist')).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.ts new file mode 100644 index 00000000000000..b58180c498edfe --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/component_registry.ts @@ -0,0 +1,83 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ComponentType } from 'react'; + +type Id = string; +const registry: Record | undefined>> = {}; + +/** + * Attempts to register the provided component. + * If a component with that ID is already registered, then the registration fails. + * + * @param {*} id the id of the component to register + * @param {*} component the component + */ +export function tryRegisterSettingsComponent( + id: Id, + component: ComponentType | undefined> +) { + if (id in registry) { + return false; + } + + registerSettingsComponent(id, component); + return true; +} + +/** + * Attempts to register the provided component, with the ability to optionally allow + * the component to override an existing one. + * + * If the intent is to override, then `allowOverride` must be set to true, otherwise an exception is thrown. + * + * @param {*} id the id of the component to register + * @param {*} component the component + * @param {*} allowOverride (default: false) - optional flag to allow this component to override a previously registered component + */ +export function registerSettingsComponent( + id: Id, + component: ComponentType | undefined>, + allowOverride = false +) { + if (!allowOverride && id in registry) { + throw new Error(`Component with id ${id} is already registered.`); + } + + // Setting a display name if one does not already exist. + // This enhances the snapshots, as well as the debugging experience. + if (!component.displayName) { + component.displayName = id; + } + + registry[id] = component; +} + +/** + * Retrieve a registered component by its ID. + * If the component does not exist, then an exception is thrown. + * + * @param {*} id the ID of the component to retrieve + */ +export function getSettingsComponent(id: Id): ComponentType | undefined> { + if (!(id in registry)) { + throw new Error(`Component not found with id ${id}`); + } + return registry[id]; +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.test.js deleted file mode 100644 index 4fc6dc710f8669..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.test.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { registerDefaultComponents, PAGE_TITLE_COMPONENT } from './default_component_registry'; -import { getSettingsComponent, registerSettingsComponent } from './component_registry'; -import { PageTitle } from './page_title'; - -describe('default_component_registry', () => { - it('should register default components with the registry', () => { - registerDefaultComponents(); - expect(getSettingsComponent(PAGE_TITLE_COMPONENT)).toEqual(PageTitle); - }); - - it('should be able to call "registerDefaultComponents" several times without throwing', () => { - registerDefaultComponents(); - registerDefaultComponents(); - registerDefaultComponents(); - }); - - it('should not override components if they are already registered', () => { - const newComponent = {}; - registerSettingsComponent(PAGE_TITLE_COMPONENT, newComponent, true); - registerDefaultComponents(); - - expect(getSettingsComponent(PAGE_TITLE_COMPONENT)).toEqual(newComponent); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.test.tsx new file mode 100644 index 00000000000000..ff3f75b79baefc --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.test.tsx @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { registerDefaultComponents, PAGE_TITLE_COMPONENT } from './default_component_registry'; +import { getSettingsComponent, registerSettingsComponent } from './component_registry'; +import { PageTitle } from './page_title'; + +describe('default_component_registry', () => { + it('should register default components with the registry', () => { + registerDefaultComponents(); + expect(getSettingsComponent(PAGE_TITLE_COMPONENT)).toEqual(PageTitle); + }); + + it('should be able to call "registerDefaultComponents" several times without throwing', () => { + registerDefaultComponents(); + registerDefaultComponents(); + registerDefaultComponents(); + }); + + it('should not override components if they are already registered', () => { + const newComponent = () =>
; + registerSettingsComponent(PAGE_TITLE_COMPONENT, newComponent, true); + registerDefaultComponents(); + + expect(getSettingsComponent(PAGE_TITLE_COMPONENT)).toEqual(newComponent); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/default_component_registry.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap deleted file mode 100644 index f4d20b45658802..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap +++ /dev/null @@ -1,4096 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Field for array setting should render as read only if saving is disabled 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="array:test:setting-aria" - title={ -

- Array test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for array setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - default_value - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="array:test:setting-aria" - title={ -

- Array test setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="array:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for array setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="array:test:setting-aria" - title={ -

- Array test setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for array setting should render default value if there is no user value set 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="array:test:setting-aria" - title={ -

- Array test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for array setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - default_value - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="array:test:setting-aria" - title={ -

- Array test setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="array:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for boolean setting should render as read only if saving is disabled 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="boolean:test:setting-aria" - title={ -

- Boolean test setting - -

- } - titleSize="xs" - > - - - } - onChange={[Function]} - onKeyDown={[Function]} - /> - - - - - -`; - -exports[`Field for boolean setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - true - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="boolean:test:setting-aria" - title={ -

- Boolean test setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="boolean:test:setting" - labelType="label" - > - - } - onChange={[Function]} - onKeyDown={[Function]} - /> - - - - - -`; - -exports[`Field for boolean setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="boolean:test:setting-aria" - title={ -

- Boolean test setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - - - } - onChange={[Function]} - onKeyDown={[Function]} - /> - - - - - -`; - -exports[`Field for boolean setting should render default value if there is no user value set 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="boolean:test:setting-aria" - title={ -

- Boolean test setting - -

- } - titleSize="xs" - > - - - } - onChange={[Function]} - onKeyDown={[Function]} - /> - - - - - -`; - -exports[`Field for boolean setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - true - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="boolean:test:setting-aria" - title={ -

- Boolean test setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="boolean:test:setting" - labelType="label" - > - - } - onChange={[Function]} - onKeyDown={[Function]} - /> - - - - - -`; - -exports[`Field for image setting should render as read only if saving is disabled 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="image:test:setting-aria" - title={ -

- Image test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for image setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - null - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="image:test:setting-aria" - title={ -

- Image test setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="image:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for image setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="image:test:setting-aria" - title={ -

- Image test setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for image setting should render default value if there is no user value set 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="image:test:setting-aria" - title={ -

- Image test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for image setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - null - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="image:test:setting-aria" - title={ -

- Image test setting - -

- } - titleSize="xs" - > - - - - - -     - - - - - - - - } - isInvalid={false} - label="image:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for json setting should render as read only if saving is disabled 1`] = ` - - - -
- - - - - - {} - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="json:test:setting-aria" - title={ -

- Json test setting - -

- } - titleSize="xs" - > - -
- -
-
- - - - -`; - -exports[`Field for json setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - {} - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="json:test:setting-aria" - title={ -

- Json test setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="json:test:setting" - labelType="label" - > -
- -
-
- - - - -`; - -exports[`Field for json setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="json:test:setting-aria" - title={ -

- Json test setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - -
- -
-
- - - - -`; - -exports[`Field for json setting should render default value if there is no user value set 1`] = ` - - - -
- - - - - - {} - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="json:test:setting-aria" - title={ -

- Json test setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="json:test:setting" - labelType="label" - > -
- -
-
- - - - -`; - -exports[`Field for json setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - {} - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="json:test:setting-aria" - title={ -

- Json test setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="json:test:setting" - labelType="label" - > -
- -
-
- - - - -`; - -exports[`Field for markdown setting should render as read only if saving is disabled 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="markdown:test:setting-aria" - title={ -

- Markdown test setting - -

- } - titleSize="xs" - > - -
- -
-
- - - - -`; - -exports[`Field for markdown setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - null - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="markdown:test:setting-aria" - title={ -

- Markdown test setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="markdown:test:setting" - labelType="label" - > -
- -
-
- - - - -`; - -exports[`Field for markdown setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="markdown:test:setting-aria" - title={ -

- Markdown test setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - -
- -
-
- - - - -`; - -exports[`Field for markdown setting should render default value if there is no user value set 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="markdown:test:setting-aria" - title={ -

- Markdown test setting - -

- } - titleSize="xs" - > - -
- -
-
- - - - -`; - -exports[`Field for markdown setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - null - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="markdown:test:setting-aria" - title={ -

- Markdown test setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="markdown:test:setting" - labelType="label" - > -
- -
-
- - - - -`; - -exports[`Field for number setting should render as read only if saving is disabled 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="number:test:setting-aria" - title={ -

- Number test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for number setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - 5 - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="number:test:setting-aria" - title={ -

- Number test setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="number:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for number setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="number:test:setting-aria" - title={ -

- Number test setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for number setting should render default value if there is no user value set 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="number:test:setting-aria" - title={ -

- Number test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for number setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - 5 - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="number:test:setting-aria" - title={ -

- Number test setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="number:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for select setting should render as read only if saving is disabled 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="select:test:setting-aria" - title={ -

- Select test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for select setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - Orange - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="select:test:setting-aria" - title={ -

- Select test setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="select:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for select setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="select:test:setting-aria" - title={ -

- Select test setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for select setting should render default value if there is no user value set 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="select:test:setting-aria" - title={ -

- Select test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for select setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - Orange - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="select:test:setting-aria" - title={ -

- Select test setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="select:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for string setting should render as read only if saving is disabled 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="string:test:setting-aria" - title={ -

- String test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for string setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - null - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="string:test:setting-aria" - title={ -

- String test setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="string:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for string setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="string:test:setting-aria" - title={ -

- String test setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for string setting should render default value if there is no user value set 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="string:test:setting-aria" - title={ -

- String test setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for string setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - null - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="string:test:setting-aria" - title={ -

- String test setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="string:test:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for stringWithValidation setting should render as read only if saving is disabled 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="string:test-validation:setting-aria" - title={ -

- String test validation setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for stringWithValidation setting should render as read only with help text if overridden 1`] = ` - - - -
- - - - - - foo-default - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="string:test-validation:setting-aria" - title={ -

- String test validation setting - -

- } - titleSize="xs" - > - - - - } - isInvalid={false} - label="string:test-validation:setting" - labelType="label" - > - - - - - - -`; - -exports[`Field for stringWithValidation setting should render custom setting icon if it is custom 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="string:test-validation:setting-aria" - title={ -

- String test validation setting - - } - type="asterisk" - /> -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for stringWithValidation setting should render default value if there is no user value set 1`] = ` - - - -
- - } - fullWidth={false} - gutterSize="l" - idAria="string:test-validation:setting-aria" - title={ -

- String test validation setting - -

- } - titleSize="xs" - > - - - - - - - -`; - -exports[`Field for stringWithValidation setting should render user value if there is user value is set 1`] = ` - - - -
- - - - - - foo-default - , - } - } - /> - - - - - } - fullWidth={false} - gutterSize="l" - idAria="string:test-validation:setting-aria" - title={ -

- String test validation setting - -

- } - titleSize="xs" - > - - - - - -     - - - } - isInvalid={false} - label="string:test-validation:setting" - labelType="label" - > - - - - - - -`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.tsx.snap new file mode 100644 index 00000000000000..915ee021e9b607 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.tsx.snap @@ -0,0 +1,4092 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Field for array setting should render as read only if saving is disabled 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="array:test:setting-aria" + title={ +

+ Array test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for array setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + default_value + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="array:test:setting-aria" + title={ +

+ Array test setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="array:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for array setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="array:test:setting-aria" + title={ +

+ Array test setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for array setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="array:test:setting-aria" + title={ +

+ Array test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for array setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + default_value + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="array:test:setting-aria" + title={ +

+ Array test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="array:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for boolean setting should render as read only if saving is disabled 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="boolean:test:setting-aria" + title={ +

+ Boolean test setting + +

+ } + titleSize="xs" + > + + + } + onChange={[Function]} + onKeyDown={[Function]} + /> + + + + + +`; + +exports[`Field for boolean setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + true + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="boolean:test:setting-aria" + title={ +

+ Boolean test setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="boolean:test:setting" + labelType="label" + > + + } + onChange={[Function]} + onKeyDown={[Function]} + /> + + + + + +`; + +exports[`Field for boolean setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="boolean:test:setting-aria" + title={ +

+ Boolean test setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + + + } + onChange={[Function]} + onKeyDown={[Function]} + /> + + + + + +`; + +exports[`Field for boolean setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="boolean:test:setting-aria" + title={ +

+ Boolean test setting + +

+ } + titleSize="xs" + > + + + } + onChange={[Function]} + onKeyDown={[Function]} + /> + + + + + +`; + +exports[`Field for boolean setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + true + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="boolean:test:setting-aria" + title={ +

+ Boolean test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="boolean:test:setting" + labelType="label" + > + + } + onChange={[Function]} + onKeyDown={[Function]} + /> + + + + + +`; + +exports[`Field for image setting should render as read only if saving is disabled 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="image:test:setting-aria" + title={ +

+ Image test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for image setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + null + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="image:test:setting-aria" + title={ +

+ Image test setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="image:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for image setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="image:test:setting-aria" + title={ +

+ Image test setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for image setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="image:test:setting-aria" + title={ +

+ Image test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for image setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + null + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="image:test:setting-aria" + title={ +

+ Image test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + + + + + + } + isInvalid={false} + label="image:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for json setting should render as read only if saving is disabled 1`] = ` + + + +
+ + + + + + {} + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="json:test:setting-aria" + title={ +

+ Json test setting + +

+ } + titleSize="xs" + > + +
+ +
+
+ + + + +`; + +exports[`Field for json setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + {} + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="json:test:setting-aria" + title={ +

+ Json test setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="json:test:setting" + labelType="label" + > +
+ +
+
+ + + + +`; + +exports[`Field for json setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="json:test:setting-aria" + title={ +

+ Json test setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + +
+ +
+
+ + + + +`; + +exports[`Field for json setting should render default value if there is no user value set 1`] = ` + + + +
+ + + + + + {} + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="json:test:setting-aria" + title={ +

+ Json test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="json:test:setting" + labelType="label" + > +
+ +
+
+ + + + +`; + +exports[`Field for json setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + {} + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="json:test:setting-aria" + title={ +

+ Json test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="json:test:setting" + labelType="label" + > +
+ +
+
+ + + + +`; + +exports[`Field for markdown setting should render as read only if saving is disabled 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="markdown:test:setting-aria" + title={ +

+ Markdown test setting + +

+ } + titleSize="xs" + > + +
+ +
+
+ + + + +`; + +exports[`Field for markdown setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + null + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="markdown:test:setting-aria" + title={ +

+ Markdown test setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="markdown:test:setting" + labelType="label" + > +
+ +
+
+ + + + +`; + +exports[`Field for markdown setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="markdown:test:setting-aria" + title={ +

+ Markdown test setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + +
+ +
+
+ + + + +`; + +exports[`Field for markdown setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="markdown:test:setting-aria" + title={ +

+ Markdown test setting + +

+ } + titleSize="xs" + > + +
+ +
+
+ + + + +`; + +exports[`Field for markdown setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + null + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="markdown:test:setting-aria" + title={ +

+ Markdown test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="markdown:test:setting" + labelType="label" + > +
+ +
+
+ + + + +`; + +exports[`Field for number setting should render as read only if saving is disabled 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="number:test:setting-aria" + title={ +

+ Number test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for number setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + 5 + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="number:test:setting-aria" + title={ +

+ Number test setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="number:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for number setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="number:test:setting-aria" + title={ +

+ Number test setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for number setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="number:test:setting-aria" + title={ +

+ Number test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for number setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + 5 + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="number:test:setting-aria" + title={ +

+ Number test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="number:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for select setting should render as read only if saving is disabled 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="select:test:setting-aria" + title={ +

+ Select test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for select setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + Orange + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="select:test:setting-aria" + title={ +

+ Select test setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="select:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for select setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="select:test:setting-aria" + title={ +

+ Select test setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for select setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="select:test:setting-aria" + title={ +

+ Select test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for select setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + Orange + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="select:test:setting-aria" + title={ +

+ Select test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="select:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for string setting should render as read only if saving is disabled 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="string:test:setting-aria" + title={ +

+ String test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for string setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + null + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="string:test:setting-aria" + title={ +

+ String test setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="string:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for string setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="string:test:setting-aria" + title={ +

+ String test setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for string setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="string:test:setting-aria" + title={ +

+ String test setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for string setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + null + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="string:test:setting-aria" + title={ +

+ String test setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="string:test:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for stringWithValidation setting should render as read only if saving is disabled 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="string:test-validation:setting-aria" + title={ +

+ String test validation setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for stringWithValidation setting should render as read only with help text if overridden 1`] = ` + + + +
+ + + + + + foo-default + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="string:test-validation:setting-aria" + title={ +

+ String test validation setting + +

+ } + titleSize="xs" + > + + + + } + isInvalid={false} + label="string:test-validation:setting" + labelType="label" + > + + + + + + +`; + +exports[`Field for stringWithValidation setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="string:test-validation:setting-aria" + title={ +

+ String test validation setting + + } + type="asterisk" + /> +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for stringWithValidation setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="string:test-validation:setting-aria" + title={ +

+ String test validation setting + +

+ } + titleSize="xs" + > + + + + + + + +`; + +exports[`Field for stringWithValidation setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + + + foo-default + , + } + } + /> + + + + + } + fullWidth={false} + gutterSize="l" + idAria="string:test-validation:setting-aria" + title={ +

+ String test validation setting + +

+ } + titleSize="xs" + > + + + + + +     + + + } + isInvalid={false} + label="string:test-validation:setting" + labelType="label" + > + + + + + + +`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.js deleted file mode 100644 index a2f201cf757f52..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.js +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { PureComponent, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { npStart } from 'ui/new_platform'; - -import 'brace/theme/textmate'; -import 'brace/mode/markdown'; - -import { toastNotifications } from 'ui/notify'; -import { - EuiBadge, - EuiButton, - EuiButtonEmpty, - EuiCode, - EuiCodeBlock, - EuiCodeEditor, - EuiDescribedFormGroup, - EuiFieldNumber, - EuiFieldText, - EuiFilePicker, - EuiFlexGroup, - EuiFlexItem, - EuiFormRow, - EuiIconTip, - EuiImage, - EuiLink, - EuiSpacer, - EuiToolTip, - EuiText, - EuiSelect, - EuiSwitch, - keyCodes, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { isDefaultValue } from '../../lib'; - -export class Field extends PureComponent { - static propTypes = { - setting: PropTypes.object.isRequired, - save: PropTypes.func.isRequired, - clear: PropTypes.func.isRequired, - enableSaving: PropTypes.bool.isRequired, - }; - - constructor(props) { - super(props); - const { type, value, defVal } = this.props.setting; - const editableValue = this.getEditableValue(type, value, defVal); - - this.state = { - isInvalid: false, - error: null, - loading: false, - changeImage: false, - savedValue: editableValue, - unsavedValue: editableValue, - isJsonArray: type === 'json' ? Array.isArray(JSON.parse(defVal || '{}')) : false, - }; - this.changeImageForm = null; - } - - UNSAFE_componentWillReceiveProps(nextProps) { - const { unsavedValue } = this.state; - const { type, value, defVal } = nextProps.setting; - const editableValue = this.getEditableValue(type, value, defVal); - - this.setState({ - savedValue: editableValue, - unsavedValue: value === null || value === undefined ? editableValue : unsavedValue, - }); - } - - getEditableValue(type, value, defVal) { - const val = value === null || value === undefined ? defVal : value; - switch (type) { - case 'array': - return val.join(', '); - case 'boolean': - return !!val; - case 'number': - return Number(val); - case 'image': - return val; - default: - return val || ''; - } - } - - getDisplayedDefaultValue(type, defVal, optionLabels = {}) { - if (defVal === undefined || defVal === null || defVal === '') { - return 'null'; - } - switch (type) { - case 'array': - return defVal.join(', '); - case 'select': - return optionLabels.hasOwnProperty(defVal) ? optionLabels[defVal] : String(defVal); - default: - return String(defVal); - } - } - - setLoading(loading) { - this.setState({ - loading, - }); - } - - clearError() { - this.setState({ - isInvalid: false, - error: null, - }); - } - - onCodeEditorChange = value => { - const { type } = this.props.setting; - const { isJsonArray } = this.state; - - let newUnsavedValue = undefined; - let isInvalid = false; - let error = null; - - switch (type) { - case 'json': - newUnsavedValue = value.trim() || (isJsonArray ? '[]' : '{}'); - try { - JSON.parse(newUnsavedValue); - } catch (e) { - isInvalid = true; - error = ( - - ); - } - break; - default: - newUnsavedValue = value; - } - - this.setState({ - error, - isInvalid, - unsavedValue: newUnsavedValue, - }); - }; - - onFieldChange = e => { - const value = e.target.value; - const { type, validation } = this.props.setting; - const { unsavedValue } = this.state; - - let newUnsavedValue = undefined; - - switch (type) { - case 'boolean': - newUnsavedValue = !unsavedValue; - break; - case 'number': - newUnsavedValue = Number(value); - break; - default: - newUnsavedValue = value; - } - - let isInvalid = false; - let error = undefined; - - if (validation && validation.regex) { - if (!validation.regex.test(newUnsavedValue)) { - error = validation.message; - isInvalid = true; - } - } - - this.setState({ - unsavedValue: newUnsavedValue, - isInvalid, - error, - }); - }; - - onFieldKeyDown = ({ keyCode }) => { - if (keyCode === keyCodes.ENTER) { - this.saveEdit(); - } - if (keyCode === keyCodes.ESCAPE) { - this.cancelEdit(); - } - }; - - onFieldEscape = ({ keyCode }) => { - if (keyCode === keyCodes.ESCAPE) { - this.cancelEdit(); - } - }; - - onImageChange = async files => { - if (!files.length) { - this.clearError(); - this.setState({ - unsavedValue: null, - }); - return; - } - - const file = files[0]; - const { maxSize } = this.props.setting.validation; - try { - const base64Image = await this.getImageAsBase64(file); - const isInvalid = !!(maxSize && maxSize.length && base64Image.length > maxSize.length); - this.setState({ - isInvalid, - error: isInvalid - ? i18n.translate('kbn.management.settings.field.imageTooLargeErrorMessage', { - defaultMessage: 'Image is too large, maximum size is {maxSizeDescription}', - values: { - maxSizeDescription: maxSize.description, - }, - }) - : null, - changeImage: true, - unsavedValue: base64Image, - }); - } catch (err) { - toastNotifications.addDanger( - i18n.translate('kbn.management.settings.field.imageChangeErrorMessage', { - defaultMessage: 'Image could not be saved', - }) - ); - this.cancelChangeImage(); - } - }; - - getImageAsBase64(file) { - if (!file instanceof File) { - return null; - } - - const reader = new FileReader(); - reader.readAsDataURL(file); - - return new Promise((resolve, reject) => { - reader.onload = () => { - resolve(reader.result); - }; - reader.onerror = err => { - reject(err); - }; - }); - } - - changeImage = () => { - this.setState({ - changeImage: true, - }); - }; - - cancelChangeImage = () => { - const { savedValue } = this.state; - - if (this.changeImageForm) { - this.changeImageForm.fileInput.value = null; - this.changeImageForm.handleChange(); - } - - this.setState({ - changeImage: false, - unsavedValue: savedValue, - }); - }; - - cancelEdit = () => { - const { savedValue } = this.state; - this.clearError(); - this.setState({ - unsavedValue: savedValue, - }); - }; - - showPageReloadToast = () => { - if (this.props.setting.requiresPageReload) { - toastNotifications.add({ - title: i18n.translate('kbn.management.settings.field.requiresPageReloadToastDescription', { - defaultMessage: 'Please reload the page for the "{settingName}" setting to take effect.', - values: { - settingName: this.props.setting.displayName || this.props.setting.name, - }, - }), - text: ( - <> - - - window.location.reload()}> - {i18n.translate( - 'kbn.management.settings.field.requiresPageReloadToastButtonLabel', - { defaultMessage: 'Reload page' } - )} - - - - - ), - color: 'success', - }); - } - }; - - saveEdit = async () => { - const { name, defVal, type } = this.props.setting; - const { changeImage, savedValue, unsavedValue, isJsonArray } = this.state; - - if (savedValue === unsavedValue) { - return; - } - - let valueToSave = unsavedValue; - let isSameValue = false; - - switch (type) { - case 'array': - valueToSave = valueToSave.split(',').map(val => val.trim()); - isSameValue = valueToSave.join(',') === defVal.join(','); - break; - case 'json': - valueToSave = valueToSave.trim(); - valueToSave = valueToSave || (isJsonArray ? '[]' : '{}'); - default: - isSameValue = valueToSave === defVal; - } - - this.setLoading(true); - try { - if (isSameValue) { - await this.props.clear(name); - } else { - await this.props.save(name, valueToSave); - } - - this.showPageReloadToast(); - - if (changeImage) { - this.cancelChangeImage(); - } - } catch (e) { - toastNotifications.addDanger( - i18n.translate('kbn.management.settings.field.saveFieldErrorMessage', { - defaultMessage: 'Unable to save {name}', - values: { name }, - }) - ); - } - this.setLoading(false); - }; - - resetField = async () => { - const { name } = this.props.setting; - this.setLoading(true); - try { - await this.props.clear(name); - this.showPageReloadToast(); - this.cancelChangeImage(); - this.clearError(); - } catch (e) { - toastNotifications.addDanger( - i18n.translate('kbn.management.settings.field.resetFieldErrorMessage', { - defaultMessage: 'Unable to reset {name}', - values: { name }, - }) - ); - } - this.setLoading(false); - }; - - renderField(setting) { - const { enableSaving } = this.props; - const { loading, changeImage, unsavedValue } = this.state; - const { name, value, type, options, optionLabels = {}, isOverridden, ariaName } = setting; - - switch (type) { - case 'boolean': - return ( - - ) : ( - - ) - } - checked={!!unsavedValue} - onChange={this.onFieldChange} - disabled={loading || isOverridden || !enableSaving} - onKeyDown={this.onFieldKeyDown} - data-test-subj={`advancedSetting-editField-${name}`} - aria-label={ariaName} - /> - ); - case 'markdown': - case 'json': - return ( -
- -
- ); - case 'image': - if (!isDefaultValue(setting) && !changeImage) { - return ; - } else { - return ( - { - this.changeImageForm = input; - }} - onKeyDown={this.onFieldEscape} - data-test-subj={`advancedSetting-editField-${name}`} - /> - ); - } - case 'select': - return ( - { - return { - text: optionLabels.hasOwnProperty(option) ? optionLabels[option] : option, - value: option, - }; - })} - onChange={this.onFieldChange} - isLoading={loading} - disabled={loading || isOverridden || !enableSaving} - onKeyDown={this.onFieldKeyDown} - data-test-subj={`advancedSetting-editField-${name}`} - /> - ); - case 'number': - return ( - - ); - default: - return ( - - ); - } - } - - renderLabel(setting) { - return setting.name; - } - - renderHelpText(setting) { - if (setting.isOverridden) { - return ( - - - - ); - } - - const canUpdateSetting = this.props.enableSaving; - const defaultLink = this.renderResetToDefaultLink(setting); - const imageLink = this.renderChangeImageLink(setting); - - if (canUpdateSetting && (defaultLink || imageLink)) { - return ( - - {defaultLink} - {imageLink} - - ); - } - - return null; - } - - renderTitle(setting) { - return ( -

- {setting.displayName || setting.name} - {setting.isCustom ? ( - - } - /> - ) : ( - '' - )} -

- ); - } - - renderDescription(setting) { - let description; - let deprecation; - - if (setting.deprecation) { - const { links } = npStart.core.docLinks; - - deprecation = ( - <> - - { - window.open(links.management[setting.deprecation.docLinksKey], '_blank'); - }} - onClickAriaLabel={i18n.translate( - 'kbn.management.settings.field.deprecationClickAreaLabel', - { - defaultMessage: 'Click to view deprecation documentation for {settingName}.', - values: { - settingName: setting.name, - }, - } - )} - > - Deprecated - - - - - ); - } - - if (React.isValidElement(setting.description)) { - description = setting.description; - } else { - description = ( -
- ); - } - - return ( - - {deprecation} - {description} - {this.renderDefaultValue(setting)} - - ); - } - - renderDefaultValue(setting) { - const { type, defVal, optionLabels } = setting; - if (isDefaultValue(setting)) { - return; - } - return ( - - - - {type === 'json' ? ( - - = 500 ? 300 : null} - > - {this.getDisplayedDefaultValue(type, defVal)} - - ), - }} - /> - - ) : ( - - {this.getDisplayedDefaultValue(type, defVal, optionLabels)} - ), - }} - /> - - )} - - - ); - } - - renderResetToDefaultLink(setting) { - const { ariaName, name } = setting; - if (isDefaultValue(setting)) { - return; - } - return ( - - - - -     - - ); - } - - renderChangeImageLink(setting) { - const { changeImage } = this.state; - const { type, value, ariaName, name } = setting; - if (type !== 'image' || !value || changeImage) { - return; - } - return ( - - - - - - ); - } - - renderActions(setting) { - const { ariaName, name } = setting; - const { loading, isInvalid, changeImage, savedValue, unsavedValue } = this.state; - const isDisabled = loading || setting.isOverridden; - - if (savedValue === unsavedValue && !changeImage) { - return; - } - - return ( - - - - - - - - - (changeImage ? this.cancelChangeImage() : this.cancelEdit())} - disabled={isDisabled} - data-test-subj={`advancedSetting-cancelEditField-${name}`} - > - - - - - - ); - } - - render() { - const { setting } = this.props; - const { error, isInvalid } = this.state; - - return ( - - - - - {this.renderField(setting)} - - - - {this.renderActions(setting)} - - ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.test.js deleted file mode 100644 index 07ce6f84d2bb64..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.test.js +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { I18nProvider } from '@kbn/i18n/react'; -import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; -import { mount } from 'enzyme'; - -import { findTestSubject } from '@elastic/eui/lib/test'; -import { Field } from './field'; - -jest.mock('ui/notify', () => ({ - toastNotifications: { - addDanger: () => {}, - add: jest.fn(), - }, -})); - -import { toastNotifications } from 'ui/notify'; - -jest.mock('brace/theme/textmate', () => 'brace/theme/textmate'); -jest.mock('brace/mode/markdown', () => 'brace/mode/markdown'); - -const settings = { - array: { - name: 'array:test:setting', - ariaName: 'array test setting', - displayName: 'Array test setting', - description: 'Description for Array test setting', - type: 'array', - value: undefined, - defVal: ['default_value'], - isCustom: false, - isOverridden: false, - options: null, - }, - boolean: { - name: 'boolean:test:setting', - ariaName: 'boolean test setting', - displayName: 'Boolean test setting', - description: 'Description for Boolean test setting', - type: 'boolean', - value: undefined, - defVal: true, - isCustom: false, - isOverridden: false, - options: null, - }, - image: { - name: 'image:test:setting', - ariaName: 'image test setting', - displayName: 'Image test setting', - description: 'Description for Image test setting', - type: 'image', - value: undefined, - defVal: null, - isCustom: false, - isOverridden: false, - validation: { - maxSize: { - length: 1000, - description: 'Description for 1 kB', - }, - }, - }, - json: { - name: 'json:test:setting', - ariaName: 'json test setting', - displayName: 'Json test setting', - description: 'Description for Json test setting', - type: 'json', - value: '{"foo": "bar"}', - defVal: '{}', - isCustom: false, - isOverridden: false, - options: null, - }, - markdown: { - name: 'markdown:test:setting', - ariaName: 'markdown test setting', - displayName: 'Markdown test setting', - description: 'Description for Markdown test setting', - type: 'markdown', - value: undefined, - defVal: '', - isCustom: false, - isOverridden: false, - options: null, - }, - number: { - name: 'number:test:setting', - ariaName: 'number test setting', - displayName: 'Number test setting', - description: 'Description for Number test setting', - type: 'number', - value: undefined, - defVal: 5, - isCustom: false, - isOverridden: false, - options: null, - }, - select: { - name: 'select:test:setting', - ariaName: 'select test setting', - displayName: 'Select test setting', - description: 'Description for Select test setting', - type: 'select', - value: undefined, - defVal: 'orange', - isCustom: false, - isOverridden: false, - options: ['apple', 'orange', 'banana'], - optionLabels: { - apple: 'Apple', - orange: 'Orange', - // Deliberately left out `banana` to test if it also works with missing labels - }, - }, - string: { - name: 'string:test:setting', - ariaName: 'string test setting', - displayName: 'String test setting', - description: 'Description for String test setting', - type: 'string', - value: undefined, - defVal: null, - isCustom: false, - isOverridden: false, - options: null, - }, - stringWithValidation: { - name: 'string:test-validation:setting', - ariaName: 'string test validation setting', - displayName: 'String test validation setting', - description: 'Description for String test validation setting', - type: 'string', - validation: { - regex: new RegExp('/^foo'), - message: 'must start with "foo"', - }, - value: undefined, - defVal: 'foo-default', - isCustom: false, - isOverridden: false, - options: null, - }, -}; -const userValues = { - array: ['user', 'value'], - boolean: false, - image: 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==', - json: '{"hello": "world"}', - markdown: '**bold**', - number: 10, - select: 'banana', - string: 'foo', - stringWithValidation: 'fooUserValue', -}; -const invalidUserValues = { - stringWithValidation: 'invalidUserValue', -}; -const save = jest.fn(() => Promise.resolve()); -const clear = jest.fn(() => Promise.resolve()); - -describe('Field', () => { - Object.keys(settings).forEach(type => { - const setting = settings[type]; - - describe(`for ${type} setting`, () => { - it('should render default value if there is no user value set', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should render as read only with help text if overridden', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should render as read only if saving is disabled', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should render user value if there is user value is set', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should render custom setting icon if it is custom', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - }); - - if (type === 'select') { - it('should use options for rendering values', () => { - const component = mountWithI18nProvider( - - ); - const select = findTestSubject(component, `advancedSetting-editField-${setting.name}`); - const labels = select.find('option').map(option => option.prop('value')); - expect(labels).toEqual(['apple', 'orange', 'banana']); - }); - - it('should use optionLabels for rendering labels', () => { - const component = mountWithI18nProvider( - - ); - const select = findTestSubject(component, `advancedSetting-editField-${setting.name}`); - const labels = select.find('option').map(option => option.text()); - expect(labels).toEqual(['Apple', 'Orange', 'banana']); - }); - } - - const setup = () => { - const Wrapper = props => ( - - - - ); - const wrapper = mount(); - const component = wrapper.find(I18nProvider).find(Field); - - return { - wrapper, - component, - }; - }; - - if (type === 'image') { - describe(`for changing ${type} setting`, () => { - const { wrapper, component } = setup(); - const userValue = userValues[type]; - component.instance().getImageAsBase64 = file => Promise.resolve(file); - - it('should be able to change value from no value and cancel', async () => { - await component.instance().onImageChange([userValue]); - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-cancelEditField-${setting.name}`).simulate( - 'click' - ); - expect( - component.instance().state.unsavedValue === component.instance().state.savedValue - ).toBe(true); - }); - - it('should be able to change value and save', async () => { - await component.instance().onImageChange([userValue]); - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-saveEditField-${setting.name}`).simulate( - 'click' - ); - expect(save).toBeCalled(); - component.setState({ savedValue: userValue }); - await wrapper.setProps({ - setting: { - ...component.instance().props.setting, - value: userValue, - }, - }); - - await component.instance().cancelChangeImage(); - wrapper.update(); - }); - - it('should be able to change value from existing value and save', async () => { - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-changeImage-${setting.name}`).simulate('click'); - - const newUserValue = `${userValue}=`; - await component.instance().onImageChange([newUserValue]); - const updated2 = wrapper.update(); - findTestSubject(updated2, `advancedSetting-saveEditField-${setting.name}`).simulate( - 'click' - ); - expect(save).toBeCalled(); - component.setState({ savedValue: newUserValue }); - await wrapper.setProps({ - setting: { - ...component.instance().props.setting, - value: newUserValue, - }, - }); - wrapper.update(); - }); - - it('should be able to reset to default value', async () => { - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-resetField-${setting.name}`).simulate('click'); - expect(clear).toBeCalled(); - }); - }); - } else if (type === 'markdown' || type === 'json') { - describe(`for changing ${type} setting`, () => { - const { wrapper, component } = setup(); - const userValue = userValues[type]; - const fieldUserValue = userValue; - - it('should be able to change value and cancel', async () => { - component.instance().onCodeEditorChange(fieldUserValue); - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-cancelEditField-${setting.name}`).simulate( - 'click' - ); - expect( - component.instance().state.unsavedValue === component.instance().state.savedValue - ).toBe(true); - }); - - it('should be able to change value and save', async () => { - component.instance().onCodeEditorChange(fieldUserValue); - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-saveEditField-${setting.name}`).simulate( - 'click' - ); - expect(save).toBeCalled(); - component.setState({ savedValue: fieldUserValue }); - await wrapper.setProps({ - setting: { - ...component.instance().props.setting, - value: userValue, - }, - }); - wrapper.update(); - }); - - if (type === 'json') { - it('should be able to clear value and have empty object populate', async () => { - component.instance().onCodeEditorChange(''); - wrapper.update(); - expect(component.instance().state.unsavedValue).toEqual('{}'); - }); - } - - it('should be able to reset to default value', async () => { - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-resetField-${setting.name}`).simulate('click'); - expect(clear).toBeCalled(); - }); - }); - } else { - describe(`for changing ${type} setting`, () => { - const { wrapper, component } = setup(); - const userValue = userValues[type]; - const fieldUserValue = type === 'array' ? userValue.join(', ') : userValue; - - if (setting.validation) { - const invalidUserValue = invalidUserValues[type]; - it('should display an error when validation fails', async () => { - component.instance().onFieldChange({ target: { value: invalidUserValue } }); - const updated = wrapper.update(); - const errorMessage = updated.find('.euiFormErrorText').text(); - expect(errorMessage).toEqual(setting.validation.message); - }); - } - - it('should be able to change value and cancel', async () => { - component.instance().onFieldChange({ target: { value: fieldUserValue } }); - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-cancelEditField-${setting.name}`).simulate( - 'click' - ); - expect( - component.instance().state.unsavedValue === component.instance().state.savedValue - ).toBe(true); - }); - - it('should be able to change value and save', async () => { - component.instance().onFieldChange({ target: { value: fieldUserValue } }); - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-saveEditField-${setting.name}`).simulate( - 'click' - ); - expect(save).toBeCalled(); - component.setState({ savedValue: fieldUserValue }); - await wrapper.setProps({ - setting: { - ...component.instance().props.setting, - value: userValue, - }, - }); - wrapper.update(); - }); - - it('should be able to reset to default value', async () => { - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-resetField-${setting.name}`).simulate('click'); - expect(clear).toBeCalled(); - }); - }); - } - }); - - it('should show a reload toast when saving setting requiring a page reload', async () => { - const setting = { - ...settings.string, - requiresPageReload: true, - }; - const wrapper = mountWithI18nProvider( - - ); - wrapper.instance().onFieldChange({ target: { value: 'a new value' } }); - const updated = wrapper.update(); - findTestSubject(updated, `advancedSetting-saveEditField-${setting.name}`).simulate('click'); - expect(save).toHaveBeenCalled(); - await save(); - expect(toastNotifications.add).toHaveBeenCalledWith( - expect.objectContaining({ - title: expect.stringContaining('Please reload the page'), - }) - ); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.test.tsx new file mode 100644 index 00000000000000..bd2ba8ac0ebcc6 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.test.tsx @@ -0,0 +1,506 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { I18nProvider } from '@kbn/i18n/react'; +import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; +import { mount } from 'enzyme'; +import { FieldSetting } from '../../types'; +import { UiSettingsType, StringValidation } from '../../../../../../../../../core/public'; + +// @ts-ignore +import { findTestSubject } from '@elastic/eui/lib/test'; +import { Field } from './field'; + +jest.mock('ui/notify', () => ({ + toastNotifications: { + addDanger: () => {}, + add: jest.fn(), + }, +})); + +import { toastNotifications } from 'ui/notify'; + +jest.mock('brace/theme/textmate', () => 'brace/theme/textmate'); +jest.mock('brace/mode/markdown', () => 'brace/mode/markdown'); + +const defaults = { + requiresPageReload: false, + readOnly: false, + category: ['category'], +}; + +const settings: Record = { + array: { + name: 'array:test:setting', + ariaName: 'array test setting', + displayName: 'Array test setting', + description: 'Description for Array test setting', + type: 'array', + value: undefined, + defVal: ['default_value'], + isCustom: false, + isOverridden: false, + ...defaults, + }, + boolean: { + name: 'boolean:test:setting', + ariaName: 'boolean test setting', + displayName: 'Boolean test setting', + description: 'Description for Boolean test setting', + type: 'boolean', + value: undefined, + defVal: true, + isCustom: false, + isOverridden: false, + ...defaults, + }, + image: { + name: 'image:test:setting', + ariaName: 'image test setting', + displayName: 'Image test setting', + description: 'Description for Image test setting', + type: 'image', + value: undefined, + defVal: null, + isCustom: false, + isOverridden: false, + validation: { + maxSize: { + length: 1000, + description: 'Description for 1 kB', + }, + }, + ...defaults, + }, + json: { + name: 'json:test:setting', + ariaName: 'json test setting', + displayName: 'Json test setting', + description: 'Description for Json test setting', + type: 'json', + value: '{"foo": "bar"}', + defVal: '{}', + isCustom: false, + isOverridden: false, + ...defaults, + }, + markdown: { + name: 'markdown:test:setting', + ariaName: 'markdown test setting', + displayName: 'Markdown test setting', + description: 'Description for Markdown test setting', + type: 'markdown', + value: undefined, + defVal: '', + isCustom: false, + isOverridden: false, + ...defaults, + }, + number: { + name: 'number:test:setting', + ariaName: 'number test setting', + displayName: 'Number test setting', + description: 'Description for Number test setting', + type: 'number', + value: undefined, + defVal: 5, + isCustom: false, + isOverridden: false, + ...defaults, + }, + select: { + name: 'select:test:setting', + ariaName: 'select test setting', + displayName: 'Select test setting', + description: 'Description for Select test setting', + type: 'select', + value: undefined, + defVal: 'orange', + isCustom: false, + isOverridden: false, + options: ['apple', 'orange', 'banana'], + optionLabels: { + apple: 'Apple', + orange: 'Orange', + // Deliberately left out `banana` to test if it also works with missing labels + }, + ...defaults, + }, + string: { + name: 'string:test:setting', + ariaName: 'string test setting', + displayName: 'String test setting', + description: 'Description for String test setting', + type: 'string', + value: undefined, + defVal: null, + isCustom: false, + isOverridden: false, + ...defaults, + }, + stringWithValidation: { + name: 'string:test-validation:setting', + ariaName: 'string test validation setting', + displayName: 'String test validation setting', + description: 'Description for String test validation setting', + type: 'string', + validation: { + regex: new RegExp('/^foo'), + message: 'must start with "foo"', + }, + value: undefined, + defVal: 'foo-default', + isCustom: false, + isOverridden: false, + ...defaults, + }, +}; +const userValues = { + array: ['user', 'value'], + boolean: false, + image: 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==', + json: '{"hello": "world"}', + markdown: '**bold**', + number: 10, + select: 'banana', + string: 'foo', + stringWithValidation: 'fooUserValue', +}; +const invalidUserValues = { + stringWithValidation: 'invalidUserValue', +}; +const save = jest.fn(() => Promise.resolve(true)); +const clear = jest.fn(() => Promise.resolve(true)); + +describe('Field', () => { + Object.keys(settings).forEach(type => { + const setting = settings[type]; + + describe(`for ${type} setting`, () => { + it('should render default value if there is no user value set', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render as read only with help text if overridden', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render as read only if saving is disabled', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render user value if there is user value is set', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render custom setting icon if it is custom', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + }); + + if (type === 'select') { + it('should use options for rendering values', () => { + const component = mountWithI18nProvider( + + ); + const select = findTestSubject(component, `advancedSetting-editField-${setting.name}`); + // @ts-ignore + const labels = select.find('option').map(option => option.prop('value')); + expect(labels).toEqual(['apple', 'orange', 'banana']); + }); + + it('should use optionLabels for rendering labels', () => { + const component = mountWithI18nProvider( + + ); + const select = findTestSubject(component, `advancedSetting-editField-${setting.name}`); + // @ts-ignore + const labels = select.find('option').map(option => option.text()); + expect(labels).toEqual(['Apple', 'Orange', 'banana']); + }); + } + + const setup = () => { + const Wrapper = (props: Record) => ( + + + + ); + const wrapper = mount(); + const component = wrapper.find(I18nProvider).find(Field); + + return { + wrapper, + component, + }; + }; + + if (type === 'image') { + describe(`for changing ${type} setting`, () => { + const { wrapper, component } = setup(); + const userValue = userValues[type]; + (component.instance() as Field).getImageAsBase64 = ({}: Blob) => Promise.resolve(''); + + it('should be able to change value from no value and cancel', async () => { + await (component.instance() as Field).onImageChange([userValue]); + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-cancelEditField-${setting.name}`).simulate( + 'click' + ); + expect( + (component.instance() as Field).state.unsavedValue === + (component.instance() as Field).state.savedValue + ).toBe(true); + }); + + it('should be able to change value and save', async () => { + await (component.instance() as Field).onImageChange([userValue]); + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-saveEditField-${setting.name}`).simulate( + 'click' + ); + expect(save).toBeCalled(); + component.setState({ savedValue: userValue }); + await wrapper.setProps({ + setting: { + ...(component.instance() as Field).props.setting, + value: userValue, + }, + }); + + await (component.instance() as Field).cancelChangeImage(); + wrapper.update(); + }); + + it('should be able to change value from existing value and save', async () => { + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-changeImage-${setting.name}`).simulate('click'); + + const newUserValue = `${userValue}=`; + await (component.instance() as Field).onImageChange([newUserValue]); + const updated2 = wrapper.update(); + findTestSubject(updated2, `advancedSetting-saveEditField-${setting.name}`).simulate( + 'click' + ); + expect(save).toBeCalled(); + component.setState({ savedValue: newUserValue }); + await wrapper.setProps({ + setting: { + ...(component.instance() as Field).props.setting, + value: newUserValue, + }, + }); + wrapper.update(); + }); + + it('should be able to reset to default value', async () => { + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-resetField-${setting.name}`).simulate('click'); + expect(clear).toBeCalled(); + }); + }); + } else if (type === 'markdown' || type === 'json') { + describe(`for changing ${type} setting`, () => { + const { wrapper, component } = setup(); + const userValue = userValues[type]; + const fieldUserValue = userValue; + + it('should be able to change value and cancel', async () => { + (component.instance() as Field).onCodeEditorChange(fieldUserValue as UiSettingsType); + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-cancelEditField-${setting.name}`).simulate( + 'click' + ); + expect( + (component.instance() as Field).state.unsavedValue === + (component.instance() as Field).state.savedValue + ).toBe(true); + }); + + it('should be able to change value and save', async () => { + (component.instance() as Field).onCodeEditorChange(fieldUserValue as UiSettingsType); + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-saveEditField-${setting.name}`).simulate( + 'click' + ); + expect(save).toBeCalled(); + component.setState({ savedValue: fieldUserValue }); + await wrapper.setProps({ + setting: { + ...(component.instance() as Field).props.setting, + value: userValue, + }, + }); + wrapper.update(); + }); + + if (type === 'json') { + it('should be able to clear value and have empty object populate', async () => { + (component.instance() as Field).onCodeEditorChange('' as UiSettingsType); + wrapper.update(); + expect((component.instance() as Field).state.unsavedValue).toEqual('{}'); + }); + } + + it('should be able to reset to default value', async () => { + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-resetField-${setting.name}`).simulate('click'); + expect(clear).toBeCalled(); + }); + }); + } else { + describe(`for changing ${type} setting`, () => { + const { wrapper, component } = setup(); + // @ts-ignore + const userValue = userValues[type]; + const fieldUserValue = type === 'array' ? userValue.join(', ') : userValue; + + if (setting.validation) { + // @ts-ignore + const invalidUserValue = invalidUserValues[type]; + it('should display an error when validation fails', async () => { + (component.instance() as Field).onFieldChange(invalidUserValue); + const updated = wrapper.update(); + const errorMessage = updated.find('.euiFormErrorText').text(); + expect(errorMessage).toEqual((setting.validation as StringValidation).message); + }); + } + + it('should be able to change value and cancel', async () => { + (component.instance() as Field).onFieldChange(fieldUserValue); + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-cancelEditField-${setting.name}`).simulate( + 'click' + ); + expect( + (component.instance() as Field).state.unsavedValue === + (component.instance() as Field).state.savedValue + ).toBe(true); + }); + + it('should be able to change value and save', async () => { + (component.instance() as Field).onFieldChange(fieldUserValue); + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-saveEditField-${setting.name}`).simulate( + 'click' + ); + expect(save).toBeCalled(); + component.setState({ savedValue: fieldUserValue }); + await wrapper.setProps({ + setting: { + ...(component.instance() as Field).props.setting, + value: userValue, + }, + }); + wrapper.update(); + }); + + it('should be able to reset to default value', async () => { + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-resetField-${setting.name}`).simulate('click'); + expect(clear).toBeCalled(); + }); + }); + } + }); + + it('should show a reload toast when saving setting requiring a page reload', async () => { + const setting = { + ...settings.string, + requiresPageReload: true, + }; + const wrapper = mountWithI18nProvider( + + ); + (wrapper.instance() as Field).onFieldChange({ target: { value: 'a new value' } }); + const updated = wrapper.update(); + findTestSubject(updated, `advancedSetting-saveEditField-${setting.name}`).simulate('click'); + expect(save).toHaveBeenCalled(); + await save(); + expect(toastNotifications.add).toHaveBeenCalledWith( + expect.objectContaining({ + title: expect.stringContaining('Please reload the page'), + }) + ); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.tsx new file mode 100644 index 00000000000000..524160191d8f08 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/field.tsx @@ -0,0 +1,847 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { PureComponent, Fragment } from 'react'; +import ReactDOM from 'react-dom'; +import { npStart } from 'ui/new_platform'; + +import 'brace/theme/textmate'; +import 'brace/mode/markdown'; + +import { toastNotifications } from 'ui/notify'; +import { + EuiBadge, + EuiButton, + EuiButtonEmpty, + EuiCode, + EuiCodeBlock, + EuiCodeEditor, + EuiDescribedFormGroup, + EuiFieldNumber, + EuiFieldText, + // @ts-ignore + EuiFilePicker, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiIconTip, + EuiImage, + EuiLink, + EuiSpacer, + EuiToolTip, + EuiText, + EuiSelect, + EuiSwitch, + EuiSwitchEvent, + keyCodes, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { FieldSetting } from '../../types'; +import { isDefaultValue } from '../../lib'; +import { + UiSettingsType, + ImageValidation, + StringValidationRegex, +} from '../../../../../../../../../core/public'; + +interface FieldProps { + setting: FieldSetting; + save: (name: string, value: string) => Promise; + clear: (name: string) => Promise; + enableSaving: boolean; +} + +interface FieldState { + unsavedValue: any; + savedValue: any; + loading: boolean; + isInvalid: boolean; + error: string | null; + changeImage: boolean; + isJsonArray: boolean; +} + +export class Field extends PureComponent { + private changeImageForm: EuiFilePicker | undefined; + constructor(props: FieldProps) { + super(props); + const { type, value, defVal } = this.props.setting; + const editableValue = this.getEditableValue(type, value, defVal); + + this.state = { + isInvalid: false, + error: null, + loading: false, + changeImage: false, + savedValue: editableValue, + unsavedValue: editableValue, + isJsonArray: type === 'json' ? Array.isArray(JSON.parse(String(defVal) || '{}')) : false, + }; + } + + UNSAFE_componentWillReceiveProps(nextProps: FieldProps) { + const { unsavedValue } = this.state; + const { type, value, defVal } = nextProps.setting; + const editableValue = this.getEditableValue(type, value, defVal); + + this.setState({ + savedValue: editableValue, + unsavedValue: value === null || value === undefined ? editableValue : unsavedValue, + }); + } + + getEditableValue( + type: UiSettingsType, + value: FieldSetting['value'], + defVal: FieldSetting['defVal'] + ) { + const val = value === null || value === undefined ? defVal : value; + switch (type) { + case 'array': + return (val as string[]).join(', '); + case 'boolean': + return !!val; + case 'number': + return Number(val); + case 'image': + return val; + default: + return val || ''; + } + } + + getDisplayedDefaultValue( + type: UiSettingsType, + defVal: FieldSetting['defVal'], + optionLabels: Record = {} + ) { + if (defVal === undefined || defVal === null || defVal === '') { + return 'null'; + } + switch (type) { + case 'array': + return (defVal as string[]).join(', '); + case 'select': + return optionLabels.hasOwnProperty(String(defVal)) + ? optionLabels[String(defVal)] + : String(defVal); + default: + return String(defVal); + } + } + + setLoading(loading: boolean) { + this.setState({ + loading, + }); + } + + clearError() { + this.setState({ + isInvalid: false, + error: null, + }); + } + + onCodeEditorChange = (value: UiSettingsType) => { + const { type } = this.props.setting; + const { isJsonArray } = this.state; + + let newUnsavedValue; + let isInvalid = false; + let error = null; + + switch (type) { + case 'json': + newUnsavedValue = value.trim() || (isJsonArray ? '[]' : '{}'); + try { + JSON.parse(newUnsavedValue); + } catch (e) { + isInvalid = true; + error = i18n.translate('kbn.management.settings.field.codeEditorSyntaxErrorMessage', { + defaultMessage: 'Invalid JSON syntax', + }); + } + break; + default: + newUnsavedValue = value; + } + + this.setState({ + error, + isInvalid, + unsavedValue: newUnsavedValue, + }); + }; + + onFieldChangeSwitch = (e: EuiSwitchEvent) => { + return this.onFieldChange(e.target.checked); + }; + + onFieldChangeEvent = (e: React.ChangeEvent) => + this.onFieldChange(e.target.value); + + onFieldChange = (value: any) => { + const { type, validation } = this.props.setting; + const { unsavedValue } = this.state; + + let newUnsavedValue; + + switch (type) { + case 'boolean': + newUnsavedValue = !unsavedValue; + break; + case 'number': + newUnsavedValue = Number(value); + break; + default: + newUnsavedValue = value; + } + + let isInvalid = false; + let error = null; + + if (validation && (validation as StringValidationRegex).regex) { + if (!(validation as StringValidationRegex).regex!.test(newUnsavedValue.toString())) { + error = (validation as StringValidationRegex).message; + isInvalid = true; + } + } + + this.setState({ + unsavedValue: newUnsavedValue, + isInvalid, + error, + }); + }; + + onFieldKeyDown = ({ keyCode }: { keyCode: number }) => { + if (keyCode === keyCodes.ENTER) { + this.saveEdit(); + } + if (keyCode === keyCodes.ESCAPE) { + this.cancelEdit(); + } + }; + + onFieldEscape = ({ keyCode }: { keyCode: number }) => { + if (keyCode === keyCodes.ESCAPE) { + this.cancelEdit(); + } + }; + + onImageChange = async (files: any[]) => { + if (!files.length) { + this.clearError(); + this.setState({ + unsavedValue: null, + }); + return; + } + + const file = files[0]; + const { maxSize } = this.props.setting.validation as ImageValidation; + try { + let base64Image = ''; + if (file instanceof File) { + base64Image = (await this.getImageAsBase64(file)) as string; + } + const isInvalid = !!(maxSize && maxSize.length && base64Image.length > maxSize.length); + this.setState({ + isInvalid, + error: isInvalid + ? i18n.translate('kbn.management.settings.field.imageTooLargeErrorMessage', { + defaultMessage: 'Image is too large, maximum size is {maxSizeDescription}', + values: { + maxSizeDescription: maxSize.description, + }, + }) + : null, + changeImage: true, + unsavedValue: base64Image, + }); + } catch (err) { + toastNotifications.addDanger( + i18n.translate('kbn.management.settings.field.imageChangeErrorMessage', { + defaultMessage: 'Image could not be saved', + }) + ); + this.cancelChangeImage(); + } + }; + + async getImageAsBase64(file: Blob): Promise { + const reader = new FileReader(); + reader.readAsDataURL(file); + + return new Promise((resolve, reject) => { + reader.onload = () => { + resolve(reader.result || undefined); + }; + reader.onerror = err => { + reject(err); + }; + }); + } + + changeImage = () => { + this.setState({ + changeImage: true, + }); + }; + + cancelChangeImage = () => { + const { savedValue } = this.state; + + if (this.changeImageForm) { + this.changeImageForm.fileInput.value = null; + this.changeImageForm.handleChange(); + } + + this.setState({ + changeImage: false, + unsavedValue: savedValue, + }); + }; + + cancelEdit = () => { + const { savedValue } = this.state; + this.clearError(); + this.setState({ + unsavedValue: savedValue, + }); + }; + + showPageReloadToast = () => { + if (this.props.setting.requiresPageReload) { + toastNotifications.add({ + title: i18n.translate('kbn.management.settings.field.requiresPageReloadToastDescription', { + defaultMessage: 'Please reload the page for the "{settingName}" setting to take effect.', + values: { + settingName: this.props.setting.displayName || this.props.setting.name, + }, + }), + text: element => { + const content = ( + <> + + + window.location.reload()}> + {i18n.translate( + 'kbn.management.settings.field.requiresPageReloadToastButtonLabel', + { defaultMessage: 'Reload page' } + )} + + + + + ); + ReactDOM.render(content, element); + return () => ReactDOM.unmountComponentAtNode(element); + }, + color: 'success', + }); + } + }; + + saveEdit = async () => { + const { name, defVal, type } = this.props.setting; + const { changeImage, savedValue, unsavedValue, isJsonArray } = this.state; + + if (savedValue === unsavedValue) { + return; + } + + let valueToSave = unsavedValue; + let isSameValue = false; + + switch (type) { + case 'array': + valueToSave = valueToSave.split(',').map((val: string) => val.trim()); + isSameValue = valueToSave.join(',') === (defVal as string[]).join(','); + break; + case 'json': + valueToSave = valueToSave.trim(); + valueToSave = valueToSave || (isJsonArray ? '[]' : '{}'); + default: + isSameValue = valueToSave === defVal; + } + + this.setLoading(true); + try { + if (isSameValue) { + await this.props.clear(name); + } else { + await this.props.save(name, valueToSave); + } + + this.showPageReloadToast(); + + if (changeImage) { + this.cancelChangeImage(); + } + } catch (e) { + toastNotifications.addDanger( + i18n.translate('kbn.management.settings.field.saveFieldErrorMessage', { + defaultMessage: 'Unable to save {name}', + values: { name }, + }) + ); + } + this.setLoading(false); + }; + + resetField = async () => { + const { name } = this.props.setting; + this.setLoading(true); + try { + await this.props.clear(name); + this.showPageReloadToast(); + this.cancelChangeImage(); + this.clearError(); + } catch (e) { + toastNotifications.addDanger( + i18n.translate('kbn.management.settings.field.resetFieldErrorMessage', { + defaultMessage: 'Unable to reset {name}', + values: { name }, + }) + ); + } + this.setLoading(false); + }; + + renderField(setting: FieldSetting) { + const { enableSaving } = this.props; + const { loading, changeImage, unsavedValue } = this.state; + const { name, value, type, options, optionLabels = {}, isOverridden, ariaName } = setting; + + switch (type) { + case 'boolean': + return ( + + ) : ( + + ) + } + checked={!!unsavedValue} + onChange={this.onFieldChangeSwitch} + disabled={loading || isOverridden || !enableSaving} + onKeyDown={this.onFieldKeyDown} + data-test-subj={`advancedSetting-editField-${name}`} + aria-label={ariaName} + /> + ); + case 'markdown': + case 'json': + return ( +
+ +
+ ); + case 'image': + if (!isDefaultValue(setting) && !changeImage) { + return ( + + ); + } else { + return ( + { + this.changeImageForm = input; + }} + onKeyDown={this.onFieldEscape} + data-test-subj={`advancedSetting-editField-${name}`} + /> + ); + } + case 'select': + return ( + { + return { + text: optionLabels.hasOwnProperty(option) ? optionLabels[option] : option, + value: option, + }; + })} + onChange={this.onFieldChangeEvent} + isLoading={loading} + disabled={loading || isOverridden || !enableSaving} + onKeyDown={this.onFieldKeyDown} + data-test-subj={`advancedSetting-editField-${name}`} + /> + ); + case 'number': + return ( + + ); + default: + return ( + + ); + } + } + + renderLabel(setting: FieldSetting) { + return setting.name; + } + + renderHelpText(setting: FieldSetting) { + if (setting.isOverridden) { + return ( + + + + ); + } + + const canUpdateSetting = this.props.enableSaving; + const defaultLink = this.renderResetToDefaultLink(setting); + const imageLink = this.renderChangeImageLink(setting); + + if (canUpdateSetting && (defaultLink || imageLink)) { + return ( + + {defaultLink} + {imageLink} + + ); + } + + return null; + } + + renderTitle(setting: FieldSetting) { + return ( +

+ {setting.displayName || setting.name} + {setting.isCustom ? ( + + } + /> + ) : ( + '' + )} +

+ ); + } + + renderDescription(setting: FieldSetting) { + let description; + let deprecation; + + if (setting.deprecation) { + const { links } = npStart.core.docLinks; + + deprecation = ( + <> + + { + window.open(links.management[setting.deprecation!.docLinksKey], '_blank'); + }} + onClickAriaLabel={i18n.translate( + 'kbn.management.settings.field.deprecationClickAreaLabel', + { + defaultMessage: 'Click to view deprecation documentation for {settingName}.', + values: { + settingName: setting.name, + }, + } + )} + > + Deprecated + + + + + ); + } + + if (React.isValidElement(setting.description)) { + description = setting.description; + } else { + description = ( +
+ ); + } + + return ( + + {deprecation} + {description} + {this.renderDefaultValue(setting)} + + ); + } + + renderDefaultValue(setting: FieldSetting) { + const { type, defVal, optionLabels } = setting; + if (isDefaultValue(setting)) { + return; + } + return ( + + + + {type === 'json' ? ( + + = 500 ? 300 : undefined} + > + {this.getDisplayedDefaultValue(type, defVal)} + + ), + }} + /> + + ) : ( + + {this.getDisplayedDefaultValue(type, defVal, optionLabels)} + ), + }} + /> + + )} + + + ); + } + + renderResetToDefaultLink(setting: FieldSetting) { + const { ariaName, name } = setting; + if (isDefaultValue(setting)) { + return; + } + return ( + + + + +     + + ); + } + + renderChangeImageLink(setting: FieldSetting) { + const { changeImage } = this.state; + const { type, value, ariaName, name } = setting; + if (type !== 'image' || !value || changeImage) { + return; + } + return ( + + + + + + ); + } + + renderActions(setting: FieldSetting) { + const { ariaName, name } = setting; + const { loading, isInvalid, changeImage, savedValue, unsavedValue } = this.state; + const isDisabled = loading || setting.isOverridden; + + if (savedValue === unsavedValue && !changeImage) { + return; + } + + return ( + + + + + + + + + (changeImage ? this.cancelChangeImage() : this.cancelEdit())} + disabled={isDisabled} + data-test-subj={`advancedSetting-cancelEditField-${name}`} + > + + + + + + ); + } + + render() { + const { setting } = this.props; + const { error, isInvalid } = this.state; + + return ( + + + + + {this.renderField(setting)} + + + + {this.renderActions(setting)} + + ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap deleted file mode 100644 index 4111b3d5fa2d3f..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap +++ /dev/null @@ -1,375 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Form should not render no settings message when instructed not to 1`] = ``; - -exports[`Form should render no settings message when there are no settings 1`] = ` - - - - - , - } - } - /> - - -`; - -exports[`Form should render normally 1`] = ` - - - - - - -

- General -

-
-
-
- - - -
-
- - - - - - -

- Dashboard -

-
-
-
- - -
-
- - - - - - -

- X-pack -

-
- - - - - - - , - "settingsCount": 9, - } - } - /> - - -
-
- - -
-
- -
-`; - -exports[`Form should render read-only when saving is disabled 1`] = ` - - - - - - -

- General -

-
-
-
- - - -
-
- - - - - - -

- Dashboard -

-
-
-
- - -
-
- - - - - - -

- X-pack -

-
- - - - - - - , - "settingsCount": 9, - } - } - /> - - -
-
- - -
-
- -
-`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.tsx.snap new file mode 100644 index 00000000000000..b43c17c2a88656 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.tsx.snap @@ -0,0 +1,433 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Form should not render no settings message when instructed not to 1`] = ``; + +exports[`Form should render no settings message when there are no settings 1`] = ` + + + + + , + } + } + /> + + +`; + +exports[`Form should render normally 1`] = ` + + + + + + +

+ General +

+
+
+
+ + + +
+
+ + + + + + +

+ Dashboard +

+
+
+
+ + +
+
+ + + + + + +

+ X-pack +

+
+ + + + + + + , + "settingsCount": 9, + } + } + /> + + +
+
+ + +
+
+ +
+`; + +exports[`Form should render read-only when saving is disabled 1`] = ` + + + + + + +

+ General +

+
+
+
+ + + +
+
+ + + + + + +

+ Dashboard +

+
+
+
+ + +
+
+ + + + + + +

+ X-pack +

+
+ + + + + + + , + "settingsCount": 9, + } + } + /> + + +
+
+ + +
+
+ +
+`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.js deleted file mode 100644 index 19d8b9da446c76..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.js +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { PureComponent, Fragment } from 'react'; -import PropTypes from 'prop-types'; - -import { - EuiFlexGroup, - EuiFlexItem, - EuiForm, - EuiLink, - EuiPanel, - EuiSpacer, - EuiText, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { getCategoryName } from '../../lib'; -import { Field } from '../field'; - -export class Form extends PureComponent { - static propTypes = { - settings: PropTypes.object.isRequired, - categories: PropTypes.array.isRequired, - categoryCounts: PropTypes.object.isRequired, - clearQuery: PropTypes.func.isRequired, - save: PropTypes.func.isRequired, - clear: PropTypes.func.isRequired, - showNoResultsMessage: PropTypes.bool.isRequired, - enableSaving: PropTypes.bool.isRequired, - }; - - renderClearQueryLink(totalSettings, currentSettings) { - const { clearQuery } = this.props; - - if (totalSettings !== currentSettings) { - return ( - - - - - - - - ), - }} - /> - - - ); - } - - return null; - } - - renderCategory(category, settings, totalSettings) { - return ( - - - - - - -

{getCategoryName(category)}

-
- {this.renderClearQueryLink(totalSettings, settings.length)} -
-
- - {settings.map(setting => { - return ( - - ); - })} -
-
- -
- ); - } - - maybeRenderNoSettings(clearQuery) { - if (this.props.showNoResultsMessage) { - return ( - - - - - ), - }} - /> - - ); - } - return null; - } - - render() { - const { settings, categories, categoryCounts, clearQuery } = this.props; - const currentCategories = []; - - categories.forEach(category => { - if (settings[category] && settings[category].length) { - currentCategories.push(category); - } - }); - - return ( - - {currentCategories.length - ? currentCategories.map(category => { - return this.renderCategory(category, settings[category], categoryCounts[category]); // fix this - }) - : this.maybeRenderNoSettings(clearQuery)} - - ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.test.js deleted file mode 100644 index 7befed814e5d0a..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.test.js +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; - -import { Form } from './form'; - -jest.mock('../field', () => ({ - Field: () => { - return 'field'; - }, -})); - -const settings = { - dashboard: [ - { - name: 'dashboard:test:setting', - ariaName: 'dashboard test setting', - displayName: 'Dashboard test setting', - category: ['dashboard'], - }, - ], - general: [ - { - name: 'general:test:date', - ariaName: 'general test date', - displayName: 'Test date', - description: 'bar', - category: ['general'], - }, - { - name: 'setting:test', - ariaName: 'setting test', - displayName: 'Test setting', - description: 'foo', - category: ['general'], - }, - ], - 'x-pack': [ - { - name: 'xpack:test:setting', - ariaName: 'xpack test setting', - displayName: 'X-Pack test setting', - category: ['x-pack'], - description: 'bar', - }, - ], -}; -const categories = ['general', 'dashboard', 'hiddenCategory', 'x-pack']; -const categoryCounts = { - general: 2, - dashboard: 1, - 'x-pack': 10, -}; -const save = () => {}; -const clear = () => {}; -const clearQuery = () => {}; - -describe('Form', () => { - it('should render normally', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should render read-only when saving is disabled', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should render no settings message when there are no settings', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should not render no settings message when instructed not to', async () => { - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.test.tsx new file mode 100644 index 00000000000000..6bbcfd543a6290 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.test.tsx @@ -0,0 +1,160 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; +import { UiSettingsType } from '../../../../../../../../../core/public'; + +import { Form } from './form'; + +jest.mock('../field', () => ({ + Field: () => { + return 'field'; + }, +})); + +const defaults = { + requiresPageReload: false, + readOnly: false, + value: 'value', + description: 'description', + isOverridden: false, + type: 'string' as UiSettingsType, + isCustom: false, + defVal: 'defVal', +}; + +const settings = { + dashboard: [ + { + name: 'dashboard:test:setting', + ariaName: 'dashboard test setting', + displayName: 'Dashboard test setting', + category: ['dashboard'], + ...defaults, + }, + ], + general: [ + { + name: 'general:test:date', + ariaName: 'general test date', + displayName: 'Test date', + description: 'bar', + category: ['general'], + ...defaults, + }, + { + name: 'setting:test', + ariaName: 'setting test', + displayName: 'Test setting', + description: 'foo', + category: ['general'], + ...defaults, + }, + ], + 'x-pack': [ + { + name: 'xpack:test:setting', + ariaName: 'xpack test setting', + displayName: 'X-Pack test setting', + category: ['x-pack'], + description: 'bar', + ...defaults, + }, + ], +}; +const categories = ['general', 'dashboard', 'hiddenCategory', 'x-pack']; +const categoryCounts = { + general: 2, + dashboard: 1, + 'x-pack': 10, +}; +const save = (key: string, value: any) => Promise.resolve(true); +const clear = (key: string) => Promise.resolve(true); +const clearQuery = () => {}; + +describe('Form', () => { + it('should render normally', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render read-only when saving is disabled', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render no settings message when there are no settings', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should not render no settings message when instructed not to', async () => { + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.tsx new file mode 100644 index 00000000000000..113e0b2db5f308 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/form.tsx @@ -0,0 +1,159 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { PureComponent, Fragment } from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiLink, + EuiPanel, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { getCategoryName } from '../../lib'; +import { Field } from '../field'; +import { FieldSetting } from '../../types'; + +type Category = string; + +interface FormProps { + settings: Record; + categories: Category[]; + categoryCounts: Record; + clearQuery: () => void; + save: (key: string, value: any) => Promise; + clear: (key: string) => Promise; + showNoResultsMessage: boolean; + enableSaving: boolean; +} + +export class Form extends PureComponent { + renderClearQueryLink(totalSettings: number, currentSettings: number) { + const { clearQuery } = this.props; + + if (totalSettings !== currentSettings) { + return ( + + + + + + + + ), + }} + /> + + + ); + } + + return null; + } + + renderCategory(category: Category, settings: FieldSetting[], totalSettings: number) { + return ( + + + + + + +

{getCategoryName(category)}

+
+ {this.renderClearQueryLink(totalSettings, settings.length)} +
+
+ + {settings.map(setting => { + return ( + + ); + })} +
+
+ +
+ ); + } + + maybeRenderNoSettings(clearQuery: FormProps['clearQuery']) { + if (this.props.showNoResultsMessage) { + return ( + + + + + ), + }} + /> + + ); + } + return null; + } + + render() { + const { settings, categories, categoryCounts, clearQuery } = this.props; + const currentCategories: Category[] = []; + + categories.forEach(category => { + if (settings[category] && settings[category].length) { + currentCategories.push(category); + } + }); + + return ( + + {currentCategories.length + ? currentCategories.map(category => { + return this.renderCategory(category, settings[category], categoryCounts[category]); + }) + : this.maybeRenderNoSettings(clearQuery)} + + ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/__snapshots__/page_footer.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/__snapshots__/page_footer.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/__snapshots__/page_footer.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/__snapshots__/page_footer.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/page_footer.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/page_footer.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/page_footer.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/page_footer.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/page_footer.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/page_footer.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/page_footer.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_footer/page_footer.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/__snapshots__/page_subtitle.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/__snapshots__/page_subtitle.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/__snapshots__/page_subtitle.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/__snapshots__/page_subtitle.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/page_subtitle.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/page_subtitle.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/page_subtitle.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/page_subtitle.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/page_subtitle.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/page_subtitle.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/page_subtitle.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_subtitle/page_subtitle.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/__snapshots__/page_title.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/__snapshots__/page_title.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/__snapshots__/page_title.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/__snapshots__/page_title.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/page_title.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/page_title.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/page_title.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/page_title.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/page_title.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/page_title.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/page_title.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/page_title/page_title.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/__snapshots__/search.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/__snapshots__/search.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/__snapshots__/search.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/__snapshots__/search.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.js deleted file mode 100644 index 02315e73cc11b8..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.js +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { Fragment, PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { i18n } from '@kbn/i18n'; - -import { EuiSearchBar, EuiFormErrorText } from '@elastic/eui'; - -import { getCategoryName } from '../../lib'; - -export class Search extends PureComponent { - static propTypes = { - categories: PropTypes.array.isRequired, - query: PropTypes.object.isRequired, - onQueryChange: PropTypes.func.isRequired, - }; - - constructor(props) { - super(props); - const { categories } = props; - this.categories = categories.map(category => { - return { - value: category, - name: getCategoryName(category), - }; - }); - } - - state = { - isSearchTextValid: true, - parseErrorMessage: null, - }; - - onChange = ({ query, error }) => { - if (error) { - this.setState({ - isSearchTextValid: false, - parseErrorMessage: error.message, - }); - return; - } - - this.setState({ - isSearchTextValid: true, - parseErrorMessage: null, - }); - this.props.onQueryChange({ query }); - }; - - render() { - const { query } = this.props; - - const box = { - incremental: true, - 'data-test-subj': 'settingsSearchBar', - 'aria-label': i18n.translate('kbn.management.settings.searchBarAriaLabel', { - defaultMessage: 'Search advanced settings', - }), // hack until EuiSearchBar is fixed - }; - - const filters = [ - { - type: 'field_value_selection', - field: 'category', - name: i18n.translate('kbn.management.settings.categorySearchLabel', { - defaultMessage: 'Category', - }), - multiSelect: 'or', - options: this.categories, - }, - ]; - - let queryParseError; - if (!this.state.isSearchTextValid) { - const parseErrorMsg = i18n.translate( - 'kbn.management.settings.searchBar.unableToParseQueryErrorMessage', - { defaultMessage: 'Unable to parse query' } - ); - queryParseError = ( - {`${parseErrorMsg}. ${this.state.parseErrorMessage}`} - ); - } - - return ( - - - {queryParseError} - - ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.test.js deleted file mode 100644 index 3cd2de6ddccaa7..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.test.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; -import { findTestSubject } from '@elastic/eui/lib/test'; - -import { Query } from '@elastic/eui'; -import { Search } from './search'; - -const query = Query.parse(''); -const categories = ['general', 'dashboard', 'hiddenCategory', 'x-pack']; - -describe('Search', () => { - it('should render normally', async () => { - const onQueryChange = () => {}; - const component = shallowWithI18nProvider( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('should call parent function when query is changed', async () => { - //This test is brittle as it knows about implementation details - // (EuiFieldSearch uses onKeyup instead of onChange to handle input) - const onQueryChange = jest.fn(); - const component = mountWithI18nProvider( - - ); - findTestSubject(component, 'settingsSearchBar').simulate('keyup', { - target: { value: 'new filter' }, - }); - expect(onQueryChange).toHaveBeenCalledTimes(1); - }); - - it('should handle query parse error', async () => { - const onQueryChangeMock = jest.fn(); - const component = mountWithI18nProvider( - - ); - - const searchBar = findTestSubject(component, 'settingsSearchBar'); - - // Send invalid query - searchBar.simulate('keyup', { target: { value: '?' } }); - expect(onQueryChangeMock).toHaveBeenCalledTimes(0); - expect(component.state().isSearchTextValid).toBe(false); - - onQueryChangeMock.mockReset(); - - // Send valid query to ensure component can recover from invalid query - searchBar.simulate('keyup', { target: { value: 'dateFormat' } }); - expect(onQueryChangeMock).toHaveBeenCalledTimes(1); - expect(component.state().isSearchTextValid).toBe(true); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.test.tsx new file mode 100644 index 00000000000000..8e7bac5129ae94 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.test.tsx @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; +// @ts-ignore +import { findTestSubject } from '@elastic/eui/lib/test'; + +import { Query } from '@elastic/eui'; +import { Search } from './search'; + +const query = Query.parse(''); +const categories = ['general', 'dashboard', 'hiddenCategory', 'x-pack']; + +describe('Search', () => { + it('should render normally', async () => { + const onQueryChange = () => {}; + const component = shallowWithI18nProvider( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should call parent function when query is changed', async () => { + // This test is brittle as it knows about implementation details + // (EuiFieldSearch uses onKeyup instead of onChange to handle input) + const onQueryChange = jest.fn(); + const component = mountWithI18nProvider( + + ); + findTestSubject(component, 'settingsSearchBar').simulate('keyup', { + target: { value: 'new filter' }, + }); + expect(onQueryChange).toHaveBeenCalledTimes(1); + }); + + it('should handle query parse error', async () => { + const onQueryChangeMock = jest.fn(); + const component = mountWithI18nProvider( + + ); + + const searchBar = findTestSubject(component, 'settingsSearchBar'); + + // Send invalid query + searchBar.simulate('keyup', { target: { value: '?' } }); + expect(onQueryChangeMock).toHaveBeenCalledTimes(0); + expect(component.state().isSearchTextValid).toBe(false); + + onQueryChangeMock.mockReset(); + + // Send valid query to ensure component can recover from invalid query + searchBar.simulate('keyup', { target: { value: 'dateFormat' } }); + expect(onQueryChangeMock).toHaveBeenCalledTimes(1); + expect(component.state().isSearchTextValid).toBe(true); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.tsx b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.tsx new file mode 100644 index 00000000000000..471f2ba28005ca --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/search/search.tsx @@ -0,0 +1,113 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { Fragment, PureComponent } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + // @ts-ignore + EuiSearchBar, + EuiFormErrorText, +} from '@elastic/eui'; +import { IQuery } from '../../types'; + +import { getCategoryName } from '../../lib'; + +interface SearchProps { + categories: string[]; + query: IQuery; + onQueryChange: ({ query }: { query: IQuery }) => void; +} + +export class Search extends PureComponent { + private categories: Array<{ value: string; name: string }> = []; + + constructor(props: SearchProps) { + super(props); + const { categories } = props; + this.categories = categories.map(category => { + return { + value: category, + name: getCategoryName(category), + }; + }); + } + + state = { + isSearchTextValid: true, + parseErrorMessage: null, + }; + + onChange = ({ query, error }: { query: IQuery; error: { message: string } }) => { + if (error) { + this.setState({ + isSearchTextValid: false, + parseErrorMessage: error.message, + }); + return; + } + + this.setState({ + isSearchTextValid: true, + parseErrorMessage: null, + }); + this.props.onQueryChange({ query }); + }; + + render() { + const { query } = this.props; + + const box = { + incremental: true, + 'data-test-subj': 'settingsSearchBar', + 'aria-label': i18n.translate('kbn.management.settings.searchBarAriaLabel', { + defaultMessage: 'Search advanced settings', + }), // hack until EuiSearchBar is fixed + }; + + const filters = [ + { + type: 'field_value_selection', + field: 'category', + name: i18n.translate('kbn.management.settings.categorySearchLabel', { + defaultMessage: 'Category', + }), + multiSelect: 'or', + options: this.categories, + }, + ]; + + let queryParseError; + if (!this.state.isSearchTextValid) { + const parseErrorMsg = i18n.translate( + 'kbn.management.settings.searchBar.unableToParseQueryErrorMessage', + { defaultMessage: 'Unable to parse query' } + ); + queryParseError = ( + {`${parseErrorMsg}. ${this.state.parseErrorMessage}`} + ); + } + + return ( + + + {queryParseError} + + ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/index.html b/src/legacy/core_plugins/kibana/public/management/sections/settings/index.html index e1b901a9669606..2fe8fce08b4abc 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/index.html +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/index.html @@ -1,5 +1,5 @@ -
+
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/index.js index f03dcd195092aa..6d8987b1a928e5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/index.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/index.js @@ -29,38 +29,10 @@ import { } from 'ui/registry/feature_catalogue'; import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; import { AdvancedSettings } from './advanced_settings'; import { i18n } from '@kbn/i18n'; import { getBreadcrumbs } from './breadcrumbs'; -const REACT_ADVANCED_SETTINGS_DOM_ELEMENT_ID = 'reactAdvancedSettings'; - -function updateAdvancedSettings($scope, config, query) { - $scope.$$postDigest(() => { - const node = document.getElementById(REACT_ADVANCED_SETTINGS_DOM_ELEMENT_ID); - if (!node) { - return; - } - - render( - - - , - node - ); - }); -} - -function destroyAdvancedSettings() { - const node = document.getElementById(REACT_ADVANCED_SETTINGS_DOM_ELEMENT_ID); - node && unmountComponentAtNode(node); -} - uiRoutes.when('/management/kibana/settings/:setting?', { template: indexTemplate, k7Breadcrumbs: getBreadcrumbs, @@ -82,23 +54,28 @@ uiRoutes.when('/management/kibana/settings/:setting?', { }, }); -uiModules.get('apps/management').directive('kbnManagementAdvanced', function(config, $route) { +uiModules.get('apps/management').directive('kbnManagementAdvanced', function($route) { return { restrict: 'E', link: function($scope) { - config.watchAll(() => { - updateAdvancedSettings($scope, config, $route.current.params.setting || ''); - }, $scope); - - $scope.$on('$destroy', () => { - destroyAdvancedSettings(); - }); - + $scope.query = $route.current.params.setting || ''; $route.updateParams({ setting: null }); }, }; }); +const AdvancedSettingsApp = ({ query = '' }) => { + return ( + + + + ); +}; + +uiModules.get('apps/management').directive('kbnManagementAdvancedReact', function(reactDirective) { + return reactDirective(AdvancedSettingsApp, [['query', { watchDepth: 'reference' }]]); +}); + management.getSection('kibana').register('settings', { display: i18n.translate('kbn.management.settings.sectionLabel', { defaultMessage: 'Advanced Settings', diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js deleted file mode 100644 index 1172542dbce3d0..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { DEFAULT_CATEGORY } from '../default_category'; - -describe('Settings', function() { - describe('Advanced', function() { - describe('DEFAULT_CATEGORY', function() { - it('should be general', function() { - expect(DEFAULT_CATEGORY).to.be('general'); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js deleted file mode 100644 index 0e54480813e3fb..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { getAriaName } from '../get_aria_name'; - -describe('Settings', function() { - describe('Advanced', function() { - describe('getAriaName(name)', function() { - it('should be a function', function() { - expect(getAriaName).to.be.a(Function); - }); - - it('should return a space delimited lower-case string with no special characters', function() { - expect(getAriaName('xPack:defaultAdminEmail')).to.be('x pack default admin email'); - expect(getAriaName('doc_table:highlight')).to.be('doc table highlight'); - expect(getAriaName('foo')).to.be('foo'); - }); - - it('should return an empty string if passed undefined or null', function() { - expect(getAriaName()).to.be(''); - expect(getAriaName(undefined)).to.be(''); - expect(getAriaName(null)).to.be(''); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js deleted file mode 100644 index 731281933161b3..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { getCategoryName } from '../get_category_name'; - -describe('Settings', function() { - describe('Advanced', function() { - describe('getCategoryName(category)', function() { - it('should be a function', function() { - expect(getCategoryName).to.be.a(Function); - }); - - it('should return correct name for known categories', function() { - expect(getCategoryName('general')).to.be('General'); - expect(getCategoryName('timelion')).to.be('Timelion'); - expect(getCategoryName('notifications')).to.be('Notifications'); - expect(getCategoryName('visualizations')).to.be('Visualizations'); - expect(getCategoryName('discover')).to.be('Discover'); - expect(getCategoryName('dashboard')).to.be('Dashboard'); - expect(getCategoryName('reporting')).to.be('Reporting'); - expect(getCategoryName('search')).to.be('Search'); - }); - - it('should capitalize unknown category', function() { - expect(getCategoryName('elasticsearch')).to.be('Elasticsearch'); - }); - - it('should return empty string for no category', function() { - expect(getCategoryName()).to.be(''); - expect(getCategoryName('')).to.be(''); - expect(getCategoryName(false)).to.be(''); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js deleted file mode 100644 index 0a6cce972e518b..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { getValType } from '../get_val_type'; - -describe('Settings', function() { - describe('Advanced', function() { - describe('getValType(def, val)', function() { - it('should be a function', function() { - expect(getValType).to.be.a(Function); - }); - - it('should return the explicitly defined type of a setting', function() { - expect(getValType({ type: 'string' })).to.be('string'); - expect(getValType({ type: 'json' })).to.be('json'); - expect(getValType({ type: 'string', value: 5 })).to.be('string'); - }); - - it('should return array if the value is an Array and there is no defined type', function() { - expect(getValType({ type: 'string' }, [1, 2, 3])).to.be('string'); - expect(getValType({ type: 'json', value: [1, 2, 3] })).to.be('json'); - - expect(getValType({ value: 'someString' }, [1, 2, 3])).to.be('array'); - expect(getValType({ value: [1, 2, 3] }, 'someString')).to.be('array'); - }); - - it('should return the type of the default value if there is no type and it is not an array', function() { - expect(getValType({ value: 'someString' })).to.be('string'); - expect(getValType({ value: 'someString' }, 42)).to.be('string'); - }); - - it('should return the type of the value if the default value is null', function() { - expect(getValType({ value: null }, 'someString')).to.be('string'); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js deleted file mode 100644 index 58ffd0597a34a9..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { isDefaultValue } from '../is_default_value'; - -describe('Settings', function() { - describe('Advanced', function() { - describe('getCategoryName(category)', function() { - it('should be a function', function() { - expect(isDefaultValue).to.be.a(Function); - }); - - describe('when given a setting definition object', function() { - const setting = { - isCustom: false, - value: 'value', - defVal: 'defaultValue', - }; - - describe('that is custom', function() { - it('should return true', function() { - expect(isDefaultValue({ ...setting, isCustom: true })).to.be(true); - }); - }); - - describe('without a value', function() { - it('should return true', function() { - expect(isDefaultValue({ ...setting, value: undefined })).to.be(true); - expect(isDefaultValue({ ...setting, value: '' })).to.be(true); - }); - }); - - describe('with a value that is the same as the default value', function() { - it('should return true', function() { - expect(isDefaultValue({ ...setting, value: 'defaultValue' })).to.be(true); - expect(isDefaultValue({ ...setting, value: [], defVal: [] })).to.be(true); - expect( - isDefaultValue({ ...setting, value: '{"foo":"bar"}', defVal: '{"foo":"bar"}' }) - ).to.be(true); - expect(isDefaultValue({ ...setting, value: 123, defVal: 123 })).to.be(true); - expect(isDefaultValue({ ...setting, value: 456, defVal: '456' })).to.be(true); - expect(isDefaultValue({ ...setting, value: false, defVal: false })).to.be(true); - }); - }); - - describe('with a value that is different than the default value', function() { - it('should return false', function() { - expect(isDefaultValue({ ...setting })).to.be(false); - expect(isDefaultValue({ ...setting, value: [1], defVal: [2] })).to.be(false); - expect( - isDefaultValue({ ...setting, value: '{"foo":"bar"}', defVal: '{"foo2":"bar2"}' }) - ).to.be(false); - expect(isDefaultValue({ ...setting, value: 123, defVal: 1234 })).to.be(false); - expect(isDefaultValue({ ...setting, value: 456, defVal: '4567' })).to.be(false); - expect(isDefaultValue({ ...setting, value: true, defVal: false })).to.be(false); - }); - }); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js deleted file mode 100644 index 4896b4516dd1da..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { toEditableConfig } from '../to_editable_config'; - -describe('Settings', function() { - describe('Advanced', function() { - describe('toEditableConfig(def, name, value)', function() { - it('sets name', function() { - expect(invoke({ name: 'who' }).name).to.equal('who'); - }); - - it('sets value', function() { - expect(invoke({ value: 'what' }).value).to.equal('what'); - }); - - it('sets type', function() { - expect(invoke({ value: 'what' }).type).to.be('string'); - expect(invoke({ value: 0 }).type).to.be('number'); - expect(invoke({ value: [] }).type).to.be('array'); - }); - - describe('when given a setting definition object', function() { - let def; - beforeEach(function() { - def = { - value: 'the original', - description: 'the one and only', - options: 'all the options', - }; - }); - - it('is not marked as custom', function() { - expect(invoke({ def }).isCustom).to.be.false; - }); - - it('sets a default value', function() { - expect(invoke({ def }).defVal).to.equal(def.value); - }); - - it('sets a description', function() { - expect(invoke({ def }).description).to.equal(def.description); - }); - - it('sets options', function() { - expect(invoke({ def }).options).to.equal(def.options); - }); - - describe('that contains a type', function() { - it('sets that type', function() { - def.type = 'something'; - expect(invoke({ def }).type).to.equal(def.type); - }); - }); - - describe('that contains a value of type array', function() { - it('sets type to array', function() { - def.value = []; - expect(invoke({ def }).type).to.equal('array'); - }); - }); - - describe('that contains a validation object', function() { - it('constructs a validation regex with message', function() { - def.validation = { - regexString: '^foo', - message: 'must start with "foo"', - }; - const result = invoke({ def }); - expect(result.validation.regex).to.be.a(RegExp); - expect(result.validation.message).to.equal('must start with "foo"'); - }); - }); - }); - - describe('when not given a setting definition object', function() { - it('is marked as custom', function() { - expect(invoke().isCustom).to.be.true; - }); - - it('sets defVal to undefined', function() { - expect(invoke().defVal).to.be.undefined; - }); - - it('sets description to undefined', function() { - expect(invoke().description).to.be.undefined; - }); - - it('sets options to undefined', function() { - expect(invoke().options).to.be.undefined; - }); - - it('sets validation to undefined', function() { - expect(invoke().validation).to.be.undefined; - }); - }); - }); - }); -}); - -function invoke({ def = false, name = 'woah', value = 'forreal' } = {}) { - return toEditableConfig({ def, name, value, isCustom: def === false }); -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/default_category.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/default_category.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/lib/default_category.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/lib/default_category.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.js deleted file mode 100644 index c75c761328370d..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { words } from 'lodash'; - -/** - * @name {string} the name of the configuration object - * @returns {string} a space delimited, lowercase string with - * special characters removed. - * - * Example: 'xPack:fooBar:foo_bar_baz' -> 'x pack foo bar foo bar baz' - */ -export function getAriaName(name) { - return words(name) - .map(word => word.toLowerCase()) - .join(' '); -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.test.ts new file mode 100644 index 00000000000000..e129481a397c16 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.test.ts @@ -0,0 +1,38 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { getAriaName } from './get_aria_name'; + +describe('Settings', function() { + describe('Advanced', function() { + describe('getAriaName(name)', function() { + it('should return a space delimited lower-case string with no special characters', function() { + expect(getAriaName('xPack:defaultAdminEmail')).to.be('x pack default admin email'); + expect(getAriaName('doc_table:highlight')).to.be('doc table highlight'); + expect(getAriaName('foo')).to.be('foo'); + }); + + it('should return an empty string if passed undefined or null', function() { + expect(getAriaName()).to.be(''); + expect(getAriaName(undefined)).to.be(''); + }); + }); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.ts new file mode 100644 index 00000000000000..d5c2be752a278a --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.ts @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { words } from 'lodash'; + +/** + * @name {string} the name of the configuration object + * @returns {string} a space delimited, lowercase string with + * special characters removed. + * + * Example: 'xPack:fooBar:foo_bar_baz' -> 'x pack foo bar foo bar baz' + */ +export function getAriaName(name?: string) { + return words(name || '') + .map(word => word.toLowerCase()) + .join(' '); +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js deleted file mode 100644 index c64b332e8ebee3..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -const upperFirst = (str = '') => str.replace(/^./, str => str.toUpperCase()); - -const names = { - general: i18n.translate('kbn.management.settings.categoryNames.generalLabel', { - defaultMessage: 'General', - }), - timelion: i18n.translate('kbn.management.settings.categoryNames.timelionLabel', { - defaultMessage: 'Timelion', - }), - notifications: i18n.translate('kbn.management.settings.categoryNames.notificationsLabel', { - defaultMessage: 'Notifications', - }), - visualizations: i18n.translate('kbn.management.settings.categoryNames.visualizationsLabel', { - defaultMessage: 'Visualizations', - }), - discover: i18n.translate('kbn.management.settings.categoryNames.discoverLabel', { - defaultMessage: 'Discover', - }), - dashboard: i18n.translate('kbn.management.settings.categoryNames.dashboardLabel', { - defaultMessage: 'Dashboard', - }), - reporting: i18n.translate('kbn.management.settings.categoryNames.reportingLabel', { - defaultMessage: 'Reporting', - }), - search: i18n.translate('kbn.management.settings.categoryNames.searchLabel', { - defaultMessage: 'Search', - }), - siem: i18n.translate('kbn.management.settings.categoryNames.siemLabel', { - defaultMessage: 'SIEM', - }), -}; - -export function getCategoryName(category) { - return category ? names[category] || upperFirst(category) : ''; -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.test.ts new file mode 100644 index 00000000000000..73e303e20c64d7 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.test.ts @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { getCategoryName } from './get_category_name'; + +describe('Settings', function() { + describe('Advanced', function() { + describe('getCategoryName(category)', function() { + it('should capitalize unknown category', function() { + expect(getCategoryName('elasticsearch')).to.be('Elasticsearch'); + }); + + it('should return empty string for no category', function() { + expect(getCategoryName()).to.be(''); + expect(getCategoryName('')).to.be(''); + }); + }); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.ts new file mode 100644 index 00000000000000..d0361ba698eebf --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.ts @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +const upperFirst = (str = '') => str.replace(/^./, strng => strng.toUpperCase()); + +const names: Record = { + general: i18n.translate('kbn.management.settings.categoryNames.generalLabel', { + defaultMessage: 'General', + }), + timelion: i18n.translate('kbn.management.settings.categoryNames.timelionLabel', { + defaultMessage: 'Timelion', + }), + notifications: i18n.translate('kbn.management.settings.categoryNames.notificationsLabel', { + defaultMessage: 'Notifications', + }), + visualizations: i18n.translate('kbn.management.settings.categoryNames.visualizationsLabel', { + defaultMessage: 'Visualizations', + }), + discover: i18n.translate('kbn.management.settings.categoryNames.discoverLabel', { + defaultMessage: 'Discover', + }), + dashboard: i18n.translate('kbn.management.settings.categoryNames.dashboardLabel', { + defaultMessage: 'Dashboard', + }), + reporting: i18n.translate('kbn.management.settings.categoryNames.reportingLabel', { + defaultMessage: 'Reporting', + }), + search: i18n.translate('kbn.management.settings.categoryNames.searchLabel', { + defaultMessage: 'Search', + }), + siem: i18n.translate('kbn.management.settings.categoryNames.siemLabel', { + defaultMessage: 'SIEM', + }), +}; + +export function getCategoryName(category?: string) { + return category ? names[category] || upperFirst(category) : ''; +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.js deleted file mode 100644 index 35ed1f14332ede..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * @param {object} advanced setting definition object - * @param {?} current value of the setting - * @returns {string} the type to use for determining the display and editor - */ -export function getValType(def, value) { - if (def.type) { - return def.type; - } - - if (Array.isArray(value) || Array.isArray(def.value)) { - return 'array'; - } - - return def.value != null ? typeof def.value : typeof value; -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.test.ts new file mode 100644 index 00000000000000..ec59dcaa1ea290 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.test.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { getValType } from './get_val_type'; + +describe('Settings', function() { + describe('Advanced', function() { + describe('getValType(def, val)', function() { + it('should return the explicitly defined type of a setting', function() { + expect(getValType({ type: 'string' })).to.be('string'); + expect(getValType({ type: 'json' })).to.be('json'); + expect(getValType({ type: 'string', value: 5 })).to.be('string'); + }); + + it('should return array if the value is an Array and there is no defined type', function() { + expect(getValType({ type: 'string' }, [1, 2, 3])).to.be('string'); + expect(getValType({ type: 'json', value: [1, 2, 3] })).to.be('json'); + + expect(getValType({ value: 'someString' }, [1, 2, 3])).to.be('array'); + expect(getValType({ value: [1, 2, 3] }, 'someString')).to.be('array'); + }); + + it('should return the type of the default value if there is no type and it is not an array', function() { + expect(getValType({ value: 'someString' })).to.be('string'); + expect(getValType({ value: 'someString' }, 42)).to.be('string'); + }); + + it('should return the type of the value if the default value is null', function() { + expect(getValType({ value: null }, 'someString')).to.be('string'); + }); + }); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.ts new file mode 100644 index 00000000000000..e0aafb6710b7b4 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.ts @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * @param {object} advanced setting definition object + * @param {?} current value of the setting + * @returns {string} the type to use for determining the display and editor + */ + +import { UiSettingsType } from 'src/core/public'; +import { FieldSetting } from '../types'; + +export function getValType(def: Partial, value?: any): UiSettingsType { + if (def.type) { + return def.type; + } + + if (Array.isArray(value) || Array.isArray(def.value)) { + return 'array'; + } + + const typeofVal = def.value != null ? typeof def.value : typeof value; + + if (typeofVal === 'bigint') { + return 'number'; + } + + if (typeofVal === 'symbol' || typeofVal === 'object' || typeofVal === 'function') { + throw new Error( + `incompatible UiSettingsType: '${def.name}' type ${typeofVal} | ${JSON.stringify(def)}` + ); + } + + return typeofVal; +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/index.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/settings/lib/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/settings/lib/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.js deleted file mode 100644 index 166aed6aeb5130..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export function isDefaultValue(setting) { - return ( - setting.isCustom || - setting.value === undefined || - setting.value === '' || - String(setting.value) === String(setting.defVal) - ); -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.test.ts new file mode 100644 index 00000000000000..30531ca89b0b58 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.test.ts @@ -0,0 +1,87 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { isDefaultValue } from './is_default_value'; +import { UiSettingsType } from '../../../../../../../../core/public'; + +describe('Settings', function() { + describe('Advanced', function() { + describe('getCategoryName(category)', function() { + describe('when given a setting definition object', function() { + const setting = { + isCustom: false, + value: 'value', + defVal: 'defaultValue', + displayName: 'displayName', + name: 'name', + ariaName: 'ariaName', + description: 'description', + requiresPageReload: false, + type: 'string' as UiSettingsType, + isOverridden: false, + readOnly: false, + options: [], + optionLabels: { option: 'label' }, + category: ['category'], + validation: { regex: /regexString/, message: 'validation description' }, + }; + + describe('that is custom', function() { + it('should return true', function() { + expect(isDefaultValue({ ...setting, isCustom: true })).to.be(true); + }); + }); + + describe('without a value', function() { + it('should return true', function() { + expect(isDefaultValue({ ...setting, value: undefined })).to.be(true); + expect(isDefaultValue({ ...setting, value: '' })).to.be(true); + }); + }); + + describe('with a value that is the same as the default value', function() { + it('should return true', function() { + expect(isDefaultValue({ ...setting, value: 'defaultValue' })).to.be(true); + expect(isDefaultValue({ ...setting, value: [], defVal: [] })).to.be(true); + expect( + isDefaultValue({ ...setting, value: '{"foo":"bar"}', defVal: '{"foo":"bar"}' }) + ).to.be(true); + expect(isDefaultValue({ ...setting, value: 123, defVal: 123 })).to.be(true); + expect(isDefaultValue({ ...setting, value: 456, defVal: '456' })).to.be(true); + expect(isDefaultValue({ ...setting, value: false, defVal: false })).to.be(true); + }); + }); + + describe('with a value that is different than the default value', function() { + it('should return false', function() { + expect(isDefaultValue({ ...setting })).to.be(false); + expect(isDefaultValue({ ...setting, value: [1], defVal: [2] })).to.be(false); + expect( + isDefaultValue({ ...setting, value: '{"foo":"bar"}', defVal: '{"foo2":"bar2"}' }) + ).to.be(false); + expect(isDefaultValue({ ...setting, value: 123, defVal: 1234 })).to.be(false); + expect(isDefaultValue({ ...setting, value: 456, defVal: '4567' })).to.be(false); + expect(isDefaultValue({ ...setting, value: true, defVal: false })).to.be(false); + }); + }); + }); + }); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.ts new file mode 100644 index 00000000000000..53c2ef3187f091 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { FieldSetting } from '../types'; + +export function isDefaultValue(setting: FieldSetting) { + return ( + setting.isCustom || + setting.value === undefined || + setting.value === '' || + String(setting.value) === String(setting.defVal) + ); +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js deleted file mode 100644 index 6efb89cfba2b25..00000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { getValType } from './get_val_type'; -import { getAriaName } from './get_aria_name'; -import { DEFAULT_CATEGORY } from './default_category'; - -/** - * @param {object} advanced setting definition object - * @param {object} name of setting - * @param {object} current value of setting - * @returns {object} the editable config object - */ -export function toEditableConfig({ def, name, value, isCustom, isOverridden }) { - if (!def) { - def = {}; - } - const conf = { - name, - displayName: def.name || name, - ariaName: def.name || getAriaName(name), - value, - category: def.category && def.category.length ? def.category : [DEFAULT_CATEGORY], - isCustom, - isOverridden, - readonly: !!def.readonly, - defVal: def.value, - type: getValType(def, value), - description: def.description, - deprecation: def.deprecation, - validation: - def.validation && def.validation.regexString - ? { - regex: new RegExp(def.validation.regexString), - message: def.validation.message, - } - : def.validation, - options: def.options, - optionLabels: def.optionLabels, - requiresPageReload: !!def.requiresPageReload, - }; - - return conf; -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.test.ts new file mode 100644 index 00000000000000..881a2eb003cc81 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.test.ts @@ -0,0 +1,134 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { UiSettingsParams, StringValidationRegex } from 'src/core/public'; +import expect from '@kbn/expect'; +import { toEditableConfig } from './to_editable_config'; + +const defDefault = { + isOverridden: true, +}; + +function invoke({ + def = defDefault, + name = 'woah', + value = 'forreal', +}: { + def?: UiSettingsParams & { isOverridden?: boolean }; + name?: string; + value?: any; +}) { + return toEditableConfig({ def, name, value, isCustom: def === defDefault, isOverridden: true }); +} + +describe('Settings', function() { + describe('Advanced', function() { + describe('toEditableConfig(def, name, value)', function() { + it('sets name', function() { + expect(invoke({ name: 'who' }).name).to.equal('who'); + }); + + it('sets value', function() { + expect(invoke({ value: 'what' }).value).to.equal('what'); + }); + + it('sets type', function() { + expect(invoke({ value: 'what' }).type).to.be('string'); + expect(invoke({ value: 0 }).type).to.be('number'); + expect(invoke({ value: [] }).type).to.be('array'); + }); + + describe('when given a setting definition object', function() { + let def: UiSettingsParams & { isOverridden?: boolean }; + beforeEach(function() { + def = { + value: 'the original', + description: 'the one and only', + options: ['all the options'], + }; + }); + + it('is not marked as custom', function() { + expect(invoke({ def }).isCustom).to.be(false); + }); + + it('sets a default value', function() { + expect(invoke({ def }).defVal).to.equal(def.value); + }); + + it('sets a description', function() { + expect(invoke({ def }).description).to.equal(def.description); + }); + + it('sets options', function() { + expect(invoke({ def }).options).to.equal(def.options); + }); + + describe('that contains a type', function() { + it('sets that type', function() { + def.type = 'string'; + expect(invoke({ def }).type).to.equal(def.type); + }); + }); + + describe('that contains a value of type array', function() { + it('sets type to array', function() { + def.value = []; + expect(invoke({ def }).type).to.equal('array'); + }); + }); + + describe('that contains a validation object', function() { + it('constructs a validation regex with message', function() { + def.validation = { + regexString: '^foo', + message: 'must start with "foo"', + }; + const result = invoke({ def }); + const validationTyped = result.validation as StringValidationRegex; + expect(validationTyped.regex).to.be.a(RegExp); + expect(validationTyped.message).to.equal('must start with "foo"'); + }); + }); + }); + + describe('when not given a setting definition object', function() { + it('is marked as custom', function() { + expect(invoke({}).isCustom).to.be(true); + }); + + it('sets defVal to undefined', function() { + expect(invoke({}).defVal).to.be(undefined); + }); + + it('sets description to undefined', function() { + expect(invoke({}).description).to.be(undefined); + }); + + it('sets options to undefined', function() { + expect(invoke({}).options).to.be(undefined); + }); + + it('sets validation to undefined', function() { + expect(invoke({}).validation).to.be(undefined); + }); + }); + }); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.ts new file mode 100644 index 00000000000000..2c27d72f7f645a --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.ts @@ -0,0 +1,81 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + UiSettingsParams, + UserProvidedValues, + StringValidationRegexString, + SavedObjectAttribute, +} from 'src/core/public'; +import { getValType } from './get_val_type'; +import { getAriaName } from './get_aria_name'; +import { DEFAULT_CATEGORY } from './default_category'; + +/** + * @param {object} advanced setting definition object + * @param {object} name of setting + * @param {object} current value of setting + * @returns {object} the editable config object + */ +export function toEditableConfig({ + def, + name, + value, + isCustom, + isOverridden, +}: { + def: UiSettingsParams & UserProvidedValues; + name: string; + value: SavedObjectAttribute; + isCustom: boolean; + isOverridden: boolean; +}) { + if (!def) { + def = {}; + } + + const validationTyped = def.validation as StringValidationRegexString; + + const conf = { + name, + displayName: def.name || name, + ariaName: def.name || getAriaName(name), + value, + category: def.category && def.category.length ? def.category : [DEFAULT_CATEGORY], + isCustom, + isOverridden, + readonly: !!def.readonly, + defVal: def.value, + type: getValType(def, value), + description: def.description, + deprecation: def.deprecation, + validation: + validationTyped && validationTyped.regexString + ? { + regex: new RegExp(validationTyped.regexString), + message: validationTyped.message, + } + : def.validation, + options: def.options, + optionLabels: def.optionLabels, + requiresPageReload: !!def.requiresPageReload, + }; + + return conf; +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/types.ts b/src/legacy/core_plugins/kibana/public/management/sections/settings/types.ts new file mode 100644 index 00000000000000..fea70110f60711 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/types.ts @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + UiSettingsType, + StringValidation, + ImageValidation, + SavedObjectAttribute, +} from '../../../../../../../core/public'; + +export interface FieldSetting { + displayName: string; + name: string; + value: SavedObjectAttribute; + description?: string; + options?: string[]; + optionLabels?: Record; + requiresPageReload: boolean; + type: UiSettingsType; + category: string[]; + ariaName: string; + isOverridden: boolean; + defVal: SavedObjectAttribute; + isCustom: boolean; + validation?: StringValidation | ImageValidation; + readOnly?: boolean; + deprecation?: { + message: string; + docLinksKey: string; + }; +} + +// until eui searchbar and query are typed +export interface IQuery { + ast: any; // incomplete + text: string; + syntax: any; // incomplete +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/index.ts b/src/legacy/core_plugins/kibana/public/visualize/index.ts index f113c81256f8e4..e7170836cf749b 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/index.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/index.ts @@ -17,50 +17,14 @@ * under the License. */ -import { - IPrivate, - legacyChrome, - npSetup, - npStart, - VisEditorTypesRegistryProvider, -} from './legacy_imports'; -import { VisualizePlugin, LegacyAngularInjectedDependencies } from './plugin'; -import { start as embeddables } from '../../../embeddable_api/public/np_ready/public/legacy'; -import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy'; +import { PluginInitializerContext } from 'kibana/public'; +import { VisualizePlugin } from './plugin'; export * from './np_ready/visualize_constants'; export { showNewVisModal } from './np_ready/wizard'; +export { VisualizeConstants, createVisualizeEditUrl } from './np_ready/visualize_constants'; -/** - * Get dependencies relying on the global angular context. - * They also have to get resolved together with the legacy imports above - */ -async function getAngularDependencies(): Promise { - const injector = await legacyChrome.dangerouslyGetActiveInjector(); - - const Private = injector.get('Private'); - - const editorTypes = Private(VisEditorTypesRegistryProvider); - - return { - legacyChrome, - editorTypes, - }; -} - -(() => { - const instance = new VisualizePlugin(); - instance.setup(npSetup.core, { - ...npSetup.plugins, - __LEGACY: { - getAngularDependencies, - }, - }); - instance.start(npStart.core, { - ...npStart.plugins, - embeddables, - visualizations, - }); -})(); - -export { createSavedVisLoader } from './saved_visualizations/saved_visualizations'; +// Core will be looking for this when loading our plugin in the new platform +export const plugin = (context: PluginInitializerContext) => { + return new VisualizePlugin(); +}; diff --git a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts index ea4cd0669a7cd2..f7fd19e8288e73 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts @@ -33,17 +33,17 @@ import { DataPublicPluginStart, IndexPatternsContract } from '../../../../../plu import { VisualizationsStart } from '../../../visualizations/public'; import { SavedVisualizations } from './np_ready/types'; import { UsageCollectionSetup } from '../../../../../plugins/usage_collection/public'; +import { Chrome } from './legacy_imports'; export interface VisualizeKibanaServices { addBasePath: (url: string) => string; chrome: ChromeStart; core: LegacyCoreStart; data: DataPublicPluginStart; - editorTypes: any; embeddables: IEmbeddableStart; getBasePath: () => string; indexPatterns: IndexPatternsContract; - legacyChrome: any; + legacyChrome: Chrome; localStorage: Storage; navigation: NavigationStart; toastNotifications: ToastsStart; diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy.ts new file mode 100644 index 00000000000000..2d615e3132b01e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PluginInitializerContext } from 'kibana/public'; +import { legacyChrome, npSetup, npStart } from './legacy_imports'; +import { start as embeddables } from '../../../embeddable_api/public/np_ready/public/legacy'; +import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy'; +import { plugin } from './index'; + +(() => { + const instance = plugin({} as PluginInitializerContext); + instance.setup(npSetup.core, { + ...npSetup.plugins, + __LEGACY: { + legacyChrome, + }, + }); + instance.start(npStart.core, { + ...npStart.plugins, + embeddables, + visualizations, + }); +})(); diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts index 7d0a07323378a1..e5165cac5c11eb 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts @@ -27,6 +27,7 @@ import chrome from 'ui/chrome'; export const legacyChrome = chrome; +export { Chrome } from 'ui/chrome'; // @ts-ignore export { AppState, AppStateProvider } from 'ui/state_management/app_state'; @@ -58,8 +59,6 @@ export { PromiseServiceCreator } from 'ui/promises/promises'; export { confirmModalFactory } from 'ui/modals/confirm_modal'; export { configureAppAngularModule, ensureDefaultIndexPattern } from 'ui/legacy_compat'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; -// @ts-ignore -export { VisEditorTypesRegistryProvider } from 'ui/registry/vis_editor_types'; // @ts-ignore export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js index 0e085b8553bf02..2a4fdeb4e4016a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js @@ -21,7 +21,6 @@ import angular from 'angular'; import _ from 'lodash'; import { Subscription } from 'rxjs'; import { i18n } from '@kbn/i18n'; -import '../../saved_visualizations/saved_visualizations'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -58,7 +57,7 @@ export function initEditorDirective(app, deps) { }; }); - initVisEditorDirective(app, deps); + initVisEditorDirective(app); initVisualizationDirective(app, deps); } @@ -501,7 +500,7 @@ function VisualizeAppController( language: localStorage.get('kibana.userQueryLanguage') || uiSettings.get('search:queryLanguage'), }; - queryFilter.removeAll(); + queryFilter.setFilters(queryFilter.getGlobalFilters()); $state.save(); $scope.fetch(); }; @@ -510,7 +509,9 @@ function VisualizeAppController( $state.query = savedQuery.attributes.query; $state.save(); - queryFilter.setFilters(savedQuery.attributes.filters || []); + const savedQueryFilters = savedQuery.attributes.filters || []; + const globalFilters = queryFilter.getGlobalFilters(); + queryFilter.setFilters([...globalFilters, ...savedQueryFilters]); if (savedQuery.attributes.timefilter) { timefilter.setTime({ diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/visualization_editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/visualization_editor.js index f6e67d4559f01d..930dd1d930019a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/visualization_editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/visualization_editor.js @@ -17,7 +17,7 @@ * under the License. */ -export function initVisEditorDirective(app, deps) { +export function initVisEditorDirective(app) { app.directive('visualizationEditor', function($timeout, getAppState) { return { restrict: 'E', @@ -29,12 +29,7 @@ export function initVisEditorDirective(app, deps) { query: '=', }, link: function($scope, element) { - const editorType = $scope.savedObj.vis.type.editor; - const Editor = - typeof editorType === 'function' - ? editorType - : deps.editorTypes.find(editor => editor.key === editorType); - + const Editor = $scope.savedObj.vis.type.editor; const editor = new Editor(element[0], $scope.savedObj); $scope.renderFunction = () => { diff --git a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts index 80e17b1631f3e4..26c6691a3613f1 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts @@ -27,9 +27,6 @@ import { SavedObjectsClientContract, } from 'kibana/public'; -// @ts-ignore -import { uiModules } from 'ui/modules'; - import { Storage } from '../../../../../plugins/kibana_utils/public'; import { DataPublicPluginStart } from '../../../../../plugins/data/public'; import { IEmbeddableStart } from '../../../../../plugins/embeddable/public'; @@ -44,14 +41,7 @@ import { HomePublicPluginSetup, } from '../../../../../plugins/home/public'; import { UsageCollectionSetup } from '../../../../../plugins/usage_collection/public'; -import { createSavedVisLoader } from './saved_visualizations/saved_visualizations'; -// @ts-ignore -import { savedObjectManagementRegistry } from '../management/saved_object_registry'; - -export interface LegacyAngularInjectedDependencies { - legacyChrome: any; - editorTypes: any; -} +import { Chrome } from './legacy_imports'; export interface VisualizePluginStartDependencies { data: DataPublicPluginStart; @@ -63,7 +53,7 @@ export interface VisualizePluginStartDependencies { export interface VisualizePluginSetupDependencies { __LEGACY: { - getAngularDependencies: () => Promise; + legacyChrome: Chrome; }; home: HomePublicPluginSetup; kibana_legacy: KibanaLegacySetup; @@ -82,12 +72,7 @@ export class VisualizePlugin implements Plugin { public async setup( core: CoreSetup, - { - home, - kibana_legacy, - __LEGACY: { getAngularDependencies }, - usageCollection, - }: VisualizePluginSetupDependencies + { home, kibana_legacy, __LEGACY, usageCollection }: VisualizePluginSetupDependencies ) { kibana_legacy.registerLegacyApp({ id: 'visualize', @@ -106,16 +91,8 @@ export class VisualizePlugin implements Plugin { share, } = this.startDependencies; - const angularDependencies = await getAngularDependencies(); - const savedVisualizations = createSavedVisLoader({ - savedObjectsClient, - indexPatterns: data.indexPatterns, - chrome: contextCore.chrome, - overlays: contextCore.overlays, - visualizations, - }); const deps: VisualizeKibanaServices = { - ...angularDependencies, + ...__LEGACY, addBasePath: contextCore.http.basePath.prepend, core: contextCore as LegacyCoreStart, chrome: contextCore.chrome, @@ -126,7 +103,7 @@ export class VisualizePlugin implements Plugin { localStorage: new Storage(localStorage), navigation, savedObjectsClient, - savedVisualizations, + savedVisualizations: visualizations.getSavedVisualizationsLoader(), savedQueryService: data.query.savedQueries, share, toastNotifications: contextCore.notifications.toasts, @@ -168,21 +145,5 @@ export class VisualizePlugin implements Plugin { share, visualizations, }; - - const savedVisualizations = createSavedVisLoader({ - savedObjectsClient: core.savedObjects.client, - indexPatterns: data.indexPatterns, - chrome: core.chrome, - overlays: core.overlays, - visualizations, - }); - - // TODO: remove once savedobjectregistry is refactored - savedObjectManagementRegistry.register({ - service: 'savedVisualizations', - title: 'visualizations', - }); - - uiModules.get('app/visualize').service('savedVisualizations', () => savedVisualizations); } } diff --git a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/index.ts b/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/index.ts deleted file mode 100644 index 62bf106adc0d00..00000000000000 --- a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import './saved_visualizations'; diff --git a/src/legacy/core_plugins/kibana/server/field_formats/register.js b/src/legacy/core_plugins/kibana/server/field_formats/register.js deleted file mode 100644 index 34dc06aab44ac3..00000000000000 --- a/src/legacy/core_plugins/kibana/server/field_formats/register.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { - UrlFormat, - StringFormat, - NumberFormat, - BytesFormat, - TruncateFormat, - RelativeDateFormat, - PercentFormat, - IpFormat, - DurationFormat, - DateNanosFormat, - DateFormat, - ColorFormat, - BoolFormat, - SourceFormat, - StaticLookupFormat, -} from '../../../../../plugins/data/server'; - -export function registerFieldFormats(server) { - server.registerFieldFormat(UrlFormat); - server.registerFieldFormat(BytesFormat); - server.registerFieldFormat(DateFormat); - server.registerFieldFormat(DateNanosFormat); - server.registerFieldFormat(RelativeDateFormat); - server.registerFieldFormat(DurationFormat); - server.registerFieldFormat(IpFormat); - server.registerFieldFormat(NumberFormat); - server.registerFieldFormat(PercentFormat); - server.registerFieldFormat(StringFormat); - server.registerFieldFormat(SourceFormat); - server.registerFieldFormat(ColorFormat); - server.registerFieldFormat(TruncateFormat); - server.registerFieldFormat(BoolFormat); - server.registerFieldFormat(StaticLookupFormat); -} diff --git a/src/legacy/core_plugins/kibana/server/lib/system_api.js b/src/legacy/core_plugins/kibana/server/lib/system_api.js index 24c901a3db0a48..3e2ab667dd98bf 100644 --- a/src/legacy/core_plugins/kibana/server/lib/system_api.js +++ b/src/legacy/core_plugins/kibana/server/lib/system_api.js @@ -24,6 +24,7 @@ const SYSTEM_API_HEADER_NAME = 'kbn-system-api'; * * @param request HAPI request object * @return true if request is a system API request; false, otherwise + * @deprecated Use KibanaRequest#isSystemApi */ export function isSystemApiRequest(request) { return !!request.headers[SYSTEM_API_HEADER_NAME]; diff --git a/src/legacy/core_plugins/kibana/server/routes/api/home/index.js b/src/legacy/core_plugins/kibana/server/routes/api/home/index.js deleted file mode 100644 index 6a4303819f3e9c..00000000000000 --- a/src/legacy/core_plugins/kibana/server/routes/api/home/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { registerTutorials } from './register_tutorials'; - -export function homeApi(server) { - registerTutorials(server); -} diff --git a/src/legacy/core_plugins/kibana/server/routes/api/home/register_tutorials.js b/src/legacy/core_plugins/kibana/server/routes/api/home/register_tutorials.js deleted file mode 100644 index 315553af538921..00000000000000 --- a/src/legacy/core_plugins/kibana/server/routes/api/home/register_tutorials.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export function registerTutorials(server) { - server.route({ - path: '/api/kibana/home/tutorials_LP', - method: ['GET'], - handler: function(req) { - return server.getTutorials(req); - }, - }); -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/activemq_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/activemq_logs/index.js deleted file mode 100644 index fa5fe3b0ecfe3a..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/activemq_logs/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function activemqLogsSpecProvider(server, context) { - const moduleName = 'activemq'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'activemqLogs', - name: i18n.translate('kbn.server.tutorials.activemqLogs.nameTitle', { - defaultMessage: 'ActiveMQ logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.activemqLogs.shortDescription', { - defaultMessage: 'Collect ActiveMQ logs with Filebeat.', - }), - longDescription: i18n.translate('kbn.server.tutorials.activemqLogs.longDescription', { - defaultMessage: 'Collect ActiveMQ logs with Filebeat. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-activemq.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/activemq.svg', - artifacts: { - dashboards: [ - { - id: '26434790-1464-11ea-8fd8-030a13064883', - linkLabel: i18n.translate( - 'kbn.server.tutorials.activemqLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'ActiveMQ Application Events', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-activemq.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/activemq_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/activemq_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/activemq_metrics/index.js deleted file mode 100644 index 7ed2d370debd15..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/activemq_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function activemqMetricsSpecProvider(context) { - const moduleName = 'activemq'; - return { - id: 'activemqMetrics', - name: i18n.translate('kbn.server.tutorials.activemqMetrics.nameTitle', { - defaultMessage: 'ActiveMQ metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.activemqMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from ActiveMQ instances.', - }), - longDescription: i18n.translate('kbn.server.tutorials.activemqMetrics.longDescription', { - defaultMessage: - 'The `activemq` Metricbeat module fetches monitoring metrics from ActiveMQ instances \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-activemq.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/activemq.svg', - isBeta: true, - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.activemqMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-activemq.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/aerospike_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/aerospike_metrics/index.js deleted file mode 100644 index aeb00dfa526fe2..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/aerospike_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function aerospikeMetricsSpecProvider(context) { - const moduleName = 'aerospike'; - return { - id: 'aerospikeMetrics', - name: i18n.translate('kbn.server.tutorials.aerospikeMetrics.nameTitle', { - defaultMessage: 'Aerospike metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.aerospikeMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Aerospike server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.aerospikeMetrics.longDescription', { - defaultMessage: - 'The `aerospike` Metricbeat module fetches internal metrics from Aerospike. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-aerospike.html', - }, - }), - euiIconType: 'logoAerospike', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.aerospikeMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-aerospike.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apache_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/apache_logs/index.js deleted file mode 100644 index d60884e1964983..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/apache_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function apacheLogsSpecProvider(context) { - const moduleName = 'apache'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'apacheLogs', - name: i18n.translate('kbn.server.tutorials.apacheLogs.nameTitle', { - defaultMessage: 'Apache logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.apacheLogs.shortDescription', { - defaultMessage: 'Collect and parse access and error logs created by the Apache HTTP server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.apacheLogs.longDescription', { - defaultMessage: - 'The apache Filebeat module parses access and error logs created by the Apache HTTP server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-apache.html', - }, - }), - euiIconType: 'logoApache', - artifacts: { - dashboards: [ - { - id: 'Filebeat-Apache-Dashboard-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.apacheLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Apache logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-apache.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/apache_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apache_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/apache_metrics/index.js deleted file mode 100644 index 5e20bfd1e9650e..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/apache_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function apacheMetricsSpecProvider(context) { - const moduleName = 'apache'; - return { - id: 'apacheMetrics', - name: i18n.translate('kbn.server.tutorials.apacheMetrics.nameTitle', { - defaultMessage: 'Apache metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.apacheMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Apache 2 HTTP server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.apacheMetrics.longDescription', { - defaultMessage: - 'The `apache` Metricbeat module fetches internal metrics from the Apache 2 HTTP server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-apache.html', - }, - }), - euiIconType: 'logoApache', - artifacts: { - dashboards: [ - { - id: 'Metricbeat-Apache-HTTPD-server-status-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.apacheMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Apache metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-apache.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/apache_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/elastic_cloud.js b/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/elastic_cloud.js deleted file mode 100644 index 64698a54eed3c5..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/elastic_cloud.js +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { get, has } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { INSTRUCTION_VARIANT } from '../../../../common/tutorials/instruction_variant'; - -import { - createNodeAgentInstructions, - createDjangoAgentInstructions, - createFlaskAgentInstructions, - createRailsAgentInstructions, - createRackAgentInstructions, - createJsAgentInstructions, - createGoAgentInstructions, - createJavaAgentInstructions, - createDotNetAgentInstructions, -} from '../instructions/apm_agent_instructions'; - -function getIfExists(obj, key) { - return has(obj, key) && get(obj, key); -} - -export function createElasticCloudInstructions(cloudSetup) { - const apmServerUrl = getIfExists(cloudSetup, 'apm.url'); - const instructionSets = []; - - if (!apmServerUrl) { - instructionSets.push(getApmServerInstructionSet(cloudSetup)); - } - - instructionSets.push(getApmAgentInstructionSet(cloudSetup)); - - return { - instructionSets, - }; -} - -function getApmServerInstructionSet(cloudSetup) { - const cloudId = getIfExists(cloudSetup, 'cloudId'); - return { - title: i18n.translate('kbn.server.tutorials.apm.apmServer.title', { - defaultMessage: 'APM Server', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.ESC, - instructions: [ - { - title: 'Enable the APM Server in the ESS console', - textPre: i18n.translate('kbn.server.tutorials.apm.elasticCloud.textPre', { - defaultMessage: - 'To enable the APM Server go to [the Elastic Cloud console](https://cloud.elastic.co/deployments?q={cloudId}) and enable APM in the deployment settings. Once enabled, refresh this page.', - values: { cloudId }, - }), - }, - ], - }, - ], - }; -} - -function getApmAgentInstructionSet(cloudSetup) { - const apmServerUrl = getIfExists(cloudSetup, 'apm.url'); - const secretToken = getIfExists(cloudSetup, 'apm.secretToken'); - - return { - title: i18n.translate('kbn.server.tutorials.apm.elasticCloudInstructions.title', { - defaultMessage: 'APM Agents', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.NODE, - instructions: createNodeAgentInstructions(apmServerUrl, secretToken), - }, - { - id: INSTRUCTION_VARIANT.DJANGO, - instructions: createDjangoAgentInstructions(apmServerUrl, secretToken), - }, - { - id: INSTRUCTION_VARIANT.FLASK, - instructions: createFlaskAgentInstructions(apmServerUrl, secretToken), - }, - { - id: INSTRUCTION_VARIANT.RAILS, - instructions: createRailsAgentInstructions(apmServerUrl, secretToken), - }, - { - id: INSTRUCTION_VARIANT.RACK, - instructions: createRackAgentInstructions(apmServerUrl, secretToken), - }, - { - id: INSTRUCTION_VARIANT.JS, - instructions: createJsAgentInstructions(apmServerUrl), - }, - { - id: INSTRUCTION_VARIANT.GO, - instructions: createGoAgentInstructions(apmServerUrl, secretToken), - }, - { - id: INSTRUCTION_VARIANT.JAVA, - instructions: createJavaAgentInstructions(apmServerUrl, secretToken), - }, - { - id: INSTRUCTION_VARIANT.DOTNET, - instructions: createDotNetAgentInstructions(apmServerUrl, secretToken), - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/on_prem.js b/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/on_prem.js deleted file mode 100644 index 4cbbbf89bf122c..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/envs/on_prem.js +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { INSTRUCTION_VARIANT } from '../../../../common/tutorials/instruction_variant'; -import { - createWindowsServerInstructions, - createEditConfig, - createStartServerUnixSysv, - createStartServerUnix, - createDownloadServerRpm, - createDownloadServerDeb, - createDownloadServerOsx, -} from '../instructions/apm_server_instructions'; -import { - createNodeAgentInstructions, - createDjangoAgentInstructions, - createFlaskAgentInstructions, - createRailsAgentInstructions, - createRackAgentInstructions, - createJsAgentInstructions, - createGoAgentInstructions, - createJavaAgentInstructions, - createDotNetAgentInstructions, -} from '../instructions/apm_agent_instructions'; - -export function onPremInstructions(config) { - const EDIT_CONFIG = createEditConfig(); - const START_SERVER_UNIX = createStartServerUnix(); - const START_SERVER_UNIX_SYSV = createStartServerUnixSysv(); - - return { - instructionSets: [ - { - title: i18n.translate('kbn.server.tutorials.apm.apmServer.title', { - defaultMessage: 'APM Server', - }), - callOut: { - title: i18n.translate('kbn.server.tutorials.apm.apmServer.callOut.title', { - defaultMessage: 'Important: Updating to 7.0 or higher', - }), - message: i18n.translate('kbn.server.tutorials.apm.apmServer.callOut.message', { - defaultMessage: `Please make sure your APM Server is updated to 7.0 or higher. \ - You can also migrate your 6.x data with the migration assistant found in Kibana's management section.`, - }), - iconType: 'alert', - }, - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [createDownloadServerOsx(), EDIT_CONFIG, START_SERVER_UNIX], - }, - { - id: INSTRUCTION_VARIANT.DEB, - instructions: [createDownloadServerDeb(), EDIT_CONFIG, START_SERVER_UNIX_SYSV], - }, - { - id: INSTRUCTION_VARIANT.RPM, - instructions: [createDownloadServerRpm(), EDIT_CONFIG, START_SERVER_UNIX_SYSV], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: createWindowsServerInstructions(), - }, - ], - statusCheck: { - title: i18n.translate('kbn.server.tutorials.apm.apmServer.statusCheck.title', { - defaultMessage: 'APM Server status', - }), - text: i18n.translate('kbn.server.tutorials.apm.apmServer.statusCheck.text', { - defaultMessage: - 'Make sure APM Server is running before you start implementing the APM agents.', - }), - btnLabel: i18n.translate('kbn.server.tutorials.apm.apmServer.statusCheck.btnLabel', { - defaultMessage: 'Check APM Server status', - }), - success: i18n.translate('kbn.server.tutorials.apm.apmServer.statusCheck.successMessage', { - defaultMessage: 'You have correctly setup APM Server', - }), - error: i18n.translate('kbn.server.tutorials.apm.apmServer.statusCheck.errorMessage', { - defaultMessage: - 'No APM Server detected. Please make sure it is running and you have updated to 7.0 or higher.', - }), - esHitsCheck: { - index: config.get('apm_oss.onboardingIndices'), - query: { - bool: { - filter: [ - { term: { 'processor.event': 'onboarding' } }, - { range: { 'observer.version_major': { gte: 7 } } }, - ], - }, - }, - }, - }, - }, - { - title: i18n.translate('kbn.server.tutorials.apm.apmAgents.title', { - defaultMessage: 'APM Agents', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.JAVA, - instructions: createJavaAgentInstructions(), - }, - { - id: INSTRUCTION_VARIANT.JS, - instructions: createJsAgentInstructions(), - }, - { - id: INSTRUCTION_VARIANT.NODE, - instructions: createNodeAgentInstructions(), - }, - { - id: INSTRUCTION_VARIANT.DJANGO, - instructions: createDjangoAgentInstructions(), - }, - { - id: INSTRUCTION_VARIANT.FLASK, - instructions: createFlaskAgentInstructions(), - }, - { - id: INSTRUCTION_VARIANT.RAILS, - instructions: createRailsAgentInstructions(), - }, - { - id: INSTRUCTION_VARIANT.RACK, - instructions: createRackAgentInstructions(), - }, - { - id: INSTRUCTION_VARIANT.GO, - instructions: createGoAgentInstructions(), - }, - { - id: INSTRUCTION_VARIANT.DOTNET, - instructions: createDotNetAgentInstructions(), - }, - ], - statusCheck: { - title: i18n.translate('kbn.server.tutorials.apm.apmAgents.statusCheck.title', { - defaultMessage: 'Agent status', - }), - text: i18n.translate('kbn.server.tutorials.apm.apmAgents.statusCheck.text', { - defaultMessage: - 'Make sure your application is running and the agents are sending data.', - }), - btnLabel: i18n.translate('kbn.server.tutorials.apm.apmAgents.statusCheck.btnLabel', { - defaultMessage: 'Check agent status', - }), - success: i18n.translate('kbn.server.tutorials.apm.apmAgents.statusCheck.successMessage', { - defaultMessage: 'Data successfully received from one or more agents', - }), - error: i18n.translate('kbn.server.tutorials.apm.apmAgents.statusCheck.errorMessage', { - defaultMessage: 'No data has been received from agents yet', - }), - esHitsCheck: { - index: [ - config.get('apm_oss.errorIndices'), - config.get('apm_oss.transactionIndices'), - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.sourcemapIndices'), - ], - query: { - bool: { - filter: [ - { terms: { 'processor.event': ['error', 'transaction', 'metric', 'sourcemap'] } }, - { range: { 'observer.version_major': { gte: 7 } } }, - ], - }, - }, - }, - }, - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/index.js b/src/legacy/core_plugins/kibana/server/tutorials/apm/index.js deleted file mode 100644 index d86810a8bdf185..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/index.js +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { onPremInstructions } from './envs/on_prem'; -import { createElasticCloudInstructions } from './envs/elastic_cloud'; -import apmIndexPattern from './index_pattern.json'; - -const apmIntro = i18n.translate('kbn.server.tutorials.apm.introduction', { - defaultMessage: 'Collect in-depth performance metrics and errors from inside your applications.', -}); - -function isEnabled(config) { - const ENABLED_KEY = 'xpack.apm.ui.enabled'; - if (config.has(ENABLED_KEY)) { - return config.get(ENABLED_KEY); - } - - return false; -} - -export function apmSpecProvider(server) { - const config = server.config(); - const apmIndexPatternTitle = config.get('apm_oss.indexPattern'); - const { cloud } = server.newPlatform.setup; - - const savedObjects = [ - { - ...apmIndexPattern, - attributes: { - ...apmIndexPattern.attributes, - title: apmIndexPatternTitle, - }, - }, - ]; - - const artifacts = { - dashboards: [ - { - id: '8d3ed660-7828-11e7-8c47-65b845b5cfb3', - linkLabel: i18n.translate( - 'kbn.server.tutorials.apm.specProvider.artifacts.dashboards.linkLabel', - { - defaultMessage: 'APM dashboard', - } - ), - isOverview: true, - }, - ], - }; - - if (isEnabled(config)) { - artifacts.application = { - path: '/app/apm', - label: i18n.translate('kbn.server.tutorials.apm.specProvider.artifacts.application.label', { - defaultMessage: 'Launch APM', - }), - }; - } - - return { - id: 'apm', - name: i18n.translate('kbn.server.tutorials.apm.specProvider.name', { - defaultMessage: 'APM', - }), - category: TUTORIAL_CATEGORY.OTHER, - shortDescription: apmIntro, - longDescription: i18n.translate('kbn.server.tutorials.apm.specProvider.longDescription', { - defaultMessage: - 'Application Performance Monitoring (APM) collects in-depth \ -performance metrics and errors from inside your application. \ -It allows you to monitor the performance of thousands of applications in real time. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: - '{config.docs.base_url}guide/en/apm/get-started/{config.docs.version}/index.html', - }, - }), - euiIconType: 'logoAPM', - artifacts, - onPrem: onPremInstructions(config), - elasticCloud: createElasticCloudInstructions(cloud), - previewImagePath: '/plugins/kibana/home/tutorial_resources/apm/apm.png', - savedObjects, - savedObjectsInstallMsg: i18n.translate( - 'kbn.server.tutorials.apm.specProvider.savedObjectsInstallMsg', - { - defaultMessage: 'An APM index pattern is required for some features in the APM UI.', - } - ), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/instructions/apm_agent_instructions.js b/src/legacy/core_plugins/kibana/server/tutorials/apm/instructions/apm_agent_instructions.js deleted file mode 100644 index b47793a1610fd1..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/instructions/apm_agent_instructions.js +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -export const createNodeAgentInstructions = (apmServerUrl = '', secretToken = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.nodeClient.install.title', { - defaultMessage: 'Install the APM agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.nodeClient.install.textPre', { - defaultMessage: 'Install the APM agent for Node.js as a dependency to your application.', - }), - commands: ['npm install elastic-apm-node --save'], - }, - { - title: i18n.translate('kbn.server.tutorials.apm.nodeClient.configure.title', { - defaultMessage: 'Configure the agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.nodeClient.configure.textPre', { - defaultMessage: - 'Agents are libraries that run inside of your application process. \ -APM services are created programmatically based on the `serviceName`. \ -This agent supports a vararity of frameworks but can also be used with your custom stack.', - }), - commands: `// ${i18n.translate( - 'kbn.server.tutorials.apm.nodeClient.configure.commands.addThisToTheFileTopComment', - { - defaultMessage: 'Add this to the VERY top of the first file loaded in your app', - } - )} -var apm = require('elastic-apm-node').start({curlyOpen} - // ${i18n.translate( - 'kbn.server.tutorials.apm.nodeClient.configure.commands.setRequiredServiceNameComment', - { - defaultMessage: 'Override service name from package.json', - } - )} - // ${i18n.translate( - 'kbn.server.tutorials.apm.nodeClient.configure.commands.allowedCharactersComment', - { - defaultMessage: 'Allowed characters: a-z, A-Z, 0-9, -, _, and space', - } - )} - serviceName: '', - - // ${i18n.translate( - 'kbn.server.tutorials.apm.nodeClient.configure.commands.useIfApmRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a token', - } - )} - secretToken: '${secretToken}', - - // ${i18n.translate( - 'kbn.server.tutorials.apm.nodeClient.configure.commands.setCustomApmServerUrlComment', - { - defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} - serverUrl: '${apmServerUrl}' -{curlyClose})`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.nodeClient.configure.textPost', { - defaultMessage: - 'See [the documentation]({documentationLink}) for advanced usage, including how to use with \ -[Babel/ES Modules]({babelEsModulesLink}).', - values: { - documentationLink: '{config.docs.base_url}guide/en/apm/agent/nodejs/current/index.html', - babelEsModulesLink: - '{config.docs.base_url}guide/en/apm/agent/nodejs/current/advanced-setup.html#es-modules', - }, - }), - }, -]; - -export const createDjangoAgentInstructions = (apmServerUrl = '', secretToken = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.djangoClient.install.title', { - defaultMessage: 'Install the APM agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.djangoClient.install.textPre', { - defaultMessage: 'Install the APM agent for Python as a dependency.', - }), - commands: ['$ pip install elastic-apm'], - }, - { - title: i18n.translate('kbn.server.tutorials.apm.djangoClient.configure.title', { - defaultMessage: 'Configure the agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.djangoClient.configure.textPre', { - defaultMessage: - 'Agents are libraries that run inside of your application process. \ -APM services are created programmatically based on the `SERVICE_NAME`.', - }), - commands: `# ${i18n.translate( - 'kbn.server.tutorials.apm.djangoClient.configure.commands.addAgentComment', - { - defaultMessage: 'Add the agent to the installed apps', - } - )} -INSTALLED_APPS = ( - 'elasticapm.contrib.django', - # ... -) - -ELASTIC_APM = {curlyOpen} - # ${i18n.translate( - 'kbn.server.tutorials.apm.djangoClient.configure.commands.setRequiredServiceNameComment', - { - defaultMessage: 'Set required service name. Allowed characters:', - } - )} - # ${i18n.translate( - 'kbn.server.tutorials.apm.djangoClient.configure.commands.allowedCharactersComment', - { - defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', - } - )} - 'SERVICE_NAME': '', - - # ${i18n.translate( - 'kbn.server.tutorials.apm.djangoClient.configure.commands.useIfApmServerRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a token', - } - )} - 'SECRET_TOKEN': '${secretToken}', - - # ${i18n.translate( - 'kbn.server.tutorials.apm.djangoClient.configure.commands.setCustomApmServerUrlComment', - { - defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} - 'SERVER_URL': '${apmServerUrl}', -{curlyClose} - -# ${i18n.translate( - 'kbn.server.tutorials.apm.djangoClient.configure.commands.addTracingMiddlewareComment', - { - defaultMessage: 'To send performance metrics, add our tracing middleware:', - } - )} -MIDDLEWARE = ( - 'elasticapm.contrib.django.middleware.TracingMiddleware', - #... -)`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.djangoClient.configure.textPost', { - defaultMessage: 'See the [documentation]({documentationLink}) for advanced usage.', - values: { - documentationLink: - '{config.docs.base_url}guide/en/apm/agent/python/current/django-support.html', - }, - }), - }, -]; - -export const createFlaskAgentInstructions = (apmServerUrl = '', secretToken = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.flaskClient.install.title', { - defaultMessage: 'Install the APM agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.flaskClient.install.textPre', { - defaultMessage: 'Install the APM agent for Python as a dependency.', - }), - commands: ['$ pip install elastic-apm[flask]'], - }, - { - title: i18n.translate('kbn.server.tutorials.apm.flaskClient.configure.title', { - defaultMessage: 'Configure the agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.flaskClient.configure.textPre', { - defaultMessage: - 'Agents are libraries that run inside of your application process. \ -APM services are created programmatically based on the `SERVICE_NAME`.', - }), - commands: `# ${i18n.translate( - 'kbn.server.tutorials.apm.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment', - { - defaultMessage: 'initialize using environment variables', - } - )} -from elasticapm.contrib.flask import ElasticAPM -app = Flask(__name__) -apm = ElasticAPM(app) - -# ${i18n.translate( - 'kbn.server.tutorials.apm.flaskClient.configure.commands.configureElasticApmComment', - { - defaultMessage: "or configure to use ELASTIC_APM in your application's settings", - } - )} -from elasticapm.contrib.flask import ElasticAPM -app.config['ELASTIC_APM'] = {curlyOpen} - # ${i18n.translate( - 'kbn.server.tutorials.apm.flaskClient.configure.commands.setRequiredServiceNameComment', - { - defaultMessage: 'Set required service name. Allowed characters:', - } - )} - # ${i18n.translate( - 'kbn.server.tutorials.apm.flaskClient.configure.commands.allowedCharactersComment', - { - defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', - } - )} - 'SERVICE_NAME': '', - - # ${i18n.translate( - 'kbn.server.tutorials.apm.flaskClient.configure.commands.useIfApmServerRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a token', - } - )} - 'SECRET_TOKEN': '${secretToken}', - - # ${i18n.translate( - 'kbn.server.tutorials.apm.flaskClient.configure.commands.setCustomApmServerUrlComment', - { - defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} - 'SERVER_URL': '${apmServerUrl}', -{curlyClose} - -apm = ElasticAPM(app)`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.flaskClient.configure.textPost', { - defaultMessage: 'See the [documentation]({documentationLink}) for advanced usage.', - values: { - documentationLink: - '{config.docs.base_url}guide/en/apm/agent/python/current/flask-support.html', - }, - }), - }, -]; - -export const createRailsAgentInstructions = (apmServerUrl = '', secretToken = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.railsClient.install.title', { - defaultMessage: 'Install the APM agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.railsClient.install.textPre', { - defaultMessage: 'Add the agent to your Gemfile.', - }), - commands: [`gem 'elastic-apm'`], - }, - { - title: i18n.translate('kbn.server.tutorials.apm.railsClient.configure.title', { - defaultMessage: 'Configure the agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.railsClient.configure.textPre', { - defaultMessage: - 'APM is automatically started when your app boots. Configure the agent, by creating the config file {configFile}', - values: { configFile: '`config/elastic_apm.yml`' }, - }), - commands: `# config/elastic_apm.yml: - -# Set service name - allowed characters: a-z, A-Z, 0-9, -, _ and space -# Defaults to the name of your Rails app -# service_name: 'my-service' - -# Use if APM Server requires a token -# secret_token: '${secretToken}' - -# Set custom APM Server URL (default: http://localhost:8200) -# server_url: '${apmServerUrl || 'http://localhost:8200'}'`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.railsClient.configure.textPost', { - defaultMessage: - 'See the [documentation]({documentationLink}) for configuration options and advanced usage.\n\n', - values: { - documentationLink: '{config.docs.base_url}guide/en/apm/agent/ruby/current/index.html', - }, - }), - }, -]; - -export const createRackAgentInstructions = (apmServerUrl = '', secretToken = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.rackClient.install.title', { - defaultMessage: 'Install the APM agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.rackClient.install.textPre', { - defaultMessage: 'Add the agent to your Gemfile.', - }), - commands: [`gem 'elastic-apm'`], - }, - { - title: i18n.translate('kbn.server.tutorials.apm.rackClient.configure.title', { - defaultMessage: 'Configure the agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.rackClient.configure.textPre', { - defaultMessage: - 'For Rack or a compatible framework (e.g. Sinatra), include the middleware in your app and start the agent.', - }), - commands: `# config.ru - require 'sinatra/base' - - class MySinatraApp < Sinatra::Base - use ElasticAPM::Middleware - - # ... - end - - ElasticAPM.start( - app: MySinatraApp, # ${i18n.translate( - 'kbn.server.tutorials.apm.rackClient.configure.commands.requiredComment', - { - defaultMessage: 'required', - } - )} - config_file: '' # ${i18n.translate( - 'kbn.server.tutorials.apm.rackClient.configure.commands.optionalComment', - { - defaultMessage: 'optional, defaults to config/elastic_apm.yml', - } - )} - ) - - run MySinatraApp - - at_exit {curlyOpen} ElasticAPM.stop {curlyClose}`.split('\n'), - }, - { - title: i18n.translate('kbn.server.tutorials.apm.rackClient.createConfig.title', { - defaultMessage: 'Create config file', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.rackClient.createConfig.textPre', { - defaultMessage: 'Create a config file {configFile}:', - values: { configFile: '`config/elastic_apm.yml`' }, - }), - commands: `# config/elastic_apm.yml: - -# ${i18n.translate( - 'kbn.server.tutorials.apm.rackClient.createConfig.commands.setServiceNameComment', - { - defaultMessage: 'Set service name - allowed characters: a-z, A-Z, 0-9, -, _ and space', - } - )} -# ${i18n.translate( - 'kbn.server.tutorials.apm.rackClient.createConfig.commands.defaultsToTheNameOfRackAppClassComment', - { - defaultMessage: "Defaults to the name of your Rack app's class.", - } - )} -# service_name: 'my-service' - -# ${i18n.translate( - 'kbn.server.tutorials.apm.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a token', - } - )} -# secret_token: '${secretToken}' - -# ${i18n.translate( - 'kbn.server.tutorials.apm.rackClient.createConfig.commands.setCustomApmServerComment', - { - defaultMessage: 'Set custom APM Server URL (default: {defaultServerUrl})', - values: { defaultServerUrl: 'http://localhost:8200' }, - } - )} -# server_url: '${apmServerUrl || 'http://localhost:8200'}'`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.rackClient.createConfig.textPost', { - defaultMessage: - 'See the [documentation]({documentationLink}) for configuration options and advanced usage.\n\n', - values: { - documentationLink: '{config.docs.base_url}guide/en/apm/agent/ruby/current/index.html', - }, - }), - }, -]; - -export const createJsAgentInstructions = (apmServerUrl = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.jsClient.enableRealUserMonitoring.title', { - defaultMessage: 'Enable Real User Monitoring support in APM server', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.jsClient.enableRealUserMonitoring.textPre', { - defaultMessage: - 'APM Server disables RUM support by default. See the [documentation]({documentationLink}) \ -for details on how to enable RUM support.', - values: { - documentationLink: - '{config.docs.base_url}guide/en/apm/server/{config.docs.version}/configuration-rum.html', - }, - }), - }, - { - title: i18n.translate('kbn.server.tutorials.apm.jsClient.installDependency.title', { - defaultMessage: 'Set up the Agent as a dependency', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.jsClient.installDependency.textPre', { - defaultMessage: - 'You can install the Agent as a dependency to your application with \ -`npm install @elastic/apm-rum --save`.\n\n\ -The Agent can then be initialized and configured in your application like this:', - }), - commands: `import {curlyOpen} init as initApm {curlyClose} from '@elastic/apm-rum' -var apm = initApm({curlyOpen} - - // ${i18n.translate( - 'kbn.server.tutorials.apm.jsClient.installDependency.commands.setRequiredServiceNameComment', - { - defaultMessage: - 'Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)', - } - )} - serviceName: 'your-app-name', - - // ${i18n.translate( - 'kbn.server.tutorials.apm.jsClient.installDependency.commands.setCustomApmServerUrlComment', - { - defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} - serverUrl: '${apmServerUrl}', - - // ${i18n.translate( - 'kbn.server.tutorials.apm.jsClient.installDependency.commands.setServiceVersionComment', - { - defaultMessage: 'Set service version (required for source map feature)', - } - )} - serviceVersion: '' -{curlyClose})`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.jsClient.installDependency.textPost', { - defaultMessage: - 'Framework integrations, like React or Angular, have custom dependencies. \ -See the [integration documentation]({docLink}) for more information.', - values: { - docLink: - '{config.docs.base_url}guide/en/apm/agent/rum-js/{config.docs.version}/framework-integrations.html', - }, - }), - }, - { - title: i18n.translate('kbn.server.tutorials.apm.jsClient.scriptTags.title', { - defaultMessage: 'Set up the Agent with Script Tags', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.jsClient.scriptTags.textPre', { - defaultMessage: - "Alternatively, you can use Script tags to set up and configure the Agent. \ -Add a ` - -`.split('\n'), - }, -]; - -export const createGoAgentInstructions = (apmServerUrl = '', secretToken = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.goClient.install.title', { - defaultMessage: 'Install the APM agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.goClient.install.textPre', { - defaultMessage: 'Install the APM agent packages for Go.', - }), - commands: ['go get go.elastic.co/apm'], - }, - { - title: i18n.translate('kbn.server.tutorials.apm.goClient.configure.title', { - defaultMessage: 'Configure the agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.goClient.configure.textPre', { - defaultMessage: - 'Agents are libraries that run inside of your application process. \ -APM services are created programmatically based on the executable \ -file name, or the `ELASTIC_APM_SERVICE_NAME` environment variable.', - }), - commands: `# ${i18n.translate( - 'kbn.server.tutorials.apm.goClient.configure.commands.initializeUsingEnvironmentVariablesComment', - { - defaultMessage: 'Initialize using environment variables:', - } - )} - -# ${i18n.translate('kbn.server.tutorials.apm.goClient.configure.commands.setServiceNameComment', { - defaultMessage: 'Set the service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space.', - })} -# ${i18n.translate( - 'kbn.server.tutorials.apm.goClient.configure.commands.usedExecutableNameComment', - { - defaultMessage: - 'If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used.', - } - )} -export ELASTIC_APM_SERVICE_NAME= - -# ${i18n.translate( - 'kbn.server.tutorials.apm.goClient.configure.commands.setCustomApmServerUrlComment', - { - defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} -export ELASTIC_APM_SERVER_URL=${apmServerUrl} - -# ${i18n.translate( - 'kbn.server.tutorials.apm.goClient.configure.commands.useIfApmRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a token', - } - )} -export ELASTIC_APM_SECRET_TOKEN=${secretToken} -`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.goClient.configure.textPost', { - defaultMessage: 'See the [documentation]({documentationLink}) for advanced configuration.', - values: { - documentationLink: '{config.docs.base_url}guide/en/apm/agent/go/current/configuration.html', - }, - }), - }, - { - title: i18n.translate('kbn.server.tutorials.apm.goClient.instrument.title', { - defaultMessage: 'Instrument your application', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.goClient.instrument.textPre', { - defaultMessage: - 'Instrument your Go application by using one of the provided instrumentation modules or \ -by using the tracer API directly.', - }), - commands: `\ -import ( - "net/http" - - "go.elastic.co/apm/module/apmhttp" -) - -func main() {curlyOpen} - mux := http.NewServeMux() - ... - http.ListenAndServe(":8080", apmhttp.Wrap(mux)) -{curlyClose} -`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.goClient.instrument.textPost', { - defaultMessage: - 'See the [documentation]({documentationLink}) for a detailed \ -guide to instrumenting Go source code.', - values: { - documentationLink: - '{config.docs.base_url}guide/en/apm/agent/go/current/instrumenting-source.html', - }, - }), - }, -]; - -export const createJavaAgentInstructions = (apmServerUrl = '', secretToken = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.javaClient.download.title', { - defaultMessage: 'Download the APM agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.javaClient.download.textPre', { - defaultMessage: - 'Download the agent jar from [Maven Central]({mavenCentralLink}). \ -Do **not** add the agent as a dependency to your application.', - values: { - mavenCentralLink: 'http://search.maven.org/#search%7Cga%7C1%7Ca%3Aelastic-apm-agent', - }, - }), - }, - { - title: i18n.translate('kbn.server.tutorials.apm.javaClient.startApplication.title', { - defaultMessage: 'Start your application with the javaagent flag', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.javaClient.startApplication.textPre', { - defaultMessage: - 'Add the `-javaagent` flag and configure the agent with system properties.\n\n \ -* Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)\n \ -* Set custom APM Server URL (default: {customApmServerUrl})\n \ -* Set the base package of your application', - values: { customApmServerUrl: 'http://localhost:8200' }, - }), - commands: `java -javaagent:/path/to/elastic-apm-agent-.jar \\ - -Delastic.apm.service_name=my-application \\ - -Delastic.apm.server_url=${apmServerUrl || 'http://localhost:8200'} \\ - -Delastic.apm.secret_token=${secretToken} \\ - -Delastic.apm.application_packages=org.example \\ - -jar my-application.jar`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.javaClient.startApplication.textPost', { - defaultMessage: - 'See the [documentation]({documentationLink}) for configuration options and advanced \ -usage.', - values: { - documentationLink: '{config.docs.base_url}guide/en/apm/agent/java/current/index.html', - }, - }), - }, -]; - -export const createDotNetAgentInstructions = (apmServerUrl = '', secretToken = '') => [ - { - title: i18n.translate('kbn.server.tutorials.apm.dotNetClient.download.title', { - defaultMessage: 'Download the APM agent', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.dotNetClient.download.textPre', { - defaultMessage: - 'Add the the agent package(s) from [NuGet]({allNuGetPackagesLink}) to your .NET application. There are multiple \ - NuGet packages available for different use cases. \n\nFor an ASP.NET Core application with Entity Framework \ - Core download the [Elastic.Apm.NetCoreAll]({netCoreAllApmPackageLink}) package. This package will automatically add every \ - agent component to your application. \n\n In case you would like to to minimize the dependencies, you can use the \ - [Elastic.Apm.AspNetCore]({aspNetCorePackageLink}) package for just \ - ASP.NET Core monitoring or the [Elastic.Apm.EfCore]({efCorePackageLink}) package for just Entity Framework Core monitoring. \n\n \ - In case you only want to use the public Agent API for manual instrumentation use the [Elastic.Apm]({elasticApmPackageLink}) package.', - values: { - allNuGetPackagesLink: 'https://www.nuget.org/packages?q=Elastic.apm', - netCoreAllApmPackageLink: 'https://www.nuget.org/packages/Elastic.Apm.NetCoreAll', - aspNetCorePackageLink: 'https://www.nuget.org/packages/Elastic.Apm.AspNetCore', - efCorePackageLink: 'https://www.nuget.org/packages/Elastic.Apm.EntityFrameworkCore', - elasticApmPackageLink: 'https://www.nuget.org/packages/Elastic.Apm', - }, - }), - }, - { - title: i18n.translate('kbn.server.tutorials.apm.dotNetClient.configureApplication.title', { - defaultMessage: 'Add the agent to the application', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.dotNetClient.configureApplication.textPre', { - defaultMessage: - 'In case of ASP.NET Core with the `Elastic.Apm.NetCoreAll` package, call the `UseAllElasticApm` \ - method in the `Configure` method within the `Startup.cs` file.', - }), - commands: `public class Startup -{curlyOpen} - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - {curlyOpen} - app.UseAllElasticApm(Configuration); - //…rest of the method - {curlyClose} - //…rest of the class -{curlyClose}`.split('\n'), - textPost: i18n.translate( - 'kbn.server.tutorials.apm.dotNetClient.configureApplication.textPost', - { - defaultMessage: - 'Passing an `IConfiguration` instance is optional and by doing so, the agent will read config settings through this \ - `IConfiguration` instance (e.g. from the `appsettings.json` file).', - } - ), - }, - { - title: i18n.translate('kbn.server.tutorials.apm.dotNetClient.configureAgent.title', { - defaultMessage: 'Sample appsettings.json file:', - }), - commands: `{curlyOpen} - "ElasticApm": {curlyOpen} - "SecretToken": "${secretToken}", - "ServerUrls": "${apmServerUrl || - 'http://localhost:8200'}", //Set custom APM Server URL (default: http://localhost:8200) - "ServiceName" : "MyApp", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application - {curlyClose} -{curlyClose}`.split('\n'), - textPost: i18n.translate('kbn.server.tutorials.apm.dotNetClient.configureAgent.textPost', { - defaultMessage: - 'In case you don’t pass an `IConfiguration` instance to the agent (e.g. in case of non ASP.NET Core applications) \ - you can also configure the agent through environment variables. \n \ - See [the documentation]({documentationLink}) for advanced usage.', - values: { - documentationLink: - '{config.docs.base_url}guide/en/apm/agent/dotnet/current/configuration.html', - }, - }), - }, -]; diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/instructions/apm_server_instructions.js b/src/legacy/core_plugins/kibana/server/tutorials/apm/instructions/apm_server_instructions.js deleted file mode 100644 index 92626025276eed..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/instructions/apm_server_instructions.js +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -export const createEditConfig = () => ({ - title: i18n.translate('kbn.server.tutorials.apm.editConfig.title', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.editConfig.textPre', { - defaultMessage: - "If you're using an X-Pack secured version of Elastic Stack, you must specify \ -credentials in the `apm-server.yml` config file.", - }), - commands: [ - 'output.elasticsearch:', - ' hosts: [""]', - ' username: ', - ' password: ', - ], -}); - -const createStartServer = () => ({ - title: i18n.translate('kbn.server.tutorials.apm.startServer.title', { - defaultMessage: 'Start APM Server', - }), - textPre: i18n.translate('kbn.server.tutorials.apm.startServer.textPre', { - defaultMessage: - 'The server processes and stores application performance metrics in Elasticsearch.', - }), -}); - -export function createStartServerUnixSysv() { - const START_SERVER = createStartServer(); - - return { - title: START_SERVER.title, - textPre: START_SERVER.textPre, - commands: ['service apm-server start'], - }; -} - -export function createStartServerUnix() { - const START_SERVER = createStartServer(); - - return { - title: START_SERVER.title, - textPre: START_SERVER.textPre, - commands: ['./apm-server -e'], - }; -} - -const createDownloadServerTitle = () => - i18n.translate('kbn.server.tutorials.apm.downloadServer.title', { - defaultMessage: 'Download and unpack APM Server', - }); - -export const createDownloadServerOsx = () => ({ - title: createDownloadServerTitle(), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-{config.kibana.version}-darwin-x86_64.tar.gz', - 'tar xzvf apm-server-{config.kibana.version}-darwin-x86_64.tar.gz', - 'cd apm-server-{config.kibana.version}-darwin-x86_64/', - ], -}); - -export const createDownloadServerDeb = () => ({ - title: createDownloadServerTitle(), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-{config.kibana.version}-amd64.deb', - 'sudo dpkg -i apm-server-{config.kibana.version}-amd64.deb', - ], - textPost: i18n.translate('kbn.server.tutorials.apm.downloadServerTitle', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({downloadPageLink}).', - values: { downloadPageLink: '{config.docs.base_url}downloads/apm/apm-server' }, - }), -}); - -export const createDownloadServerRpm = () => ({ - title: createDownloadServerTitle(), - commands: [ - 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-{config.kibana.version}-x86_64.rpm', - 'sudo rpm -vi apm-server-{config.kibana.version}-x86_64.rpm', - ], - textPost: i18n.translate('kbn.server.tutorials.apm.downloadServerRpm', { - defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({downloadPageLink}).', - values: { downloadPageLink: '{config.docs.base_url}downloads/apm/apm-server' }, - }), -}); - -export function createWindowsServerInstructions() { - const START_SERVER = createStartServer(); - - return [ - { - title: createDownloadServerTitle(), - textPre: i18n.translate('kbn.server.tutorials.apm.windowsServerInstructions.textPre', { - defaultMessage: - '1. Download the APM Server Windows zip file from the \ -[Download page]({downloadPageLink}).\n2. Extract the contents of \ -the zip file into {zipFileExtractFolder}.\n3. Rename the {apmServerDirectory} \ -directory to `APM-Server`.\n4. Open a PowerShell prompt as an Administrator \ -(right-click the PowerShell icon and select \ -**Run As Administrator**). If you are running Windows XP, you might need to download and install \ -PowerShell.\n5. From the PowerShell prompt, run the following commands to install APM Server as a Windows service:', - values: { - downloadPageLink: 'https://www.elastic.co/downloads/apm/apm-server', - zipFileExtractFolder: '`C:\\Program Files`', - apmServerDirectory: '`apm-server-{config.kibana.version}-windows`', - }, - }), - commands: [`cd 'C:\\Program Files\\APM-Server'`, `.\\install-service-apm-server.ps1`], - textPost: i18n.translate('kbn.server.tutorials.apm.windowsServerInstructions.textPost', { - defaultMessage: - 'Note: If script execution is disabled on your system, \ -you need to set the execution policy for the current session \ -to allow the script to run. For example: {command}.', - values: { - command: - '`PowerShell.exe -ExecutionPolicy UnRestricted -File .\\install-service-apm-server.ps1`', - }, - }), - }, - createEditConfig(), - { - title: START_SERVER.title, - textPre: START_SERVER.textPre, - commands: ['Start-Service apm-server'], - }, - ]; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/auditbeat/index.js b/src/legacy/core_plugins/kibana/server/tutorials/auditbeat/index.js deleted file mode 100644 index b67a872dcc0aa9..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/auditbeat/index.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/auditbeat_instructions'; - -export function auditbeatSpecProvider(context) { - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'auditbeat', - name: i18n.translate('kbn.server.tutorials.auditbeat.nameTitle', { - defaultMessage: 'Auditbeat', - }), - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.auditbeat.shortDescription', { - defaultMessage: 'Collect audit data from your hosts.', - }), - longDescription: i18n.translate('kbn.server.tutorials.auditbeat.longDescription', { - defaultMessage: - 'Use Auditbeat to collect auditing data from your hosts. These include \ -processes, users, logins, sockets information, file accesses, and more. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.auditbeat}/auditbeat-overview.html', - }, - }), - euiIconType: 'securityAnalyticsApp', - artifacts: { - dashboards: [], - application: { - path: '/app/siem', - label: i18n.translate('kbn.server.tutorials.auditbeat.artifacts.dashboards.linkLabel', { - defaultMessage: 'SIEM App', - }), - }, - exportedFields: { - documentationUrl: '{config.docs.beats.auditbeat}/exported-fields.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/auditbeat/screenshot.png', - onPrem: onPremInstructions(platforms, context), - elasticCloud: cloudInstructions(platforms), - onPremElasticCloud: onPremCloudInstructions(platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/aws_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/aws_logs/index.js deleted file mode 100644 index 5f7131cb4dcdef..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/aws_logs/index.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function awsLogsSpecProvider(server, context) { - const moduleName = 'aws'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'awsLogs', - name: i18n.translate('kbn.server.tutorials.awsLogs.nameTitle', { - defaultMessage: 'AWS S3 based logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.awsLogs.shortDescription', { - defaultMessage: 'Collect AWS logs from S3 bucket with Filebeat.', - }), - longDescription: i18n.translate('kbn.server.tutorials.awsLogs.longDescription', { - defaultMessage: - 'Collect AWS logs by exporting them to an S3 bucket which is configured with SQS notification. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-aws.html', - }, - }), - euiIconType: 'logoAWS', - artifacts: { - dashboards: [ - { - id: '4746e000-bacd-11e9-9f70-1f7bda85a5eb', - linkLabel: i18n.translate('kbn.server.tutorials.awsLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'AWS S3 server access log dashboard', - }), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-aws.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/aws_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/aws_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/aws_metrics/index.js deleted file mode 100644 index e7b6644ecea1c7..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/aws_metrics/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function awsMetricsSpecProvider(context) { - const moduleName = 'aws'; - return { - id: 'awsMetrics', - name: i18n.translate('kbn.server.tutorials.awsMetrics.nameTitle', { - defaultMessage: 'AWS metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.awsMetrics.shortDescription', { - defaultMessage: - 'Fetch monitoring metrics for EC2 instances from the AWS APIs and Cloudwatch.', - }), - longDescription: i18n.translate('kbn.server.tutorials.awsMetrics.longDescription', { - defaultMessage: - 'The `aws` Metricbeat module fetches monitoring metrics from the AWS APIs and Cloudwatch. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-aws.html', - }, - }), - euiIconType: 'logoAWS', - isBeta: false, - artifacts: { - dashboards: [ - { - id: 'c5846400-f7fb-11e8-af03-c999c9dea608-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.awsMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'AWS metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-aws.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/aws_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/azure_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/azure_metrics/index.js deleted file mode 100644 index cbefd713a73814..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/azure_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function azureMetricsSpecProvider(context) { - const moduleName = 'azure'; - return { - id: 'azureMetrics', - name: i18n.translate('kbn.server.tutorials.azureMetrics.nameTitle', { - defaultMessage: 'Azure metrics', - }), - isBeta: true, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.azureMetrics.shortDescription', { - defaultMessage: 'Fetch Azure Monitor metrics.', - }), - longDescription: i18n.translate('kbn.server.tutorials.azureMetrics.longDescription', { - defaultMessage: - 'The `azure` Metricbeat module fetches Azure Monitor metrics. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-azure.html', - }, - }), - euiIconType: 'logoAzure', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.azureMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-azure.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/ceph_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/ceph_metrics/index.js deleted file mode 100644 index d844dd016657cc..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/ceph_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function cephMetricsSpecProvider(context) { - const moduleName = 'ceph'; - return { - id: 'cephMetrics', - name: i18n.translate('kbn.server.tutorials.cephMetrics.nameTitle', { - defaultMessage: 'Ceph metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.cephMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Ceph server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.cephMetrics.longDescription', { - defaultMessage: - 'The `ceph` Metricbeat module fetches internal metrics from Ceph. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-ceph.html', - }, - }), - euiIconType: 'logoCeph', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.cephMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-ceph.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/cisco_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/cisco_logs/index.js deleted file mode 100644 index 90190bd0d68770..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/cisco_logs/index.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function ciscoLogsSpecProvider(context) { - const moduleName = 'cisco'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'ciscoLogs', - name: i18n.translate('kbn.server.tutorials.ciscoLogs.nameTitle', { - defaultMessage: 'Cisco', - }), - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.ciscoLogs.shortDescription', { - defaultMessage: 'Collect and parse logs received from Cisco ASA firewalls.', - }), - longDescription: i18n.translate('kbn.server.tutorials.ciscoLogs.longDescription', { - defaultMessage: - 'This is a module for Cisco network device’s logs. Currently \ -supports the "asa" fileset for Cisco ASA firewall logs received over syslog or read from a file. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cisco.html', - }, - }), - //euiIconType: 'logoCisco', - artifacts: { - dashboards: [], - application: { - path: '/app/siem', - label: i18n.translate('kbn.server.tutorials.ciscoLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'SIEM App', - }), - }, - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-cisco.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/cisco_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/cloudwatch_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/cloudwatch_logs/index.js deleted file mode 100644 index 6abc7161d8bf22..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/cloudwatch_logs/index.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/functionbeat_instructions'; - -export function cloudwatchLogsSpecProvider(context) { - return { - id: 'cloudwatchLogs', - name: i18n.translate('kbn.server.tutorials.cloudwatchLogs.nameTitle', { - defaultMessage: 'AWS Cloudwatch logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.cloudwatchLogs.shortDescription', { - defaultMessage: 'Collect Cloudwatch logs with Functionbeat.', - }), - longDescription: i18n.translate('kbn.server.tutorials.cloudwatchLogs.longDescription', { - defaultMessage: - 'Collect Cloudwatch logs by deploying Functionbeat to run as \ - an AWS Lambda function. \ - [Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.functionbeat}/functionbeat-getting-started.html', - }, - }), - euiIconType: 'logoAWS', - artifacts: { - dashboards: [ - // TODO - ], - exportedFields: { - documentationUrl: '{config.docs.beats.functionbeat}/exported-fields.html', - }, - }, - completionTimeMinutes: 10, - //previewImagePath: '/plugins/kibana/home/tutorial_resources/uptime_monitors/screenshot.png', - onPrem: onPremInstructions(null, null, null, context), - elasticCloud: cloudInstructions(), - onPremElasticCloud: onPremCloudInstructions(), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/cockroachdb_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/cockroachdb_metrics/index.js deleted file mode 100644 index 0eb54700b50c23..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/cockroachdb_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function cockroachdbMetricsSpecProvider(context) { - const moduleName = 'cockroachdb'; - return { - id: 'cockroachdbMetrics', - name: i18n.translate('kbn.server.tutorials.cockroachdbMetrics.nameTitle', { - defaultMessage: 'CockroachDB metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.cockroachdbMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the CockroachDB server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.cockroachdbMetrics.longDescription', { - defaultMessage: - 'The `cockroachdb` Metricbeat module fetches monitoring metrics from CockroachDB. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-cockroachdb.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/cockroachdb.svg', - artifacts: { - dashboards: [ - { - id: 'e3ba0c30-9766-11e9-9eea-6f554992ec1f', - linkLabel: i18n.translate( - 'kbn.server.tutorials.cockroachdbMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'CockroachDB metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-cockroachdb.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/cockroachdb_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/consul_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/consul_metrics/index.js deleted file mode 100644 index 361fd1db39e5a9..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/consul_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function consulMetricsSpecProvider(context) { - const moduleName = 'consul'; - return { - id: 'consulMetrics', - name: i18n.translate('kbn.server.tutorials.consulMetrics.nameTitle', { - defaultMessage: 'Consul metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.consulMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the Consul server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.consulMetrics.longDescription', { - defaultMessage: - 'The `consul` Metricbeat module fetches monitoring metrics from Consul. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-consul.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/consul.svg', - artifacts: { - dashboards: [ - { - id: '496910f0-b952-11e9-a579-f5c0a5d81340', - linkLabel: i18n.translate( - 'kbn.server.tutorials.consulMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Consul metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-consul.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/consul_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/coredns_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/coredns_logs/index.js deleted file mode 100644 index ca308ac969e493..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/coredns_logs/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function corednsLogsSpecProvider(server, context) { - const moduleName = 'coredns'; - const platforms = ['OSX', 'DEB', 'RPM']; - return { - id: 'corednsLogs', - name: i18n.translate('kbn.server.tutorials.corednsLogs.nameTitle', { - defaultMessage: 'CoreDNS logs', - }), - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.corednsLogs.shortDescription', { - defaultMessage: 'Collect the logs created by Coredns.', - }), - longDescription: i18n.translate('kbn.server.tutorials.corednsLogs.longDescription', { - defaultMessage: - 'The `coredns` Filebeat module collects the logs from \ -[CoreDNS](https://coredns.io/manual/toc/). \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-coredns.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/coredns.svg', - artifacts: { - dashboards: [ - { - id: '53aa1f70-443e-11e9-8548-ab7fbe04f038', - linkLabel: i18n.translate( - 'kbn.server.tutorials.corednsLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'CoreDNS logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-coredns.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/coredns_logs/screenshot.jpg', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/coredns_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/coredns_metrics/index.js deleted file mode 100644 index 58bd8f656bafb2..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/coredns_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function corednsMetricsSpecProvider(context) { - const moduleName = 'coredns'; - return { - id: 'corednsMetrics', - name: i18n.translate('kbn.server.tutorials.corednsMetrics.nameTitle', { - defaultMessage: 'CoreDNS metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.corednsMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the CoreDNS server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.corednsMetrics.longDescription', { - defaultMessage: - 'The `coredns` Metricbeat module fetches monitoring metrics from CoreDNS. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-coredns.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/coredns.svg', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.corednsMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-coredns.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/coredns_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/couchbase_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/couchbase_metrics/index.js deleted file mode 100644 index 3348b9edb7b9c5..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/couchbase_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function couchbaseMetricsSpecProvider(context) { - const moduleName = 'couchbase'; - return { - id: 'couchbaseMetrics', - name: i18n.translate('kbn.server.tutorials.couchbaseMetrics.nameTitle', { - defaultMessage: 'Couchbase metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.couchbaseMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Couchbase.', - }), - longDescription: i18n.translate('kbn.server.tutorials.couchbaseMetrics.longDescription', { - defaultMessage: - 'The `couchbase` Metricbeat module fetches internal metrics from Couchbase. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-couchbase.html', - }, - }), - euiIconType: 'logoCouchbase', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.couchbaseMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-couchbase.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/couchdb_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/couchdb_metrics/index.js deleted file mode 100644 index cf7cec60c1f13c..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/couchdb_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function couchdbMetricsSpecProvider(context) { - const moduleName = 'couchdb'; - return { - id: 'couchdbMetrics', - name: i18n.translate('kbn.server.tutorials.couchdbMetrics.nameTitle', { - defaultMessage: 'CouchDB metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.couchdbMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the CouchdB server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.couchdbMetrics.longDescription', { - defaultMessage: - 'The `couchdb` Metricbeat module fetches monitoring metrics from CouchDB. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-couchdb.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/couchdb.svg', - artifacts: { - dashboards: [ - { - id: '496910f0-b952-11e9-a579-f5c0a5d81340', - linkLabel: i18n.translate( - 'kbn.server.tutorials.couchdbMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'CouchDB metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-couchdb.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/couchdb_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/docker_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/docker_metrics/index.js deleted file mode 100644 index 0ed852afec7b70..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/docker_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function dockerMetricsSpecProvider(context) { - const moduleName = 'docker'; - return { - id: 'dockerMetrics', - name: i18n.translate('kbn.server.tutorials.dockerMetrics.nameTitle', { - defaultMessage: 'Docker metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.dockerMetrics.shortDescription', { - defaultMessage: 'Fetch metrics about your Docker containers.', - }), - longDescription: i18n.translate('kbn.server.tutorials.dockerMetrics.longDescription', { - defaultMessage: - 'The `docker` Metricbeat module fetches metrics from the Docker server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-docker.html', - }, - }), - euiIconType: 'logoDocker', - artifacts: { - dashboards: [ - { - id: 'AV4REOpp5NkDleZmzKkE-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.dockerMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Docker metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-docker.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/docker_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/dropwizard_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/dropwizard_metrics/index.js deleted file mode 100644 index c32779fb36368c..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/dropwizard_metrics/index.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function dropwizardMetricsSpecProvider(context) { - const moduleName = 'dropwizard'; - return { - id: 'dropwizardMetrics', - name: i18n.translate('kbn.server.tutorials.dropwizardMetrics.nameTitle', { - defaultMessage: 'Dropwizard metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.dropwizardMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Dropwizard Java application.', - }), - longDescription: i18n.translate('kbn.server.tutorials.dropwizardMetrics.longDescription', { - defaultMessage: - 'The `dropwizard` Metricbeat module fetches internal metrics from Dropwizard Java Application. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-dropwizard.html', - }, - }), - euiIconType: 'logoDropwizard', - artifacts: { - application: { - label: i18n.translate( - 'kbn.server.tutorials.dropwizardMetrics.artifacts.application.label', - { - defaultMessage: 'Discover', - } - ), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-dropwizard.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/elasticsearch_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/elasticsearch_logs/index.js deleted file mode 100644 index 20bdf38a5f7798..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/elasticsearch_logs/index.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function elasticsearchLogsSpecProvider(context) { - const moduleName = 'elasticsearch'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'elasticsearchLogs', - name: i18n.translate('kbn.server.tutorials.elasticsearchLogs.nameTitle', { - defaultMessage: 'Elasticsearch logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - isBeta: true, - shortDescription: i18n.translate('kbn.server.tutorials.elasticsearchLogs.shortDescription', { - defaultMessage: 'Collect and parse logs created by Elasticsearch.', - }), - longDescription: i18n.translate('kbn.server.tutorials.elasticsearchLogs.longDescription', { - defaultMessage: - 'The `elasticsearch` Filebeat module parses logs created by Elasticsearch. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-elasticsearch.html', - }, - }), - euiIconType: 'logoElasticsearch', - artifacts: { - application: { - label: i18n.translate( - 'kbn.server.tutorials.elasticsearchLogs.artifacts.application.label', - { - defaultMessage: 'Discover', - } - ), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-elasticsearch.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/elasticsearch_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/elasticsearch_metrics/index.js deleted file mode 100644 index a4d193ebc1d1f6..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/elasticsearch_metrics/index.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function elasticsearchMetricsSpecProvider(context) { - const moduleName = 'elasticsearch'; - return { - id: 'elasticsearchMetrics', - name: i18n.translate('kbn.server.tutorials.elasticsearchMetrics.nameTitle', { - defaultMessage: 'Elasticsearch metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.elasticsearchMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Elasticsearch.', - }), - longDescription: i18n.translate('kbn.server.tutorials.elasticsearchMetrics.longDescription', { - defaultMessage: - 'The `elasticsearch` Metricbeat module fetches internal metrics from Elasticsearch. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-elasticsearch.html', - }, - }), - euiIconType: 'logoElasticsearch', - artifacts: { - application: { - label: i18n.translate( - 'kbn.server.tutorials.elasticsearchMetrics.artifacts.application.label', - { - defaultMessage: 'Discover', - } - ), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-elasticsearch.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/ems/index.js b/src/legacy/core_plugins/kibana/server/tutorials/ems/index.js deleted file mode 100644 index 24293590299b16..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/ems/index.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; - -export function emsBoundariesSpecProvider(server) { - function addBasePath(url) { - const basePath = server.config().get('server.basePath'); - return `${basePath.length > 0 ? `${basePath}` : ''}${url}`; - } - - return { - id: 'emsBoundaries', - name: i18n.translate('kbn.server.tutorials.ems.nameTitle', { - defaultMessage: 'EMS Boundaries', - }), - category: TUTORIAL_CATEGORY.OTHER, - shortDescription: i18n.translate('kbn.server.tutorials.ems.shortDescription', { - defaultMessage: 'Administrative boundaries from Elastic Maps Service.', - }), - longDescription: i18n.translate('kbn.server.tutorials.ems.longDescription', { - defaultMessage: - '[Elastic Maps Service (EMS)](https://www.elastic.co/elastic-maps-service) \ -hosts tile layers and vector shapes of administrative boundaries. \ -Indexing EMS administrative boundaries in Elasticsearch allows for search on boundary property fields.', - }), - euiIconType: 'emsApp', - completionTimeMinutes: 1, - previewImagePath: '/plugins/kibana/home/tutorial_resources/ems/boundaries_screenshot.png', - onPrem: { - instructionSets: [ - { - instructionVariants: [ - { - id: 'EMS', - instructions: [ - { - title: i18n.translate('kbn.server.tutorials.ems.downloadStepTitle', { - defaultMessage: 'Download Elastic Maps Service boundaries', - }), - textPre: i18n.translate('kbn.server.tutorials.ems.downloadStepText', { - defaultMessage: - '1. Navigate to Elastic Maps Service [landing page]({emsLandingPageUrl}).\n\ -2. In the left sidebar, select an administrative boundary.\n\ -3. Click `Download GeoJSON` button.', - values: { - emsLandingPageUrl: server.config().get('map.emsLandingPageUrl'), - }, - }), - }, - { - title: i18n.translate('kbn.server.tutorials.ems.uploadStepTitle', { - defaultMessage: 'Index Elastic Maps Service boundaries', - }), - textPre: i18n.translate('kbn.server.tutorials.ems.uploadStepText', { - defaultMessage: - '1. Open [Elastic Maps]({newMapUrl}).\n\ -2. Click `Add layer`, then select `Upload GeoJSON`.\n\ -3. Upload the GeoJSON file and click `Import file`.', - values: { - newMapUrl: addBasePath('/app/maps#/map'), - }, - }), - }, - ], - }, - ], - }, - ], - }, - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/envoyproxy_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/envoyproxy_logs/index.js deleted file mode 100644 index 977decd413f083..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/envoyproxy_logs/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function envoyproxyLogsSpecProvider(context) { - const moduleName = 'envoyproxy'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'envoyproxyLogs', - name: i18n.translate('kbn.server.tutorials.envoyproxyLogs.nameTitle', { - defaultMessage: 'Envoyproxy', - }), - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.envoyproxyLogs.shortDescription', { - defaultMessage: 'Collect and parse logs received from the Envoy proxy.', - }), - longDescription: i18n.translate('kbn.server.tutorials.envoyproxyLogs.longDescription', { - defaultMessage: - 'This is a filebeat module for [Envoy proxy access log](https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log). \ -It supports both standalone deployment and Envoy proxy deployment in Kubernetes. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-envoyproxy.html', - }, - }), - //euiIconType: 'logoCisco', - artifacts: { - dashboards: [], - application: { - path: '/app/siem', - label: i18n.translate( - 'kbn.server.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'SIEM App', - } - ), - }, - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-envoyproxy.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/envoyproxy_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/envoyproxy_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/envoyproxy_metrics/index.js deleted file mode 100644 index 4e5301149b35b0..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/envoyproxy_metrics/index.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function envoyproxyMetricsSpecProvider(server, context) { - const moduleName = 'envoyproxy'; - return { - id: 'envoyproxyMetrics', - name: i18n.translate('kbn.server.tutorials.envoyproxyMetrics.nameTitle', { - defaultMessage: 'Envoy Proxy metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.envoyproxyMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from Envoy Proxy.', - }), - longDescription: i18n.translate('kbn.server.tutorials.envoyproxyMetrics.longDescription', { - defaultMessage: - 'The `envoyproxy` Metricbeat module fetches monitoring metrics from Envoy Proxy. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-envoyproxy.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/envoyproxy.svg', - artifacts: { - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-envoyproxy.html', - }, - }, - completionTimeMinutes: 10, - // previewImagePath: '/plugins/kibana/home/tutorial_resources/envoyproxy_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/etcd_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/etcd_metrics/index.js deleted file mode 100644 index fdd0956bb25bb9..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/etcd_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function etcdMetricsSpecProvider(context) { - const moduleName = 'etcd'; - return { - id: 'etcdMetrics', - name: i18n.translate('kbn.server.tutorials.etcdMetrics.nameTitle', { - defaultMessage: 'Etcd metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.etcdMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Etcd server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.etcdMetrics.longDescription', { - defaultMessage: - 'The `etcd` Metricbeat module fetches internal metrics from Etcd. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-etcd.html', - }, - }), - euiIconType: 'logoEtcd', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.etcdMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-etcd.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/golang_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/golang_metrics/index.js deleted file mode 100644 index 7eb6e340c863d4..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/golang_metrics/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function golangMetricsSpecProvider(context) { - const moduleName = 'golang'; - return { - id: moduleName + 'Metrics', - name: i18n.translate('kbn.server.tutorials.golangMetrics.nameTitle', { - defaultMessage: 'Golang metrics', - }), - isBeta: true, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.golangMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from a Golang app.', - }), - longDescription: i18n.translate('kbn.server.tutorials.golangMetrics.longDescription', { - defaultMessage: - 'The `{moduleName}` Metricbeat module fetches internal metrics from a Golang app. \ -[Learn more]({learnMoreLink}).', - values: { - moduleName, - learnMoreLink: `{config.docs.beats.metricbeat}/metricbeat-module-${moduleName}.html`, - }, - }), - euiIconType: 'logoGolang', - artifacts: { - dashboards: [ - { - id: 'f2dc7320-f519-11e6-a3c9-9d1f7c42b045-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.golangMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Golang metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-' + moduleName + '.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/haproxy_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/haproxy_metrics/index.js deleted file mode 100644 index 7e2ca4af7fd9ca..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/haproxy_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function haproxyMetricsSpecProvider(context) { - const moduleName = 'haproxy'; - return { - id: 'haproxyMetrics', - name: i18n.translate('kbn.server.tutorials.haproxyMetrics.nameTitle', { - defaultMessage: 'HAProxy metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.haproxyMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the HAProxy server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.haproxyMetrics.longDescription', { - defaultMessage: - 'The `haproxy` Metricbeat module fetches internal metrics from HAProxy. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-haproxy.html', - }, - }), - euiIconType: 'logoHAproxy', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.haproxyMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-haproxy.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/ibmmq_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/ibmmq_logs/index.js deleted file mode 100644 index 4ffda2d7a523cf..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/ibmmq_logs/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function ibmmqLogsSpecProvider(server, context) { - const moduleName = 'ibmmq'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'ibmmqLogs', - name: i18n.translate('kbn.server.tutorials.ibmmqLogs.nameTitle', { - defaultMessage: 'IBM MQ logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.ibmmqLogs.shortDescription', { - defaultMessage: 'Collect IBM MQ logs with Filebeat.', - }), - longDescription: i18n.translate('kbn.server.tutorials.ibmmqLogs.longDescription', { - defaultMessage: 'Collect IBM MQ logs with Filebeat. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-ibmmq.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/ibmmq.svg', - artifacts: { - dashboards: [ - { - id: 'ba1d8830-7c7b-11e9-9645-e37efaf5baff', - linkLabel: i18n.translate( - 'kbn.server.tutorials.ibmmqLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'IBM MQ Events', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-ibmmq.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/ibmmq_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/ibmmq_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/ibmmq_metrics/index.js deleted file mode 100644 index b2824832dc14c4..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/ibmmq_metrics/index.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function ibmmqMetricsSpecProvider(context) { - const moduleName = 'ibmmq'; - return { - id: 'ibmmqMetrics', - name: i18n.translate('kbn.server.tutorials.ibmmqMetrics.nameTitle', { - defaultMessage: 'IBM MQ metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.ibmmqMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from IBM MQ instances.', - }), - longDescription: i18n.translate('kbn.server.tutorials.ibmmqMetrics.longDescription', { - defaultMessage: - 'The `ibmmq` Metricbeat module fetches monitoring metrics from IBM MQ instances \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-ibmmq.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/ibmmq.svg', - isBeta: true, - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.ibmmqMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-ibmmq.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/ibmmq_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/iis_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/iis_logs/index.js deleted file mode 100644 index d2a5b5f113d296..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/iis_logs/index.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function iisLogsSpecProvider(context) { - const moduleName = 'iis'; - const platforms = ['WINDOWS']; - return { - id: 'iisLogs', - name: i18n.translate('kbn.server.tutorials.iisLogs.nameTitle', { - defaultMessage: 'IIS logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.iisLogs.shortDescription', { - defaultMessage: 'Collect and parse access and error logs created by the IIS HTTP server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.iisLogs.longDescription', { - defaultMessage: - 'The `iis` Filebeat module parses access and error logs created by the IIS HTTP server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iis.html', - }, - }), - // euiIconType: 'logoIIS', - artifacts: { - dashboards: [ - { - id: '4278ad30-fe16-11e7-a3b0-d13028918f9f-ecs', - linkLabel: i18n.translate('kbn.server.tutorials.iisLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'IIS logs dashboard', - }), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-iis.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/iis_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/iptables_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/iptables_logs/index.js deleted file mode 100644 index 63246e44d2d0d9..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/iptables_logs/index.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function iptablesLogsSpecProvider(context) { - const moduleName = 'iptables'; - const platforms = ['DEB', 'RPM']; - return { - id: 'iptablesLogs', - name: i18n.translate('kbn.server.tutorials.iptablesLogs.nameTitle', { - defaultMessage: 'Iptables / Ubiquiti', - }), - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.iptablesLogs.shortDescription', { - defaultMessage: 'Collect and parse iptables and ip6tables logs or from Ubiqiti firewalls.', - }), - longDescription: i18n.translate('kbn.server.tutorials.iptablesLogs.longDescription', { - defaultMessage: - 'This is a module for iptables and ip6tables logs. It parses logs \ -received over the network via syslog or from a file. Also, it understands the \ -prefix added by some Ubiquiti firewalls, which includes the rule set name, rule \ -number and the action performed on the traffic (allow/deny).. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iptables.html', - }, - }), - //euiIconType: 'logoUbiquiti', - artifacts: { - dashboards: [], - application: { - path: '/app/siem', - label: i18n.translate('kbn.server.tutorials.iptablesLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'SIEM App', - }), - }, - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-iptables.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/iptables_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/kafka_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/kafka_logs/index.js deleted file mode 100644 index 0d98aaa8a8ccf5..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/kafka_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function kafkaLogsSpecProvider(context) { - const moduleName = 'kafka'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'kafkaLogs', - name: i18n.translate('kbn.server.tutorials.kafkaLogs.nameTitle', { - defaultMessage: 'Kafka logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.kafkaLogs.shortDescription', { - defaultMessage: 'Collect and parse logs created by Kafka.', - }), - longDescription: i18n.translate('kbn.server.tutorials.kafkaLogs.longDescription', { - defaultMessage: - 'The `kafka` Filebeat module parses logs created by Kafka. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-kafka.html', - }, - }), - euiIconType: 'logoKafka', - artifacts: { - dashboards: [ - { - id: '943caca0-87ee-11e7-ad9c-db80de0bf8d3-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.kafkaLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Kafka logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-kafka.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/kafka_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/kafka_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/kafka_metrics/index.js deleted file mode 100644 index 088ee876661bbd..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/kafka_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function kafkaMetricsSpecProvider(context) { - const moduleName = 'kafka'; - return { - id: 'kafkaMetrics', - name: i18n.translate('kbn.server.tutorials.kafkaMetrics.nameTitle', { - defaultMessage: 'Kafka metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.kafkaMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Kafka server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.kafkaMetrics.longDescription', { - defaultMessage: - 'The `kafka` Metricbeat module fetches internal metrics from Kafka. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kafka.html', - }, - }), - euiIconType: 'logoKafka', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.kafkaMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-kafka.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/kibana_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/kibana_metrics/index.js deleted file mode 100644 index 64e07a87fe402e..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/kibana_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function kibanaMetricsSpecProvider(context) { - const moduleName = 'kibana'; - return { - id: 'kibanaMetrics', - name: i18n.translate('kbn.server.tutorials.kibanaMetrics.nameTitle', { - defaultMessage: 'Kibana metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.kibanaMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Kibana.', - }), - longDescription: i18n.translate('kbn.server.tutorials.kibanaMetrics.longDescription', { - defaultMessage: - 'The `kibana` Metricbeat module fetches internal metrics from Kibana. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kibana.html', - }, - }), - euiIconType: 'logoKibana', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.kibanaMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-kibana.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/kubernetes_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/kubernetes_metrics/index.js deleted file mode 100644 index 4f59816282538a..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/kubernetes_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function kubernetesMetricsSpecProvider(context) { - const moduleName = 'kubernetes'; - return { - id: 'kubernetesMetrics', - name: i18n.translate('kbn.server.tutorials.kubernetesMetrics.nameTitle', { - defaultMessage: 'Kubernetes metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.kubernetesMetrics.shortDescription', { - defaultMessage: 'Fetch metrics from your Kubernetes installation.', - }), - longDescription: i18n.translate('kbn.server.tutorials.kubernetesMetrics.longDescription', { - defaultMessage: - 'The `kubernetes` Metricbeat module fetches metrics from the Kubernetes APIs. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kubernetes.html', - }, - }), - euiIconType: 'logoKubernetes', - artifacts: { - dashboards: [ - { - id: 'AV4RGUqo5NkDleZmzKuZ-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.kubernetesMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Kubernetes metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-kubernetes.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/kubernetes_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/logstash_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/logstash_logs/index.js deleted file mode 100644 index df0da000bc37a1..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/logstash_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function logstashLogsSpecProvider(context) { - const moduleName = 'logstash'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'logstashLogs', - name: i18n.translate('kbn.server.tutorials.logstashLogs.nameTitle', { - defaultMessage: 'Logstash logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.logstashLogs.shortDescription', { - defaultMessage: 'Collect and parse debug and slow logs created by Logstash itself.', - }), - longDescription: i18n.translate('kbn.server.tutorials.logstashLogs.longDescription', { - defaultMessage: - 'The `logstash` Filebeat module parses debug and slow logs created by Logstash itself. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-logstash.html', - }, - }), - euiIconType: 'logoLogstash', - artifacts: { - dashboards: [ - { - id: 'Filebeat-Logstash-Log-Dashboard-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.logstashLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Logstash logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-logstash.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/logstash_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/logstash_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/logstash_metrics/index.js deleted file mode 100644 index 1ccafa4762e653..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/logstash_metrics/index.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function logstashMetricsSpecProvider(context) { - const moduleName = 'logstash'; - return { - id: moduleName + 'Metrics', - name: i18n.translate('kbn.server.tutorials.logstashMetrics.nameTitle', { - defaultMessage: 'Logstash metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.logstashMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from a Logstash server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.logstashMetrics.longDescription', { - defaultMessage: - 'The `{moduleName}` Metricbeat module fetches internal metrics from a Logstash server. \ -[Learn more]({learnMoreLink}).', - values: { - moduleName, - learnMoreLink: `{config.docs.beats.metricbeat}/metricbeat-module-${moduleName}.html`, - }, - }), - euiIconType: 'logoLogstash', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.logstashMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-' + moduleName + '.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/memcached_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/memcached_metrics/index.js deleted file mode 100644 index 8a9f6bfe8b439e..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/memcached_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function memcachedMetricsSpecProvider(context) { - const moduleName = 'memcached'; - return { - id: 'memcachedMetrics', - name: i18n.translate('kbn.server.tutorials.memcachedMetrics.nameTitle', { - defaultMessage: 'Memcached metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.memcachedMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Memcached server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.memcachedMetrics.longDescription', { - defaultMessage: - 'The `memcached` Metricbeat module fetches internal metrics from Memcached. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-memcached.html', - }, - }), - euiIconType: 'logoMemcached', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.memcachedMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-memcached.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/mongodb_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/mongodb_metrics/index.js deleted file mode 100644 index 1e19650af73fd8..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/mongodb_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function mongodbMetricsSpecProvider(context) { - const moduleName = 'mongodb'; - return { - id: 'mongodbMetrics', - name: i18n.translate('kbn.server.tutorials.mongodbMetrics.nameTitle', { - defaultMessage: 'MongoDB metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.mongodbMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from MongoDB.', - }), - longDescription: i18n.translate('kbn.server.tutorials.mongodbMetrics.longDescription', { - defaultMessage: - 'The `mongodb` Metricbeat module fetches internal metrics from the MongoDB server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mongodb.html', - }, - }), - euiIconType: 'logoMongodb', - artifacts: { - dashboards: [ - { - id: 'Metricbeat-MongoDB-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.mongodbMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'MongoDB metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-mongodb.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/mongodb_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/mssql_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/mssql_metrics/index.js deleted file mode 100644 index d12964e122bc60..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/mssql_metrics/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function mssqlMetricsSpecProvider(context) { - const moduleName = 'mssql'; - return { - id: 'mssqlMetrics', - name: i18n.translate('kbn.server.tutorials.mssqlMetrics.nameTitle', { - defaultMessage: 'Microsoft SQL Server Metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.mssqlMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from a Microsoft SQL Server instance', - }), - longDescription: i18n.translate('kbn.server.tutorials.mssqlMetrics.longDescription', { - defaultMessage: - 'The `mssql` Metricbeat module fetches monitoring, log and performance metrics from a Microsoft SQL Server instance. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mssql.html', - }, - }), - // euiIconType: 'logoMSSQL', - isBeta: false, - artifacts: { - dashboards: [ - { - id: 'a2ead240-18bb-11e9-9836-f37dedd3b411-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.mssqlMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Microsoft SQL Server metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-mssql.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/mssql_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/munin_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/munin_metrics/index.js deleted file mode 100644 index 627c2ddd7dc5bc..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/munin_metrics/index.js +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function muninMetricsSpecProvider(context) { - const moduleName = 'munin'; - return { - id: 'muninMetrics', - name: i18n.translate('kbn.server.tutorials.muninMetrics.nameTitle', { - defaultMessage: 'Munin metrics', - }), - isBeta: true, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.muninMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Munin server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.muninMetrics.longDescription', { - defaultMessage: - 'The `munin` Metricbeat module fetches internal metrics from Munin. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-munin.html', - }, - }), - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.muninMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-munin.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/mysql_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/mysql_logs/index.js deleted file mode 100644 index 796c03c9b19e28..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/mysql_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function mysqlLogsSpecProvider(context) { - const moduleName = 'mysql'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'mysqlLogs', - name: i18n.translate('kbn.server.tutorials.mysqlLogs.nameTitle', { - defaultMessage: 'MySQL logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.mysqlLogs.shortDescription', { - defaultMessage: 'Collect and parse error and slow logs created by MySQL.', - }), - longDescription: i18n.translate('kbn.server.tutorials.mysqlLogs.longDescription', { - defaultMessage: - 'The `mysql` Filebeat module parses error and slow logs created by MySQL. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-mysql.html', - }, - }), - euiIconType: 'logoMySQL', - artifacts: { - dashboards: [ - { - id: 'Filebeat-MySQL-Dashboard-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.mysqlLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'MySQL logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-mysql.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/mysql_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/mysql_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/mysql_metrics/index.js deleted file mode 100644 index 55087d03237d80..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/mysql_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function mysqlMetricsSpecProvider(context) { - const moduleName = 'mysql'; - return { - id: 'mysqlMetrics', - name: i18n.translate('kbn.server.tutorials.mysqlMetrics.nameTitle', { - defaultMessage: 'MySQL metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.mysqlMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from MySQL.', - }), - longDescription: i18n.translate('kbn.server.tutorials.mysqlMetrics.longDescription', { - defaultMessage: - 'The `mysql` Metricbeat module fetches internal metrics from the MySQL server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mysql.html', - }, - }), - euiIconType: 'logoMySQL', - artifacts: { - dashboards: [ - { - id: '66881e90-0006-11e7-bf7f-c9acc3d3e306-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.mysqlMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'MySQL metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-mysql.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/mysql_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/nats_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/nats_logs/index.js deleted file mode 100644 index bbf221c91d5e22..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/nats_logs/index.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function natsLogsSpecProvider(context) { - const moduleName = 'nats'; - const geoipRequired = false; - const uaRequired = false; - const platforms = ['DEB', 'RPM']; - return { - id: 'natsLogs', - name: i18n.translate('kbn.server.tutorials.natsLogs.nameTitle', { - defaultMessage: 'NATS logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - isBeta: true, - shortDescription: i18n.translate('kbn.server.tutorials.natsLogs.shortDescription', { - defaultMessage: 'Collect and parse logs created by Nats.', - }), - longDescription: i18n.translate('kbn.server.tutorials.natsLogs.longDescription', { - defaultMessage: - 'The `nats` Filebeat module parses logs created by Nats. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-nats.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/nats.svg', - artifacts: { - dashboards: [ - { - id: 'Filebeat-nats-overview-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.natsLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'NATS logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-nats.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/nats_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, geoipRequired, uaRequired, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/nats_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/nats_metrics/index.js deleted file mode 100644 index 54f01b70e2d155..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/nats_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function natsMetricsSpecProvider(context) { - const moduleName = 'nats'; - return { - id: 'natsMetrics', - name: i18n.translate('kbn.server.tutorials.natsMetrics.nameTitle', { - defaultMessage: 'NATS metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.natsMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the Nats server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.natsMetrics.longDescription', { - defaultMessage: - 'The `nats` Metricbeat module fetches monitoring metrics from Nats. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-nats.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/nats.svg', - artifacts: { - dashboards: [ - { - id: 'Metricbeat-Nats-Dashboard-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.natsMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'NATS metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-nats.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/nats_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/netflow/common_instructions.js b/src/legacy/core_plugins/kibana/server/tutorials/netflow/common_instructions.js deleted file mode 100644 index 194e315d92ed7f..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/netflow/common_instructions.js +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -export function createCommonNetflowInstructions() { - return { - CONFIG: { - ON_PREM: { - OSX: [ - { - title: i18n.translate('kbn.server.tutorials.netflow.common.config.onPrem.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPrem.osxTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config/logstash.yml`', - }, - } - ), - commands: ['modules:', ' - name: netflow', ' var.input.udp.port: '], - textPost: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPrem.osxTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data.', - values: { - udpPort: '``', - }, - } - ), - }, - ], - WINDOWS: [ - { - title: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPrem.windowsTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPrem.windowsTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config\\logstash.yml`', - }, - } - ), - commands: ['modules:', ' - name: netflow', ' var.input.udp.port: '], - textPost: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPrem.windowsTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data.', - values: { - udpPort: '``', - }, - } - ), - }, - ], - }, - ON_PREM_ELASTIC_CLOUD: { - OSX: [ - { - title: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config/logstash.yml`', - }, - } - ), - commands: [ - 'modules:', - ' - name: netflow', - ' var.input.udp.port: ', - ' var.elasticsearch.hosts: [ "" ]', - ' var.elasticsearch.username: elastic', - ' var.elasticsearch.password: ', - ], - textPost: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data, \ - {esUrl} is the URL of Elasticsearch running on Elastic Cloud, and \ - {password} is the password of the {elastic} user.', - values: { - elastic: '`elastic`', - esUrl: '``', - password: '``', - udpPort: '``', - }, - } - ), - }, - ], - WINDOWS: [ - { - title: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config\\logstash.yml`', - }, - } - ), - commands: [ - 'modules:', - ' - name: netflow', - ' var.input.udp.port: ', - ' var.elasticsearch.hosts: [ "" ]', - ' var.elasticsearch.username: elastic', - ' var.elasticsearch.password: ', - ], - textPost: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data, \ - {esUrl} is the URL of Elasticsearch running on Elastic Cloud, and \ - {password} is the password of the {elastic} user.', - values: { - elastic: '`elastic`', - esUrl: '``', - password: '``', - udpPort: '``', - }, - } - ), - }, - ], - }, - ELASTIC_CLOUD: { - OSX: [ - { - title: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.elasticCloud.osxTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.elasticCloud.osxTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config/logstash.yml`', - }, - } - ), - commands: [ - 'cloud.id: "{config.cloud.id}"', - 'cloud.auth: "elastic:"', - ' ', - 'modules:', - ' - name: netflow', - ' var.input.udp.port: ', - ], - textPost: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.elasticCloud.osxTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data and \ - {password} is the password of the {elastic} user.', - values: { - elastic: '`elastic`', - password: '``', - udpPort: '``', - }, - } - ), - }, - ], - WINDOWS: [ - { - title: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config\\logstash.yml`', - }, - } - ), - commands: [ - 'cloud.id: "{config.cloud.id}"', - 'cloud.auth: "elastic:"', - ' ', - 'modules:', - ' - name: netflow', - ' var.input.udp.port: ', - ], - textPost: i18n.translate( - 'kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data and \ - {password} is the password of the {elastic} user.', - values: { - elastic: '`elastic`', - password: '``', - udpPort: '``', - }, - } - ), - }, - ], - }, - }, - SETUP: { - OSX: [ - { - title: i18n.translate('kbn.server.tutorials.netflow.common.setup.osxTitle', { - defaultMessage: 'Run the Netflow module', - }), - textPre: i18n.translate('kbn.server.tutorials.netflow.common.setup.osxTextPre', { - defaultMessage: 'Run:', - }), - commands: ['./bin/logstash --modules netflow --setup'], - textPost: i18n.translate('kbn.server.tutorials.netflow.common.setup.osxTextPost', { - defaultMessage: - 'The {setupOption} option creates a {netflowPrefix} index pattern in Elasticsearch and imports \ - Kibana dashboards and visualizations. Omit this option for subsequent runs to avoid overwriting existing dashboards.', - values: { - setupOption: '`--setup`', - netflowPrefix: '`netflow-*`', - }, - }), - }, - ], - WINDOWS: [ - { - title: i18n.translate('kbn.server.tutorials.netflow.common.setup.windowsTitle', { - defaultMessage: 'Run the Netflow module', - }), - textPre: i18n.translate('kbn.server.tutorials.netflow.common.setup.windowsTextPre', { - defaultMessage: 'Run:', - }), - commands: ['bin\\logstash --modules netflow --setup'], - textPost: i18n.translate('kbn.server.tutorials.netflow.common.setup.windowsTextPost', { - defaultMessage: - 'The {setupOption} option creates a {netflowPrefix} index pattern in Elasticsearch and imports \ - Kibana dashboards and visualizations. Omit this option for subsequent runs to avoid overwriting existing dashboards.', - values: { - setupOption: '`--setup`', - netflowPrefix: '`netflow-*`', - }, - }), - }, - ], - }, - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/netflow/elastic_cloud.js b/src/legacy/core_plugins/kibana/server/tutorials/netflow/elastic_cloud.js deleted file mode 100644 index 6ba76c2b5fa9c2..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/netflow/elastic_cloud.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; -import { createLogstashInstructions } from '../../../common/tutorials/logstash_instructions'; -import { createCommonNetflowInstructions } from './common_instructions'; - -// TODO: compare with onPremElasticCloud and onPrem scenarios and extract out common bits -export function createElasticCloudInstructions() { - const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); - const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate('kbn.server.tutorials.netflow.elasticCloudInstructions.title', { - defaultMessage: 'Getting Started', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ELASTIC_CLOUD.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ELASTIC_CLOUD.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, - ], - }, - ], - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/netflow/index.js b/src/legacy/core_plugins/kibana/server/tutorials/netflow/index.js deleted file mode 100644 index 10a57fc291d59b..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/netflow/index.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { createOnPremInstructions } from './on_prem'; -import { createElasticCloudInstructions } from './elastic_cloud'; -import { createOnPremElasticCloudInstructions } from './on_prem_elastic_cloud'; - -export function netflowSpecProvider() { - return { - id: 'netflow', - name: 'Netflow', - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.netflow.tutorialShortDescription', { - defaultMessage: 'Collect Netflow records sent by a Netflow exporter.', - }), - longDescription: i18n.translate('kbn.server.tutorials.netflow.tutorialLongDescription', { - defaultMessage: - 'The Logstash Netflow module collects and parses network flow data, \ -indexes the events into Elasticsearch, and installs a suite of Kibana dashboards. \ -This module support Netflow Version 5 and 9. [Learn more]({linkUrl}).', - values: { - linkUrl: '{config.docs.logstash}/netflow-module.html', - }, - }), - completionTimeMinutes: 10, - //previewImagePath: 'kibana-apache.png', TODO - onPrem: createOnPremInstructions(), - elasticCloud: createElasticCloudInstructions(), - onPremElasticCloud: createOnPremElasticCloudInstructions(), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/netflow/on_prem.js b/src/legacy/core_plugins/kibana/server/tutorials/netflow/on_prem.js deleted file mode 100644 index cc060611361bdc..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/netflow/on_prem.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; -import { createLogstashInstructions } from '../../../common/tutorials/logstash_instructions'; -import { createCommonNetflowInstructions } from './common_instructions'; - -// TODO: compare with onPremElasticCloud and elasticCloud scenarios and extract out common bits -export function createOnPremInstructions() { - const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); - const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate('kbn.server.tutorials.netflow.onPremInstructions.title', { - defaultMessage: 'Getting Started', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, - ], - }, - ], - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/netflow/on_prem_elastic_cloud.js b/src/legacy/core_plugins/kibana/server/tutorials/netflow/on_prem_elastic_cloud.js deleted file mode 100644 index 49674621b70be8..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/netflow/on_prem_elastic_cloud.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; -import { createLogstashInstructions } from '../../../common/tutorials/logstash_instructions'; -import { - createTrycloudOption1, - createTrycloudOption2, -} from '../../../common/tutorials/onprem_cloud_instructions'; -import { createCommonNetflowInstructions } from './common_instructions'; - -// TODO: compare with onPrem and elasticCloud scenarios and extract out common bits -export function createOnPremElasticCloudInstructions() { - const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); - const TRYCLOUD_OPTION1 = createTrycloudOption1(); - const TRYCLOUD_OPTION2 = createTrycloudOption2(); - const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate('kbn.server.tutorials.netflow.onPremElasticCloudInstructions.title', { - defaultMessage: 'Getting Started', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM_ELASTIC_CLOUD.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM_ELASTIC_CLOUD.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, - ], - }, - ], - }, - ], - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/nginx_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/nginx_logs/index.js deleted file mode 100644 index ef4dae582790ea..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/nginx_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function nginxLogsSpecProvider(context) { - const moduleName = 'nginx'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'nginxLogs', - name: i18n.translate('kbn.server.tutorials.nginxLogs.nameTitle', { - defaultMessage: 'Nginx logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.nginxLogs.shortDescription', { - defaultMessage: 'Collect and parse access and error logs created by the Nginx HTTP server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.nginxLogs.longDescription', { - defaultMessage: - 'The `nginx` Filebeat module parses access and error logs created by the Nginx HTTP server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-nginx.html', - }, - }), - euiIconType: 'logoNginx', - artifacts: { - dashboards: [ - { - id: '55a9e6e0-a29e-11e7-928f-5dbe6f6f5519-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.nginxLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Nginx logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-nginx.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/nginx_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/nginx_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/nginx_metrics/index.js deleted file mode 100644 index 2acb72b01eca90..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/nginx_metrics/index.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function nginxMetricsSpecProvider(context) { - const moduleName = 'nginx'; - return { - id: 'nginxMetrics', - name: i18n.translate('kbn.server.tutorials.nginxMetrics.nameTitle', { - defaultMessage: 'Nginx metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.nginxMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Nginx HTTP server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.nginxMetrics.longDescription', { - defaultMessage: - 'The `nginx` Metricbeat module fetches internal metrics from the 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. \ -[Learn more]({learnMoreLink}).', - values: { - statusModuleLink: - '[ngx_http_stub_status_module](http://nginx.org/en/docs/http/ngx_http_stub_status_module.html)', - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-nginx.html', - }, - }), - euiIconType: 'logoNginx', - artifacts: { - dashboards: [ - { - id: '023d2930-f1a5-11e7-a9ef-93c69af7b129-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.nginxMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Nginx metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-nginx.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/nginx_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/osquery_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/osquery_logs/index.js deleted file mode 100644 index eddb81a9762e35..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/osquery_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function osqueryLogsSpecProvider(context) { - const moduleName = 'osquery'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'osqueryLogs', - name: i18n.translate('kbn.server.tutorials.osqueryLogs.nameTitle', { - defaultMessage: 'Osquery logs', - }), - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.osqueryLogs.shortDescription', { - defaultMessage: 'Collect the result logs created by osqueryd.', - }), - longDescription: i18n.translate('kbn.server.tutorials.osqueryLogs.longDescription', { - defaultMessage: - 'The `osquery` Filebeat module collects the JSON result logs collected by `osqueryd`. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-osquery.html', - }, - }), - euiIconType: 'logoOsquery', - artifacts: { - dashboards: [ - { - id: '69f5ae20-eb02-11e7-8f04-51231daa5b05-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.osqueryLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Osquery logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-osquery.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/osquery_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/php_fpm_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/php_fpm_metrics/index.js deleted file mode 100644 index c62cdfa0917ef3..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/php_fpm_metrics/index.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function phpfpmMetricsSpecProvider(context) { - const moduleName = 'php_fpm'; - return { - id: 'phpfpmMetrics', - name: i18n.translate('kbn.server.tutorials.phpFpmMetrics.nameTitle', { - defaultMessage: 'PHP-FPM metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - isBeta: false, - shortDescription: i18n.translate('kbn.server.tutorials.phpFpmMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from PHP-FPM.', - }), - longDescription: i18n.translate('kbn.server.tutorials.phpFpmMetrics.longDescription', { - defaultMessage: - 'The `php_fpm` Metricbeat module fetches internal metrics from the PHP-FPM server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-php_fpm.html', - }, - }), - euiIconType: 'logoPhp', - artifacts: { - dashboards: [ - /*{ - id: 'TODO', - linkLabel: 'PHP-FPM metrics dashboard', - isOverview: true - }*/ - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-php_fpm.html', - }, - }, - completionTimeMinutes: 10, - //previewImagePath: '/plugins/kibana/home/tutorial_resources/php_fpm_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/postgresql_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/postgresql_logs/index.js deleted file mode 100644 index 810af1cb025e4a..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/postgresql_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function postgresqlLogsSpecProvider(context) { - const moduleName = 'postgresql'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'postgresqlLogs', - name: i18n.translate('kbn.server.tutorials.postgresqlLogs.nameTitle', { - defaultMessage: 'PostgreSQL logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.postgresqlLogs.shortDescription', { - defaultMessage: 'Collect and parse error and slow logs created by PostgreSQL.', - }), - longDescription: i18n.translate('kbn.server.tutorials.postgresqlLogs.longDescription', { - defaultMessage: - 'The `postgresql` Filebeat module parses error and slow logs created by PostgreSQL. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-postgresql.html', - }, - }), - euiIconType: 'logoPostgres', - artifacts: { - dashboards: [ - { - id: '158be870-87f4-11e7-ad9c-db80de0bf8d3-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.postgresqlLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'PostgreSQL logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-postgresql.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/postgresql_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/postgresql_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/postgresql_metrics/index.js deleted file mode 100644 index 62203d7f13d332..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/postgresql_metrics/index.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function postgresqlMetricsSpecProvider(context) { - const moduleName = 'postgresql'; - return { - id: 'postgresqlMetrics', - name: i18n.translate('kbn.server.tutorials.postgresqlMetrics.nameTitle', { - defaultMessage: 'PostgreSQL metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - isBeta: false, - shortDescription: i18n.translate('kbn.server.tutorials.postgresqlMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from PostgreSQL.', - }), - longDescription: i18n.translate('kbn.server.tutorials.postgresqlMetrics.longDescription', { - defaultMessage: - 'The `postgresql` Metricbeat module fetches internal metrics from the PostgreSQL server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-postgresql.html', - }, - }), - euiIconType: 'logoPostgres', - artifacts: { - dashboards: [ - /* - { - id: 'TODO', - linkLabel: 'PostgreSQL metrics dashboard', - isOverview: true - } - */ - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-postgresql.html', - }, - }, - completionTimeMinutes: 10, - //previewImagePath: '/plugins/kibana/home/tutorial_resources/postgresql_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/prometheus_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/prometheus_metrics/index.js deleted file mode 100644 index 20a66418042d6f..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/prometheus_metrics/index.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function prometheusMetricsSpecProvider(context) { - const moduleName = 'prometheus'; - return { - id: moduleName + 'Metrics', - name: i18n.translate('kbn.server.tutorials.prometheusMetrics.nameTitle', { - defaultMessage: 'Prometheus metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.prometheusMetrics.shortDescription', { - defaultMessage: 'Fetch metrics from a Prometheus exporter.', - }), - longDescription: i18n.translate('kbn.server.tutorials.prometheusMetrics.longDescription', { - defaultMessage: - 'The `{moduleName}` Metricbeat module fetches metrics from Prometheus endpoint. \ -[Learn more]({learnMoreLink}).', - values: { - moduleName, - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-' + moduleName + '.html', - }, - }), - euiIconType: 'logoPrometheus', - artifacts: { - application: { - label: i18n.translate( - 'kbn.server.tutorials.prometheusMetrics.artifacts.application.label', - { - defaultMessage: 'Discover', - } - ), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-' + moduleName + '.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/rabbitmq_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/rabbitmq_metrics/index.js deleted file mode 100644 index 34c2c28541d3f9..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/rabbitmq_metrics/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function rabbitmqMetricsSpecProvider(context) { - const moduleName = 'rabbitmq'; - return { - id: 'rabbitmqMetrics', - name: i18n.translate('kbn.server.tutorials.rabbitmqMetrics.nameTitle', { - defaultMessage: 'RabbitMQ metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.rabbitmqMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the RabbitMQ server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.rabbitmqMetrics.longDescription', { - defaultMessage: - 'The `rabbitmq` Metricbeat module fetches internal metrics from the RabbitMQ server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-rabbitmq.html', - }, - }), - euiIconType: 'logoRabbitmq', - isBeta: false, - artifacts: { - dashboards: [ - { - id: 'AV4YobKIge1VCbKU_qVo-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.rabbitmqMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'RabbitMQ metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-rabbitmq.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/rabbitmq_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/redis_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/redis_logs/index.js deleted file mode 100644 index 4d4b5dabad3da8..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/redis_logs/index.js +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function redisLogsSpecProvider(context) { - const moduleName = 'redis'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'redisLogs', - name: i18n.translate('kbn.server.tutorials.redisLogs.nameTitle', { - defaultMessage: 'Redis logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.redisLogs.shortDescription', { - defaultMessage: 'Collect and parse error and slow logs created by Redis.', - }), - longDescription: i18n.translate('kbn.server.tutorials.redisLogs.longDescription', { - defaultMessage: - 'The `redis` Filebeat module parses error and slow logs created by Redis. \ -For Redis to write error logs, make sure the `logfile` option, from the \ -Redis configuration file, is set to `redis-server.log`. \ -The slow logs are read directly from Redis via the `SLOWLOG` command. \ -For Redis to record slow logs, make sure the `slowlog-log-slower-than` \ -option is set. \ -Note that the `slowlog` fileset is experimental. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-redis.html', - }, - }), - euiIconType: 'logoRedis', - artifacts: { - dashboards: [ - { - id: '7fea2930-478e-11e7-b1f0-cb29bac6bf8b-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.redisLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Redis logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-redis.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/redis_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/redis_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/redis_metrics/index.js deleted file mode 100644 index 708c16e041acbc..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/redis_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function redisMetricsSpecProvider(context) { - const moduleName = 'redis'; - return { - id: 'redisMetrics', - name: i18n.translate('kbn.server.tutorials.redisMetrics.nameTitle', { - defaultMessage: 'Redis metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.redisMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Redis.', - }), - longDescription: i18n.translate('kbn.server.tutorials.redisMetrics.longDescription', { - defaultMessage: - 'The `redis` Metricbeat module fetches internal metrics from the Redis server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-redis.html', - }, - }), - euiIconType: 'logoRedis', - artifacts: { - dashboards: [ - { - id: 'AV4YjZ5pux-M-tCAunxK-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.redisMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Redis metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-redis.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/redis_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/register.js b/src/legacy/core_plugins/kibana/server/tutorials/register.js deleted file mode 100644 index 2f69e7dbcbc7da..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/register.js +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { systemLogsSpecProvider } from './system_logs'; -import { systemMetricsSpecProvider } from './system_metrics'; -import { apacheLogsSpecProvider } from './apache_logs'; -import { apacheMetricsSpecProvider } from './apache_metrics'; -import { elasticsearchLogsSpecProvider } from './elasticsearch_logs'; -import { iisLogsSpecProvider } from './iis_logs'; -import { kafkaLogsSpecProvider } from './kafka_logs'; -import { logstashLogsSpecProvider } from './logstash_logs'; -import { nginxLogsSpecProvider } from './nginx_logs'; -import { nginxMetricsSpecProvider } from './nginx_metrics'; -import { mysqlLogsSpecProvider } from './mysql_logs'; -import { mysqlMetricsSpecProvider } from './mysql_metrics'; -import { mongodbMetricsSpecProvider } from './mongodb_metrics'; -import { osqueryLogsSpecProvider } from './osquery_logs'; -import { phpfpmMetricsSpecProvider } from './php_fpm_metrics'; -import { postgresqlMetricsSpecProvider } from './postgresql_metrics'; -import { postgresqlLogsSpecProvider } from './postgresql_logs'; -import { rabbitmqMetricsSpecProvider } from './rabbitmq_metrics'; -import { redisLogsSpecProvider } from './redis_logs'; -import { redisMetricsSpecProvider } from './redis_metrics'; -import { suricataLogsSpecProvider } from './suricata_logs'; -import { dockerMetricsSpecProvider } from './docker_metrics'; -import { kubernetesMetricsSpecProvider } from './kubernetes_metrics'; -import { uwsgiMetricsSpecProvider } from './uwsgi_metrics'; -import { netflowSpecProvider } from './netflow'; -import { traefikLogsSpecProvider } from './traefik_logs'; -import { apmSpecProvider } from './apm'; -import { cephMetricsSpecProvider } from './ceph_metrics'; -import { aerospikeMetricsSpecProvider } from './aerospike_metrics'; -import { couchbaseMetricsSpecProvider } from './couchbase_metrics'; -import { dropwizardMetricsSpecProvider } from './dropwizard_metrics'; -import { elasticsearchMetricsSpecProvider } from './elasticsearch_metrics'; -import { etcdMetricsSpecProvider } from './etcd_metrics'; -import { haproxyMetricsSpecProvider } from './haproxy_metrics'; -import { kafkaMetricsSpecProvider } from './kafka_metrics'; -import { kibanaMetricsSpecProvider } from './kibana_metrics'; -import { memcachedMetricsSpecProvider } from './memcached_metrics'; -import { muninMetricsSpecProvider } from './munin_metrics'; -import { vSphereMetricsSpecProvider } from './vsphere_metrics'; -import { windowsMetricsSpecProvider } from './windows_metrics'; -import { windowsEventLogsSpecProvider } from './windows_event_logs'; -import { golangMetricsSpecProvider } from './golang_metrics'; -import { logstashMetricsSpecProvider } from './logstash_metrics'; -import { prometheusMetricsSpecProvider } from './prometheus_metrics'; -import { zookeeperMetricsSpecProvider } from './zookeeper_metrics'; -import { uptimeMonitorsSpecProvider } from './uptime_monitors'; -import { cloudwatchLogsSpecProvider } from './cloudwatch_logs'; -import { awsMetricsSpecProvider } from './aws_metrics'; -import { mssqlMetricsSpecProvider } from './mssql_metrics'; -import { natsMetricsSpecProvider } from './nats_metrics'; -import { natsLogsSpecProvider } from './nats_logs'; -import { zeekLogsSpecProvider } from './zeek_logs'; -import { corednsMetricsSpecProvider } from './coredns_metrics'; -import { corednsLogsSpecProvider } from './coredns_logs'; -import { auditbeatSpecProvider } from './auditbeat'; -import { iptablesLogsSpecProvider } from './iptables_logs'; -import { ciscoLogsSpecProvider } from './cisco_logs'; -import { envoyproxyLogsSpecProvider } from './envoyproxy_logs'; -import { couchdbMetricsSpecProvider } from './couchdb_metrics'; -import { emsBoundariesSpecProvider } from './ems'; -import { consulMetricsSpecProvider } from './consul_metrics'; -import { cockroachdbMetricsSpecProvider } from './cockroachdb_metrics'; -import { traefikMetricsSpecProvider } from './traefik_metrics'; -import { awsLogsSpecProvider } from './aws_logs'; -import { activemqLogsSpecProvider } from './activemq_logs'; -import { activemqMetricsSpecProvider } from './activemq_metrics'; -import { azureMetricsSpecProvider } from './azure_metrics'; -import { ibmmqLogsSpecProvider } from './ibmmq_logs'; -import { ibmmqMetricsSpecProvider } from './ibmmq_metrics'; -import { stanMetricsSpecProvider } from './stan_metrics'; -import { envoyproxyMetricsSpecProvider } from './envoyproxy_metrics'; - -export function registerTutorials(server) { - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(systemLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(systemMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(apacheLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(apacheMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(elasticsearchLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(iisLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(kafkaLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(logstashLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(nginxLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(nginxMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(mysqlLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(mysqlMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(mongodbMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(osqueryLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(phpfpmMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(postgresqlMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(postgresqlLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(rabbitmqMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(redisLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(redisMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(suricataLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(dockerMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(kubernetesMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(uwsgiMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(netflowSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(traefikLogsSpecProvider); - server.registerTutorial(apmSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(cephMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(aerospikeMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(couchbaseMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(dropwizardMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial( - elasticsearchMetricsSpecProvider - ); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(etcdMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(haproxyMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(kafkaMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(kibanaMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(memcachedMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(muninMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(vSphereMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(windowsMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(windowsEventLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(golangMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(logstashMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(prometheusMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(zookeeperMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(uptimeMonitorsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(cloudwatchLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(awsMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(mssqlMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(natsMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(natsLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(zeekLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(corednsMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(corednsLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(auditbeatSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(iptablesLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(ciscoLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(envoyproxyLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(couchdbMetricsSpecProvider); - server.registerTutorial(emsBoundariesSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(consulMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(cockroachdbMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(traefikMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(awsLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(activemqLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(activemqMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(azureMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(ibmmqLogsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(ibmmqMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(stanMetricsSpecProvider); - server.newPlatform.setup.plugins.home.tutorials.registerTutorial(envoyproxyMetricsSpecProvider); -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/stan_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/stan_metrics/index.js deleted file mode 100644 index 3f5817ce2890b3..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/stan_metrics/index.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function stanMetricsSpecProvider(context) { - const moduleName = 'stan'; - return { - id: 'stanMetrics', - name: i18n.translate('kbn.server.tutorials.stanMetrics.nameTitle', { - defaultMessage: 'STAN metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.stanMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the STAN server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.stanMetrics.longDescription', { - defaultMessage: - 'The `stan` Metricbeat module fetches monitoring metrics from STAN. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-stan.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/stan.svg', - artifacts: { - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-stan.html', - }, - }, - completionTimeMinutes: 10, - // previewImagePath: '/plugins/kibana/home/tutorial_resources/stan_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/suricata_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/suricata_logs/index.js deleted file mode 100644 index 3f2ecfa78d3b23..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/suricata_logs/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function suricataLogsSpecProvider(context) { - const moduleName = 'suricata'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'suricataLogs', - name: i18n.translate('kbn.server.tutorials.suricataLogs.nameTitle', { - defaultMessage: 'Suricata logs', - }), - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.suricataLogs.shortDescription', { - defaultMessage: 'Collect the result logs created by Suricata IDS/IPS/NSM.', - }), - longDescription: i18n.translate('kbn.server.tutorials.suricataLogs.longDescription', { - defaultMessage: - 'The `suricata` Filebeat module collects the logs from the \ -[Suricata Eve JSON output](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html). \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-suricata.html', - }, - }), - //euiIconType: 'logoSuricata', - artifacts: { - dashboards: [ - { - id: '69f5ae20-eb02-11e7-8f04-51231daa5b05', - linkLabel: i18n.translate( - 'kbn.server.tutorials.suricataLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Suricata logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-suricata.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/suricata_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/system_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/system_logs/index.js deleted file mode 100644 index ec9792c3c4356a..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/system_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function systemLogsSpecProvider(context) { - const moduleName = 'system'; - const platforms = ['OSX', 'DEB', 'RPM']; - return { - id: 'systemLogs', - name: i18n.translate('kbn.server.tutorials.systemLogs.nameTitle', { - defaultMessage: 'System logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.systemLogs.shortDescription', { - defaultMessage: 'Collect and parse logs written by the local Syslog server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.systemLogs.longDescription', { - defaultMessage: - 'The `system` Filebeat module collects and parses logs created by the system logging service of common \ -Unix/Linux based distributions. This module is not available on Windows. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-system.html', - }, - }), - artifacts: { - dashboards: [ - { - id: 'Filebeat-syslog-dashboard-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.systemLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'System logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-system.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/system_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/system_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/system_metrics/index.js deleted file mode 100644 index 1bebc78146f83e..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/system_metrics/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function systemMetricsSpecProvider(context) { - const moduleName = 'system'; - return { - id: 'systemMetrics', - name: i18n.translate('kbn.server.tutorials.systemMetrics.nameTitle', { - defaultMessage: 'System metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.systemMetrics.shortDescription', { - defaultMessage: 'Collect CPU, memory, network, and disk statistics from the host.', - }), - longDescription: i18n.translate('kbn.server.tutorials.systemMetrics.longDescription', { - defaultMessage: - 'The `system` Metricbeat module collects CPU, memory, network, and disk statistics from the host. \ -It collects system wide statistics and statistics per process and filesystem. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-system.html', - }, - }), - artifacts: { - dashboards: [ - { - id: 'Metricbeat-system-overview-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.systemMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'System metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-system.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/system_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/traefik_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/traefik_logs/index.js deleted file mode 100644 index 65f697a59ee82f..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/traefik_logs/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function traefikLogsSpecProvider(context) { - const moduleName = 'traefik'; - const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS']; - return { - id: 'traefikLogs', - name: i18n.translate('kbn.server.tutorials.traefikLogs.nameTitle', { - defaultMessage: 'Traefik logs', - }), - category: TUTORIAL_CATEGORY.LOGGING, - shortDescription: i18n.translate('kbn.server.tutorials.traefikLogs.shortDescription', { - defaultMessage: 'Collect and parse access logs created by the Traefik Proxy.', - }), - longDescription: i18n.translate('kbn.server.tutorials.traefikLogs.longDescription', { - defaultMessage: - 'The `traefik` Filebeat module parses access logs created by Traefik. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-traefik.html', - }, - }), - //euiIconType: 'logoTraefik', - artifacts: { - dashboards: [ - { - id: 'Filebeat-Traefik-Dashboard-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.traefikLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Traefik logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-traefik.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/traefik_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/traefik_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/traefik_metrics/index.js deleted file mode 100644 index 1a4c043ebc706c..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/traefik_metrics/index.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function traefikMetricsSpecProvider(server, context) { - const moduleName = 'traefik'; - return { - id: 'traefikMetrics', - name: i18n.translate('kbn.server.tutorials.traefikMetrics.nameTitle', { - defaultMessage: 'Traefik metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.traefikMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from Traefik.', - }), - longDescription: i18n.translate('kbn.server.tutorials.traefikMetrics.longDescription', { - defaultMessage: - 'The `traefik` Metricbeat module fetches monitoring metrics from Traefik. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-traefik.html', - }, - }), - euiIconType: '/plugins/kibana/home/tutorial_resources/logos/traefik.svg', - artifacts: { - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-traefik.html', - }, - }, - completionTimeMinutes: 10, - // previewImagePath: '/plugins/kibana/home/tutorial_resources/traefik_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/uptime_monitors/index.js b/src/legacy/core_plugins/kibana/server/tutorials/uptime_monitors/index.js deleted file mode 100644 index 7cc90c740eb698..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/uptime_monitors/index.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/heartbeat_instructions'; - -export function uptimeMonitorsSpecProvider(context) { - return { - id: 'uptimeMonitors', - name: i18n.translate('kbn.server.tutorials.uptimeMonitors.nameTitle', { - defaultMessage: 'Uptime Monitors', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.uptimeMonitors.shortDescription', { - defaultMessage: 'Monitor services for their availability', - }), - longDescription: i18n.translate('kbn.server.tutorials.uptimeMonitors.longDescription', { - defaultMessage: - 'Monitor services for their availability with active probing. \ - Given a list of URLs, Heartbeat asks the simple question: Are you alive? \ - [Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html', - }, - }), - euiIconType: 'uptimeApp', - artifacts: { - dashboards: [], - application: { - path: '/app/uptime', - label: i18n.translate( - 'kbn.server.tutorials.uptimeMonitors.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Uptime App', - } - ), - }, - exportedFields: { - documentationUrl: '{config.docs.beats.heartbeat}/exported-fields.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/uptime_monitors/screenshot.png', - onPrem: onPremInstructions(null, null, null, context), - elasticCloud: cloudInstructions(), - onPremElasticCloud: onPremCloudInstructions(), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/uwsgi_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/uwsgi_metrics/index.js deleted file mode 100644 index 8ec422f5b81d1b..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/uwsgi_metrics/index.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function uwsgiMetricsSpecProvider(context) { - const moduleName = 'uwsgi'; - return { - id: 'uwsgiMetrics', - name: i18n.translate('kbn.server.tutorials.uwsgiMetrics.nameTitle', { - defaultMessage: 'uWSGI metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.uwsgiMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the uWSGI server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.uwsgiMetrics.longDescription', { - defaultMessage: - 'The `uwsgi` Metricbeat module fetches internal metrics from the uWSGI server. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-uwsgi.html', - }, - }), - //euiIconType: 'logouWSGI', - isBeta: false, - artifacts: { - dashboards: [ - { - id: '32fca290-f0af-11e7-b9ff-9f96241065de-ecs', - linkLabel: i18n.translate( - 'kbn.server.tutorials.uwsgiMetrics.artifacts.dashboards.linkLabel', - { - defaultMessage: 'uWSGI metrics dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-uwsgi.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/uwsgi_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/vsphere_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/vsphere_metrics/index.js deleted file mode 100644 index dc3a13bde0c766..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/vsphere_metrics/index.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function vSphereMetricsSpecProvider(context) { - const moduleName = 'vsphere'; - return { - id: 'vsphereMetrics', - name: i18n.translate('kbn.server.tutorials.vsphereMetrics.nameTitle', { - defaultMessage: 'vSphere metrics', - }), - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.vsphereMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from vSphere.', - }), - longDescription: i18n.translate('kbn.server.tutorials.vsphereMetrics.longDescription', { - defaultMessage: - 'The `vsphere` Metricbeat module fetches internal metrics from a vSphere cluster. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-vsphere.html', - }, - }), - //euiIconType: 'logoVSphere', - isBeta: true, - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.vsphereMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-vsphere.html', - }, - }, - completionTimeMinutes: 10, - //previewImagePath: '/plugins/kibana/home/tutorial_resources/vsphere_metrics/screenshot.png', - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/windows_event_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/windows_event_logs/index.js deleted file mode 100644 index 272535ad3e4e1a..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/windows_event_logs/index.js +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/winlogbeat_instructions'; - -export function windowsEventLogsSpecProvider(context) { - return { - id: 'windowsEventLogs', - name: i18n.translate('kbn.server.tutorials.windowsEventLogs.nameTitle', { - defaultMessage: 'Windows Event Log', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.windowsEventLogs.shortDescription', { - defaultMessage: 'Fetch logs from the Windows Event Log.', - }), - longDescription: i18n.translate('kbn.server.tutorials.windowsEventLogs.longDescription', { - defaultMessage: - 'Use Winlogbeat to collect the logs from the Windows Event Log. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.winlogbeat}/index.html', - }, - }), - euiIconType: 'logoWindows', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.windowsEventLogs.artifacts.application.label', { - defaultMessage: 'SIEM App', - }), - path: '/app/siem', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.winlogbeat}/exported-fields.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(null, null, null, context), - elasticCloud: cloudInstructions(), - onPremElasticCloud: onPremCloudInstructions(), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/windows_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/windows_metrics/index.js deleted file mode 100644 index 9f30c330f4ae1d..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/windows_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function windowsMetricsSpecProvider(context) { - const moduleName = 'windows'; - return { - id: 'windowsMetrics', - name: i18n.translate('kbn.server.tutorials.windowsMetrics.nameTitle', { - defaultMessage: 'Windows metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.windowsMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Windows.', - }), - longDescription: i18n.translate('kbn.server.tutorials.windowsMetrics.longDescription', { - defaultMessage: - 'The `windows` Metricbeat module fetches internal metrics from Windows. \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-windows.html', - }, - }), - euiIconType: 'logoWindows', - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.windowsMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-windows.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/zeek_logs/index.js b/src/legacy/core_plugins/kibana/server/tutorials/zeek_logs/index.js deleted file mode 100644 index 07d46c9c6ae846..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/zeek_logs/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/filebeat_instructions'; - -export function zeekLogsSpecProvider(context) { - const moduleName = 'zeek'; - const platforms = ['OSX', 'DEB', 'RPM']; - return { - id: 'zeekLogs', - name: i18n.translate('kbn.server.tutorials.zeekLogs.nameTitle', { - defaultMessage: 'Zeek logs', - }), - category: TUTORIAL_CATEGORY.SIEM, - shortDescription: i18n.translate('kbn.server.tutorials.zeekLogs.shortDescription', { - defaultMessage: 'Collect the logs created by Zeek/Bro.', - }), - longDescription: i18n.translate('kbn.server.tutorials.zeekLogs.longDescription', { - defaultMessage: - 'The `zeek` Filebeat module collects the logs from \ -[Zeek](https://www.zeek.org//documentation/index.html). \ -[Learn more]({learnMoreLink}).', - values: { - learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-zeek.html', - }, - }), - //TODO: euiIconType: 'logoZeek', - artifacts: { - dashboards: [ - { - id: '7cbb5410-3700-11e9-aa6d-ff445a78330c', - linkLabel: i18n.translate( - 'kbn.server.tutorials.zeekLogs.artifacts.dashboards.linkLabel', - { - defaultMessage: 'Zeek logs dashboard', - } - ), - isOverview: true, - }, - ], - exportedFields: { - documentationUrl: '{config.docs.beats.filebeat}/exported-fields-zeek.html', - }, - }, - completionTimeMinutes: 10, - previewImagePath: '/plugins/kibana/home/tutorial_resources/zeek_logs/screenshot.png', - onPrem: onPremInstructions(moduleName, platforms, context), - elasticCloud: cloudInstructions(moduleName, platforms), - onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), - }; -} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/zookeeper_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/zookeeper_metrics/index.js deleted file mode 100644 index 64b45759b3bcac..00000000000000 --- a/src/legacy/core_plugins/kibana/server/tutorials/zookeeper_metrics/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { - onPremInstructions, - cloudInstructions, - onPremCloudInstructions, -} from '../../../common/tutorials/metricbeat_instructions'; - -export function zookeeperMetricsSpecProvider(context) { - const moduleName = 'zookeeper'; - return { - id: moduleName + 'Metrics', - name: i18n.translate('kbn.server.tutorials.zookeeperMetrics.nameTitle', { - defaultMessage: 'Zookeeper metrics', - }), - isBeta: false, - category: TUTORIAL_CATEGORY.METRICS, - shortDescription: i18n.translate('kbn.server.tutorials.zookeeperMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from a Zookeeper server.', - }), - longDescription: i18n.translate('kbn.server.tutorials.zookeeperMetrics.longDescription', { - defaultMessage: - 'The `{moduleName}` Metricbeat module fetches internal metrics from a Zookeeper server. \ -[Learn more]({learnMoreLink}).', - values: { - moduleName, - learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-' + moduleName + '.html', - }, - }), - artifacts: { - application: { - label: i18n.translate('kbn.server.tutorials.zookeeperMetrics.artifacts.application.label', { - defaultMessage: 'Discover', - }), - path: '/app/kibana#/discover', - }, - dashboards: [], - exportedFields: { - documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-' + moduleName + '.html', - }, - }, - completionTimeMinutes: 10, - onPrem: onPremInstructions(moduleName, null, null, null, context), - elasticCloud: cloudInstructions(moduleName), - onPremElasticCloud: onPremCloudInstructions(moduleName), - }; -} diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/ui_setting_defaults.js index dc8fee4a849c50..02a4f10a543c4a 100644 --- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/ui_setting_defaults.js @@ -257,6 +257,7 @@ export function getUiSettingDefaults() { defaultMessage: 'Default index', }), value: null, + type: 'string', description: i18n.translate('kbn.advancedSettings.defaultIndexText', { defaultMessage: 'The index to access if no index is set', }), @@ -1170,5 +1171,24 @@ export function getUiSettingDefaults() { category: ['accessibility'], requiresPageReload: true, }, + pageNavigation: { + name: i18n.translate('kbn.advancedSettings.pageNavigationName', { + defaultMessage: 'Side nav style', + }), + value: 'grouped', + description: i18n.translate('kbn.advancedSettings.pageNavigationDesc', { + defaultMessage: 'Change the style of navigation', + }), + type: 'select', + options: ['grouped', 'individual'], + optionLabels: { + grouped: i18n.translate('kbn.advancedSettings.pageNavigationGrouped', { + defaultMessage: 'Grouped', + }), + individual: i18n.translate('kbn.advancedSettings.pageNavigationIndividual', { + defaultMessage: 'Individual', + }), + }, + }, }; } diff --git a/src/legacy/core_plugins/management/index.ts b/src/legacy/core_plugins/management/index.ts index 65601b53718151..4962c948f842f2 100644 --- a/src/legacy/core_plugins/management/index.ts +++ b/src/legacy/core_plugins/management/index.ts @@ -23,7 +23,7 @@ import { Legacy } from '../../../../kibana'; // eslint-disable-next-line import/no-default-export export default function ManagementPlugin(kibana: any) { const config: Legacy.PluginSpecOptions = { - id: 'management', + id: 'stack-management', publicDir: resolve(__dirname, 'public'), config: (Joi: any) => { return Joi.object({ diff --git a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx index 73fe07ec60102d..287fb87e735a25 100644 --- a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx +++ b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx @@ -24,11 +24,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { FileLayerField, VectorLayer, ServiceSettings } from 'ui/vis/map/service_settings'; import { VisOptionsProps } from 'ui/vis/editors/default'; -import { - NumberInputOption, - SelectOption, - SwitchOption, -} from '../../../vis_type_vislib/public/components'; +import { NumberInputOption, SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; import { WmsOptions } from '../../../tile_map/public/components/wms_options'; import { RegionMapVisParams } from '../types'; diff --git a/src/legacy/core_plugins/state_session_storage_redirect/index.js b/src/legacy/core_plugins/state_session_storage_redirect/index.js deleted file mode 100644 index 2d4d7c97232c04..00000000000000 --- a/src/legacy/core_plugins/state_session_storage_redirect/index.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default function(kibana) { - return new kibana.Plugin({ - uiExports: { - app: { - require: ['kibana'], - title: 'Redirecting', - id: 'stateSessionStorageRedirect', - main: 'plugins/state_session_storage_redirect', - hidden: true, - }, - }, - }); -} diff --git a/src/legacy/core_plugins/state_session_storage_redirect/package.json b/src/legacy/core_plugins/state_session_storage_redirect/package.json deleted file mode 100644 index 21956e5d76d5b1..00000000000000 --- a/src/legacy/core_plugins/state_session_storage_redirect/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "state_session_storage_redirect", - "version": "kibana", - "description": "When using the state:storeInSessionStorage setting with the short-urls, we need some way to get the full URL's hashed states into sessionStorage, this app will grab the URL from the injected state and and put the URL hashed states into sessionStorage before redirecting the user." -} diff --git a/src/legacy/core_plugins/state_session_storage_redirect/public/index.js b/src/legacy/core_plugins/state_session_storage_redirect/public/index.js deleted file mode 100644 index 701a5736c7d3b8..00000000000000 --- a/src/legacy/core_plugins/state_session_storage_redirect/public/index.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import chrome from 'ui/chrome'; -import { hashUrl } from '../../../../plugins/kibana_utils/public'; -import uiRoutes from 'ui/routes'; -import { fatalError } from 'ui/notify'; - -uiRoutes.enable(); -uiRoutes.when('/', { - resolve: { - url: function(AppState, globalState, $window) { - const redirectUrl = chrome.getInjected('redirectUrl'); - try { - const hashedUrl = hashUrl(redirectUrl); - const url = chrome.addBasePath(hashedUrl); - - $window.location = url; - } catch (e) { - fatalError(e); - } - }, - }, -}); diff --git a/src/legacy/core_plugins/telemetry/common/constants.ts b/src/legacy/core_plugins/telemetry/common/constants.ts index cb4ff79969a322..cf2c9c883871bf 100644 --- a/src/legacy/core_plugins/telemetry/common/constants.ts +++ b/src/legacy/core_plugins/telemetry/common/constants.ts @@ -80,4 +80,4 @@ export const PATH_TO_ADVANCED_SETTINGS = 'kibana#/management/kibana/settings'; * The type name used within the Monitoring index to publish management stats. * @type {string} */ -export const KIBANA_MANAGEMENT_STATS_TYPE = 'management'; +export const KIBANA_STACK_MANAGEMENT_STATS_TYPE = 'stack_management'; diff --git a/src/legacy/core_plugins/telemetry/server/collectors/management/telemetry_management_collector.ts b/src/legacy/core_plugins/telemetry/server/collectors/management/telemetry_management_collector.ts index f45cf7fc6bb33f..481b1e9af2a79b 100644 --- a/src/legacy/core_plugins/telemetry/server/collectors/management/telemetry_management_collector.ts +++ b/src/legacy/core_plugins/telemetry/server/collectors/management/telemetry_management_collector.ts @@ -19,7 +19,7 @@ import { Server } from 'hapi'; import { size } from 'lodash'; -import { KIBANA_MANAGEMENT_STATS_TYPE } from '../../../common/constants'; +import { KIBANA_STACK_MANAGEMENT_STATS_TYPE } from '../../../common/constants'; import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/server'; import { SavedObjectsClient } from '../../../../../../core/server'; @@ -32,7 +32,7 @@ export async function getTranslationCount(loader: any, locale: string): Promise< export function createCollectorFetch(server: Server) { return async function fetchUsageStats(): Promise { - const internalRepo = server.newPlatform.setup.core.savedObjects.createInternalRepository(); + const internalRepo = server.newPlatform.start.core.savedObjects.createInternalRepository(); const uiSettingsClient = server.newPlatform.start.core.uiSettings.asScopedToClient( new SavedObjectsClient(internalRepo) ); @@ -54,7 +54,7 @@ export function registerManagementUsageCollector( server: any ) { const collector = usageCollection.makeUsageCollector({ - type: KIBANA_MANAGEMENT_STATS_TYPE, + type: KIBANA_STACK_MANAGEMENT_STATS_TYPE, isReady: () => true, fetch: createCollectorFetch(server), }); diff --git a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js index 94263e7b76a976..57adf730f3dd96 100644 --- a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js +++ b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js @@ -78,6 +78,10 @@ const coreSystem = new CoreSystem({ buildNumber: 1234, legacyMode: true, legacyMetadata: { + app: { + id: 'karma', + title: 'Karma', + }, nav: [], version: '1.2.3', buildNum: 1234, diff --git a/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx b/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx index e57cea8467d124..4ab9f95ee4c3c2 100644 --- a/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx @@ -27,7 +27,7 @@ import { RangeOption, SelectOption, SwitchOption, -} from '../../../vis_type_vislib/public/components'; +} from '../../../vis_type_vislib/public'; import { WmsOptions } from './wms_options'; import { TileMapVisParams } from '../types'; import { MapTypes } from '../map_types'; diff --git a/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx b/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx index 2989f6ce7ebd58..b81667400303d5 100644 --- a/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { EuiLink, EuiSpacer, EuiText, EuiScreenReaderOnly } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { TextInputOption } from '../../../vis_type_vislib/public/components'; +import { TextInputOption } from '../../../vis_type_vislib/public'; import { WMSOptions } from '../types'; interface WmsInternalOptions { diff --git a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx index d9dca5afd73776..a0b7a0a844f55f 100644 --- a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx @@ -25,7 +25,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { TmsLayer } from 'ui/vis/map/service_settings'; import { Vis } from 'ui/vis'; import { RegionMapVisParams } from '../../../region_map/public/types'; -import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public/components'; +import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; import { WmsInternalOptions } from './wms_internal_options'; import { WMSOptions, TileMapVisParams } from '../types'; diff --git a/src/legacy/core_plugins/timelion/index.ts b/src/legacy/core_plugins/timelion/index.ts index ec121647f4e477..42d4e04184a257 100644 --- a/src/legacy/core_plugins/timelion/index.ts +++ b/src/legacy/core_plugins/timelion/index.ts @@ -21,9 +21,7 @@ import { resolve } from 'path'; import { i18n } from '@kbn/i18n'; import { Legacy } from 'kibana'; import { LegacyPluginApi, LegacyPluginInitializer } from 'src/legacy/plugin_discovery/types'; -import { CoreSetup, PluginInitializerContext } from 'src/core/server'; -import { plugin } from './server'; -import { CustomCoreSetup } from './server/plugin'; +import { DEFAULT_APP_CATEGORIES } from '../../../core/utils'; const experimentalLabel = i18n.translate('timelion.uiSettings.experimentalLabel', { defaultMessage: 'experimental', @@ -60,6 +58,7 @@ const timelionPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPl icon: 'plugins/timelion/icon.svg', euiIconType: 'timelionApp', main: 'plugins/timelion/app', + category: DEFAULT_APP_CATEGORIES.analyze, }, styleSheetPaths: resolve(__dirname, 'public/index.scss'), hacks: [resolve(__dirname, 'public/legacy')], @@ -193,12 +192,6 @@ const timelionPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPl }, }, }, - init: (server: Legacy.Server) => { - const initializerContext = {} as PluginInitializerContext; - const core = { http: { server } } as CoreSetup & CustomCoreSetup; - - plugin(initializerContext).setup(core); - }, }); // eslint-disable-next-line import/no-default-export diff --git a/src/legacy/core_plugins/timelion/public/app.js b/src/legacy/core_plugins/timelion/public/app.js index 084e497761e438..e9f8e3496acf40 100644 --- a/src/legacy/core_plugins/timelion/public/app.js +++ b/src/legacy/core_plugins/timelion/public/app.js @@ -43,7 +43,7 @@ import '../../data/public/legacy'; import './services/saved_sheet_register'; import rootTemplate from 'plugins/timelion/index.html'; -import { createSavedVisLoader } from '../../kibana/public/visualize'; +import { createSavedVisLoader, TypesService } from '../../visualizations/public'; require('plugins/timelion/directives/cells/cells'); require('plugins/timelion/directives/fixed_element'); @@ -131,6 +131,7 @@ app.controller('timelion', function( indexPatterns: npStart.plugins.data.indexPatterns, chrome: npStart.core.chrome, overlays: npStart.core.overlays, + visualizationTypes: new TypesService().start(), }); const timezone = Private(timezoneProvider)(); diff --git a/src/legacy/core_plugins/timelion/public/directives/__tests__/timelion_expression_input_helpers.js b/src/legacy/core_plugins/timelion/public/directives/__tests__/timelion_expression_input_helpers.js deleted file mode 100644 index ea2d44bcaefe07..00000000000000 --- a/src/legacy/core_plugins/timelion/public/directives/__tests__/timelion_expression_input_helpers.js +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import PEG from 'pegjs'; -import grammar from 'raw-loader!../../../../vis_type_timelion/public/chain.peg'; -import { SUGGESTION_TYPE, suggest } from '../timelion_expression_input_helpers'; -import { getArgValueSuggestions } from '../../../../vis_type_timelion/public/helpers/arg_value_suggestions'; -import { - setIndexPatterns, - setSavedObjectsClient, -} from '../../../../vis_type_timelion/public/helpers/plugin_services'; - -describe('Timelion expression suggestions', () => { - setIndexPatterns({}); - setSavedObjectsClient({}); - - const argValueSuggestions = getArgValueSuggestions(); - - describe('getSuggestions', () => { - const func1 = { - name: 'func1', - chainable: true, - args: [ - { name: 'inputSeries' }, - { name: 'argA' }, - { - name: 'argAB', - suggestions: [{ name: 'value1' }], - }, - ], - }; - const myFunc2 = { - name: 'myFunc2', - chainable: false, - args: [{ name: 'argA' }, { name: 'argAB' }, { name: 'argABC' }], - }; - const functionList = [func1, myFunc2]; - let Parser; - beforeEach(function() { - Parser = PEG.generate(grammar); - }); - - describe('parse exception', () => { - describe('incompleteFunction', () => { - it('should return function suggestions', async () => { - const expression = '.'; - const cursorPosition = 1; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [func1, myFunc2], - location: { - min: 0, - max: 1, - }, - type: 'functions', - }); - }); - it('should filter function suggestions by function name', async () => { - const expression = '.myF'; - const cursorPosition = 4; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [myFunc2], - location: { - min: 0, - max: 4, - }, - type: 'functions', - }); - }); - }); - - describe('no argument name provided', () => { - it('should return no argument suggestions when none provided by help', async () => { - const expression = '.otherFunc(=)'; - const cursorPosition = 0; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [], - location: { - min: 11, - max: 12, - }, - type: 'arguments', - }); - }); - - it('should return argument suggestions when provided by help', async () => { - const expression = '.myFunc2(=)'; - const cursorPosition = 0; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: myFunc2.args, - location: { - min: 9, - max: 10, - }, - type: 'arguments', - }); - }); - - it('should return argument suggestions when argument value provided', async () => { - const expression = '.myFunc2(=whatArgumentAmI)'; - const cursorPosition = 0; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: myFunc2.args, - location: { - min: 9, - max: 25, - }, - type: 'arguments', - }); - }); - - it('should not show first argument for chainable functions', async () => { - const expression = '.func1(=)'; - const cursorPosition = 0; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [{ name: 'argA' }, { name: 'argAB', suggestions: [{ name: 'value1' }] }], - location: { - min: 7, - max: 8, - }, - type: 'arguments', - }); - }); - - it('should not provide argument suggestions for argument that is all ready set in function def', async () => { - const expression = '.myFunc2(argAB=provided,=)'; - const cursorPosition = 0; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [{ name: 'argA' }, { name: 'argABC' }], - location: { - min: 24, - max: 25, - }, - type: 'arguments', - }); - }); - }); - - describe('no argument value provided', () => { - it('should return no argument value suggestions when not provided by help', async () => { - const expression = '.func1(argA=)'; - const cursorPosition = 11; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [], - location: { - min: 11, - max: 11, - }, - type: 'argument_value', - }); - }); - - it('should return argument value suggestions when provided by help', async () => { - const expression = '.func1(argAB=)'; - const cursorPosition = 11; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [{ name: 'value1' }], - location: { - min: 11, - max: 11, - }, - type: 'argument_value', - }); - }); - }); - }); - - describe('parse cleanly', () => { - describe('cursor in function name', () => { - it('should return function suggestion', async () => { - const expression = '.func1()'; - const cursorPosition = 1; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [func1], - location: { - min: 0, - max: 8, - }, - type: 'functions', - }); - }); - }); - - describe('cursor in function parentheses', () => { - describe('cursor in argument name', () => { - it('should return argument suggestions', async () => { - const expression = '.myFunc2()'; - const cursorPosition = 9; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: myFunc2.args, - location: { - min: 9, - max: 9, - }, - type: 'arguments', - }); - }); - it('should not provide argument suggestions for argument that is all ready set in function def', async () => { - const expression = '.myFunc2(argAB=provided,)'; - const cursorPosition = 24; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions.type).to.equal(SUGGESTION_TYPE.ARGUMENTS); - expect(suggestions).to.eql({ - list: [{ name: 'argA' }, { name: 'argABC' }], - location: { - min: 24, - max: 24, - }, - type: 'arguments', - }); - }); - it('should filter argument suggestions by argument name', async () => { - const expression = '.myFunc2(argAB,)'; - const cursorPosition = 14; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [{ name: 'argAB' }, { name: 'argABC' }], - location: { - min: 9, - max: 14, - }, - type: 'arguments', - }); - }); - it('should not show first argument for chainable functions', async () => { - const expression = '.func1()'; - const cursorPosition = 7; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [{ name: 'argA' }, { name: 'argAB', suggestions: [{ name: 'value1' }] }], - location: { - min: 7, - max: 7, - }, - type: 'arguments', - }); - }); - }); - describe('cursor in argument value', () => { - it('should return no argument value suggestions when not provided by help', async () => { - const expression = '.myFunc2(argA=42)'; - const cursorPosition = 14; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [], - location: { - min: 14, - max: 16, - }, - type: 'argument_value', - }); - }); - - it('should return no argument value suggestions when provided by help', async () => { - const expression = '.func1(argAB=val)'; - const cursorPosition = 16; - const suggestions = await suggest( - expression, - functionList, - Parser, - cursorPosition, - argValueSuggestions - ); - expect(suggestions).to.eql({ - list: [{ name: 'value1' }], - location: { - min: 13, - max: 16, - }, - type: 'argument_value', - }); - }); - }); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js b/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js index 1fec243a277f85..57262fda55e48a 100644 --- a/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js +++ b/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js @@ -43,7 +43,7 @@ import _ from 'lodash'; import $ from 'jquery'; import PEG from 'pegjs'; -import grammar from 'raw-loader!../../../vis_type_timelion/public/chain.peg'; +import grammar from 'raw-loader!../../../../../plugins/timelion/common/chain.peg'; import timelionExpressionInputTemplate from './timelion_expression_input.html'; import { SUGGESTION_TYPE, diff --git a/src/legacy/core_plugins/timelion/public/lib/_tests_/calculate_interval.js b/src/legacy/core_plugins/timelion/public/lib/_tests_/calculate_interval.js deleted file mode 100644 index 77472dc89cd734..00000000000000 --- a/src/legacy/core_plugins/timelion/public/lib/_tests_/calculate_interval.js +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const filename = require('path').basename(__filename); -const fn = require(`../calculate_interval`); -const moment = require('moment'); -const expect = require('chai').expect; - -const from = (count, unit) => - moment() - .subtract(count, unit) - .valueOf(); -const to = moment().valueOf(); -const size = 200; -const min = '1ms'; - -describe(filename, () => { - it('Exports a function', () => { - expect(fn).to.be.a('function'); - }); - - it('Only calculates when interval = auto', () => { - const partialFn = interval => fn(from(1, 'y'), to, size, interval, min); - expect(partialFn('1ms')).to.equal('1ms'); - expect(partialFn('bag_of_beans')).to.equal('bag_of_beans'); - expect(partialFn('auto')).to.not.equal('auto'); - }); - - it('Calculates nice round intervals', () => { - const partialFn = (count, unit) => fn(from(count, unit), to, size, 'auto', min); - expect(partialFn(15, 'm')).to.equal('1s'); - expect(partialFn(1, 'h')).to.equal('30s'); - expect(partialFn(3, 'd')).to.equal('30m'); - expect(partialFn(1, 'w')).to.equal('1h'); - expect(partialFn(1, 'y')).to.equal('24h'); - expect(partialFn(100, 'y')).to.equal('1y'); - }); - - it('Does not calculate an interval lower than the minimum', () => { - const partialFn = (count, unit) => fn(from(count, unit), to, size, 'auto', '1m'); - expect(partialFn(5, 's')).to.equal('1m'); - expect(partialFn(15, 'm')).to.equal('1m'); - expect(partialFn(1, 'h')).to.equal('1m'); - expect(partialFn(3, 'd')).to.equal('30m'); - expect(partialFn(1, 'w')).to.equal('1h'); - expect(partialFn(1, 'y')).to.equal('24h'); - expect(partialFn(100, 'y')).to.equal('1y'); - }); -}); diff --git a/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts b/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts index 57ee99f5268b08..cd40cbfa89ffed 100644 --- a/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts +++ b/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts @@ -24,7 +24,11 @@ import moment from 'moment-timezone'; import { timefilter } from 'ui/timefilter'; // @ts-ignore import observeResize from '../../lib/observe_resize'; -import { calculateInterval, DEFAULT_TIME_FORMAT } from '../../../../vis_type_timelion/common/lib'; +import { + calculateInterval, + DEFAULT_TIME_FORMAT, + // @ts-ignore +} from '../../../../../../plugins/timelion/common/lib'; import { tickFormatters } from '../../../../vis_type_timelion/public/helpers/tick_formatters'; import { TimelionVisualizationDependencies } from '../../plugin'; import { xaxisFormatterProvider } from '../../../../vis_type_timelion/public/helpers/xaxis_formatter'; diff --git a/src/legacy/core_plugins/timelion/public/services/saved_sheets.ts b/src/legacy/core_plugins/timelion/public/services/saved_sheets.ts index df3898e3410ddd..074431bf28da83 100644 --- a/src/legacy/core_plugins/timelion/public/services/saved_sheets.ts +++ b/src/legacy/core_plugins/timelion/public/services/saved_sheets.ts @@ -19,20 +19,11 @@ import { npStart } from 'ui/new_platform'; import { SavedObjectLoader } from 'ui/saved_objects'; // @ts-ignore -import { savedObjectManagementRegistry } from 'plugins/kibana/management/saved_object_registry'; -// @ts-ignore import { uiModules } from 'ui/modules'; import { createSavedSheetClass } from './_saved_sheet'; const module = uiModules.get('app/sheet'); -// Register this service with the saved object registry so it can be -// edited by the object editor. -savedObjectManagementRegistry.register({ - service: 'savedSheets', - title: 'sheets', -}); - const savedObjectsClient = npStart.core.savedObjects.client; const services = { savedObjectsClient, diff --git a/src/legacy/core_plugins/timelion/server/fit_functions/__tests__/average.js b/src/legacy/core_plugins/timelion/server/fit_functions/__tests__/average.js deleted file mode 100644 index d30244610a1248..00000000000000 --- a/src/legacy/core_plugins/timelion/server/fit_functions/__tests__/average.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../average`); -import moment from 'moment'; -const expect = require('chai').expect; -import _ from 'lodash'; - -describe('average.js', function() { - describe('average', function() { - it('fills holes in the data', function() { - const data = [ - [moment.utc('1980', 'YYYY').valueOf(), 10], - [moment.utc('1983', 'YYYY').valueOf(), 40], - [moment.utc('1984', 'YYYY').valueOf(), 50], - ]; - - const target = [ - [moment.utc('1980', 'YYYY').valueOf(), null], - [moment.utc('1981', 'YYYY').valueOf(), null], - [moment.utc('1982', 'YYYY').valueOf(), null], - [moment.utc('1983', 'YYYY').valueOf(), null], - [moment.utc('1984', 'YYYY').valueOf(), null], - ]; - - expect(_.map(fn(data, target), 1)).to.eql([10, 20, 30, 40, 50]); - }); - - describe('sampling', function() { - it('up', function() { - const data = [ - [moment.utc('1981', 'YYYY').valueOf(), 10], - [moment.utc('1983', 'YYYY').valueOf(), 30], - [moment.utc('1985', 'YYYY').valueOf(), 70], - ]; - - const target = [ - [moment.utc('1981', 'YYYY').valueOf(), null], - [moment.utc('1982', 'YYYY').valueOf(), null], - [moment.utc('1983', 'YYYY').valueOf(), null], - [moment.utc('1984', 'YYYY').valueOf(), null], - [moment.utc('1985', 'YYYY').valueOf(), null], - ]; - - expect(_.map(fn(data, target), 1)).to.eql([10, 20, 30, 50, 70]); - }); - - it('down', function() { - const data = [ - [moment.utc('1980', 'YYYY').valueOf(), 0], - [moment.utc('1981', 'YYYY').valueOf(), 2], - [moment.utc('1982', 'YYYY').valueOf(), 4], - [moment.utc('1983', 'YYYY').valueOf(), 6], - [moment.utc('1984', 'YYYY').valueOf(), 8], - [moment.utc('1985', 'YYYY').valueOf(), 10], - [moment.utc('1986', 'YYYY').valueOf(), 12], - ]; - - const target = [ - [moment.utc('1981', 'YYYY').valueOf(), null], - [moment.utc('1983', 'YYYY').valueOf(), null], - [moment.utc('1985', 'YYYY').valueOf(), null], - ]; - - // This returns 1, 5, 9 instead of the expected 2, 6, 10 because the average function does not consider "future" - // values, rather just the next upcoming value from the end of the previously predicted bucket. E.g., When - // interpolating a weekly series into daily, in which the buckets fall on sundays, this coming Sunday's bucket - // will be distributed Mon-Sun instead of say Thur-Wed. - // Essentially the algorithm is left aligned instead of centered - expect(_.map(fn(data, target), 1)).to.eql([1, 5, 9]); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/fit_functions/__tests__/carry.js b/src/legacy/core_plugins/timelion/server/fit_functions/__tests__/carry.js deleted file mode 100644 index 8e35d63618ae4b..00000000000000 --- a/src/legacy/core_plugins/timelion/server/fit_functions/__tests__/carry.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../carry`); -import moment from 'moment'; -const expect = require('chai').expect; -import _ from 'lodash'; - -describe('carry.js', function() { - it('fills holes in the data', function() { - const data = [ - [moment.utc('1980', 'YYYY').valueOf(), 10], - [moment.utc('1983', 'YYYY').valueOf(), 40], - [moment.utc('1984', 'YYYY').valueOf(), 50], - ]; - - const target = [ - [moment.utc('1980', 'YYYY').valueOf(), null], - [moment.utc('1981', 'YYYY').valueOf(), null], - [moment.utc('1982', 'YYYY').valueOf(), null], - [moment.utc('1983', 'YYYY').valueOf(), null], - [moment.utc('1984', 'YYYY').valueOf(), null], - ]; - - expect(_.map(fn(data, target), 1)).to.eql([10, 10, 10, 40, 50]); - }); - - describe('sampling', function() { - it('up', function() { - const data = [ - [moment.utc('1981', 'YYYY').valueOf(), 10], - [moment.utc('1983', 'YYYY').valueOf(), 30], - [moment.utc('1985', 'YYYY').valueOf(), 70], - ]; - - const target = [ - [moment.utc('1981', 'YYYY').valueOf(), null], - [moment.utc('1982', 'YYYY').valueOf(), null], - [moment.utc('1983', 'YYYY').valueOf(), null], - [moment.utc('1984', 'YYYY').valueOf(), null], - [moment.utc('1985', 'YYYY').valueOf(), null], - ]; - - expect(_.map(fn(data, target), 1)).to.eql([10, 10, 30, 30, 70]); - }); - - it('down does not make sense', function() { - const data = [ - [moment.utc('1980', 'YYYY').valueOf(), 0], - [moment.utc('1981', 'YYYY').valueOf(), 2], - [moment.utc('1982', 'YYYY').valueOf(), 4], - [moment.utc('1983', 'YYYY').valueOf(), 6], - [moment.utc('1984', 'YYYY').valueOf(), 8], - [moment.utc('1985', 'YYYY').valueOf(), 10], - [moment.utc('1986', 'YYYY').valueOf(), 12], - ]; - - const target = [ - [moment.utc('1981', 'YYYY').valueOf(), null], - [moment.utc('1983', 'YYYY').valueOf(), null], - [moment.utc('1985', 'YYYY').valueOf(), null], - ]; - - // carry doesn't down sample, it simply doesn't make any sense. Use average or scale - try { - fn(data, target); - expect.fail('Success. Doh.'); - } catch (e) { - expect(e).to.be.an('error'); - } - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/handlers/__tests__/parse_sheet.js b/src/legacy/core_plugins/timelion/server/handlers/__tests__/parse_sheet.js deleted file mode 100644 index 4ec2a88d3e68b0..00000000000000 --- a/src/legacy/core_plugins/timelion/server/handlers/__tests__/parse_sheet.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const parseSheet = require('../lib/parse_sheet'); - -const expect = require('chai').expect; - -describe('timelion parse_sheet function', function() { - it(`doesn't split expressions on whitespace`, async function() { - const data = ['.es() .es(404)']; - const ast = parseSheet(data); - - const expressions = ast[0]; - expect(expressions.length).to.equal(1); - expect(expressions[0].type).to.equal('chain'); - }); - - it('splits expressions on commas', function() { - const data = ['.es(), .es(404)']; - const ast = parseSheet(data); - - const expressions = ast[0]; - expect(expressions.length).to.equal(2); - expect(expressions[0].type).to.equal('chain'); - expect(expressions[1].type).to.equal('chain'); - }); - - it('splits expressions on newlines', function() { - const data = [`.es()\n\r ,\n\r .es(404)`]; - const ast = parseSheet(data); - - const expressions = ast[0]; - expect(expressions.length).to.equal(2); - expect(expressions[0].type).to.equal('chain'); - expect(expressions[1].type).to.equal('chain'); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/handlers/lib/parse_sheet.js b/src/legacy/core_plugins/timelion/server/handlers/lib/parse_sheet.js deleted file mode 100644 index 4957d3cb78b85e..00000000000000 --- a/src/legacy/core_plugins/timelion/server/handlers/lib/parse_sheet.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import fs from 'fs'; -import path from 'path'; -import _ from 'lodash'; -const grammar = fs.readFileSync( - path.resolve(__dirname, '../../../../vis_type_timelion/public/chain.peg'), - 'utf8' -); -import PEG from 'pegjs'; -const Parser = PEG.generate(grammar); - -export default function parseSheet(sheet) { - return _.map(sheet, function(plot) { - try { - return Parser.parse(plot).tree; - } catch (e) { - if (e.expected) { - throw new Error( - i18n.translate('timelion.serverSideErrors.sheetParseErrorMessage', { - defaultMessage: 'Expected: {expectedDescription} at character {column}', - description: 'This would be for example: "Expected: a quote at character 5"', - values: { - expectedDescription: e.expected[0].description, - column: e.column, - }, - }) - ); - } else { - throw e; - } - } - }); -} diff --git a/src/legacy/core_plugins/timelion/server/index.ts b/src/legacy/core_plugins/timelion/server/index.ts deleted file mode 100644 index 36af9ce7b85dff..00000000000000 --- a/src/legacy/core_plugins/timelion/server/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { PluginInitializerContext } from 'kibana/server'; -import { TimelionServerPlugin as Plugin } from './plugin'; - -export function plugin(initializerContext: PluginInitializerContext) { - return new Plugin(initializerContext); -} diff --git a/src/legacy/core_plugins/timelion/server/lib/__tests__/load_functions.js b/src/legacy/core_plugins/timelion/server/lib/__tests__/load_functions.js deleted file mode 100644 index 45dd436be6943a..00000000000000 --- a/src/legacy/core_plugins/timelion/server/lib/__tests__/load_functions.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../load_functions`); - -const expect = require('chai').expect; - -describe('load_functions.js', () => { - it('exports a function', () => { - expect(fn).to.be.a('function'); - }); - - it('returns an object with keys named for the javascript files in the directory', () => { - const fnList = fn('series_functions'); - - expect(fnList).to.be.an('object'); - expect(fnList.sum).to.be.a('object'); - }); - - it('also includes index.js files in direct subdirectories, and names the keys for the directory', () => { - const fnList = fn('series_functions'); - - expect(fnList).to.be.an('object'); - expect(fnList.es).to.be.a('object'); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/lib/asSorted.js b/src/legacy/core_plugins/timelion/server/lib/asSorted.js deleted file mode 100644 index ff20af78b43623..00000000000000 --- a/src/legacy/core_plugins/timelion/server/lib/asSorted.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import unzipPairs from './unzipPairs.js'; - -export default function asSorted(timeValObject, fn) { - const data = unzipPairs(timeValObject); - return _.zipObject(fn(data)); -} diff --git a/src/legacy/core_plugins/timelion/server/lib/load_functions.js b/src/legacy/core_plugins/timelion/server/lib/load_functions.js deleted file mode 100644 index 11501ce3f102b8..00000000000000 --- a/src/legacy/core_plugins/timelion/server/lib/load_functions.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import glob from 'glob'; -import path from 'path'; -import processFunctionDefinition from './process_function_definition'; - -export default function(directory) { - function getTuple(directory, name) { - return [name, require('../' + directory + '/' + name)]; // eslint-disable-line import/no-dynamic-require - } - - // Get a list of all files and use the filename as the object key - const files = _.map(glob.sync(path.resolve(__dirname, '../' + directory + '/*.js')), function( - file - ) { - const name = file.substring(file.lastIndexOf('/') + 1, file.lastIndexOf('.')); - return getTuple(directory, name); - }); - - // Get a list of all directories with an index.js, use the directory name as the key in the object - const directories = _.chain(glob.sync(path.resolve(__dirname, '../' + directory + '/*/index.js'))) - .filter(function(file) { - return file.match(/__test__/) == null; - }) - .map(function(file) { - const parts = file.split('/'); - const name = parts[parts.length - 2]; - return getTuple(directory, name); - }) - .value(); - - const functions = _.zipObject(files.concat(directories)); - - _.each(functions, function(func) { - _.assign(functions, processFunctionDefinition(func)); - }); - - return functions; -} diff --git a/src/legacy/core_plugins/timelion/server/plugin.ts b/src/legacy/core_plugins/timelion/server/plugin.ts deleted file mode 100644 index c94277ebc7adcf..00000000000000 --- a/src/legacy/core_plugins/timelion/server/plugin.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { Legacy } from 'kibana'; -import { i18n } from '@kbn/i18n'; -import { PluginInitializerContext, CoreSetup } from 'kibana/server'; - -import loadFunctions, { LoadFunctions } from './lib/load_functions'; -import { initRoutes } from './routes'; - -function getFunction(functions: LoadFunctions, name: string) { - if (functions[name]) { - return functions[name]; - } - - throw new Error( - i18n.translate('timelion.noFunctionErrorMessage', { - defaultMessage: 'No such function: {name}', - values: { name }, - }) - ); -} - -// TODO: Remove as CoreSetup is completed. -export interface CustomCoreSetup { - http: { - server: Legacy.Server; - }; -} - -export class TimelionServerPlugin { - public initializerContext: PluginInitializerContext; - - constructor(initializerContext: PluginInitializerContext) { - this.initializerContext = initializerContext; - } - - public setup(core: CoreSetup & CustomCoreSetup) { - const { server } = core.http; - const functions = loadFunctions('series_functions'); - - server.expose('functions', functions); - server.expose('getFunction', (name: string) => getFunction(functions, name)); - - initRoutes(server); - } -} diff --git a/src/legacy/core_plugins/timelion/server/routes/functions.js b/src/legacy/core_plugins/timelion/server/routes/functions.js deleted file mode 100644 index 813d006225f43d..00000000000000 --- a/src/legacy/core_plugins/timelion/server/routes/functions.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; - -export function functionsRoute(server) { - server.route({ - method: 'GET', - path: '/api/timelion/functions', - handler: () => { - const functionArray = _.map(server.plugins.timelion.functions, function(val, key) { - // TODO: This won't work on frozen objects, it should be removed when everything is converted to datasources and chainables - return _.extend({}, val, { name: key }); - }); - - return _.sortBy(functionArray, 'name'); - }, - }); -} diff --git a/src/legacy/core_plugins/timelion/server/routes/index.ts b/src/legacy/core_plugins/timelion/server/routes/index.ts deleted file mode 100644 index b6438c81ef002c..00000000000000 --- a/src/legacy/core_plugins/timelion/server/routes/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { Legacy } from 'kibana'; - -// @ts-ignore -import { runRoute } from './run'; -// @ts-ignore -import { functionsRoute } from './functions'; -// @ts-ignore -import { validateEsRoute } from './validate_es'; - -export function initRoutes(server: Legacy.Server) { - runRoute(server); - functionsRoute(server); - validateEsRoute(server); -} diff --git a/src/legacy/core_plugins/timelion/server/routes/run.ts b/src/legacy/core_plugins/timelion/server/routes/run.ts deleted file mode 100644 index 17f87825cd8b04..00000000000000 --- a/src/legacy/core_plugins/timelion/server/routes/run.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import Joi from 'joi'; -import Bluebird from 'bluebird'; -import _ from 'lodash'; -import { Legacy } from 'kibana'; -// @ts-ignore -import chainRunnerFn from '../handlers/chain_runner.js'; -// @ts-ignore -import getNamespacesSettings from '../lib/get_namespaced_settings'; -// @ts-ignore -import getTlConfig from '../handlers/lib/tl_config'; - -const timelionDefaults = getNamespacesSettings(); - -export interface TimelionRequestQuery { - payload: { - sheet: string[]; - extended?: { - es: { - filter: { - bool: { - filter: string[] | object; - must: string[]; - should: string[]; - must_not: string[]; - }; - }; - }; - }; - }; - time?: { - from?: string; - interval: string; - timezone: string; - to?: string; - }; -} - -function formatErrorResponse(e: Error, h: Legacy.ResponseToolkit) { - return h - .response({ - title: e.toString(), - message: e.toString(), - }) - .code(500); -} - -const requestPayload = { - payload: Joi.object({ - sheet: Joi.array() - .items(Joi.string()) - .required(), - extended: Joi.object({ - es: Joi.object({ - filter: Joi.object({ - bool: Joi.object({ - filter: Joi.array().allow(null), - must: Joi.array().allow(null), - should: Joi.array().allow(null), - must_not: Joi.array().allow(null), - }), - }), - }), - }).optional(), - time: Joi.object({ - from: Joi.string(), - interval: Joi.string().required(), - timezone: Joi.string().required(), - to: Joi.string(), - }).required(), - }), -}; - -export function runRoute(server: Legacy.Server) { - server.route({ - method: 'POST', - path: '/api/timelion/run', - options: { - validate: requestPayload, - }, - handler: async (request: Legacy.Request & TimelionRequestQuery, h: Legacy.ResponseToolkit) => { - try { - const uiSettings = await request.getUiSettingsService().getAll(); - - const tlConfig = getTlConfig({ - server, - request, - settings: _.defaults(uiSettings, timelionDefaults), // Just in case they delete some setting. - }); - const chainRunner = chainRunnerFn(tlConfig); - const sheet = await Bluebird.all(chainRunner.processRequest(request.payload)); - - return { - sheet, - stats: chainRunner.getStats(), - }; - } catch (err) { - server.log(['timelion', 'error'], `${err.toString()}: ${err.stack}`); - // TODO Maybe we should just replace everywhere we throw with Boom? Probably. - if (err.isBoom) { - return err; - } else { - return formatErrorResponse(err, h); - } - } - }, - }); -} diff --git a/src/legacy/core_plugins/timelion/server/routes/validate_es.js b/src/legacy/core_plugins/timelion/server/routes/validate_es.js deleted file mode 100644 index 5e39069f2a698e..00000000000000 --- a/src/legacy/core_plugins/timelion/server/routes/validate_es.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; - -export function validateEsRoute(server) { - server.route({ - method: 'GET', - path: '/api/timelion/validate/es', - handler: async function(request) { - const uiSettings = await request.getUiSettingsService().getAll(); - - const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); - - const timefield = uiSettings['timelion:es.timefield']; - - const body = { - index: uiSettings['es.default_index'], - body: { - aggs: { - maxAgg: { - max: { - field: timefield, - }, - }, - minAgg: { - min: { - field: timefield, - }, - }, - }, - size: 0, - }, - }; - - let resp = {}; - try { - resp = await callWithRequest(request, 'search', body); - } catch (errResp) { - resp = errResp; - } - - if (_.has(resp, 'aggregations.maxAgg.value') && _.has(resp, 'aggregations.minAgg.value')) { - return { - ok: true, - field: timefield, - min: _.get(resp, 'aggregations.minAgg.value'), - max: _.get(resp, 'aggregations.maxAgg.value'), - }; - } - - return { - ok: false, - resp: resp, - }; - }, - }); -} diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/abs.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/abs.js deleted file mode 100644 index 28538d4da2f79f..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/abs.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../abs`); - -import _ from 'lodash'; -const expect = require('chai').expect; -const seriesList = require('./fixtures/seriesList.js')(); -import invoke from './helpers/invoke_series_fn.js'; - -describe('abs.js', function() { - it('should return the positive value of every value', function() { - return invoke(fn, [seriesList]).then(function(result) { - const before = _.filter(result.input[0].list[0].data, function(point) { - return point[1] < 0; - }); - - const after = _.filter(result.output.list[0].data, function(point) { - return point[1] < 0; - }); - - expect(before.length > 0).to.eql(true); - expect(result.output.list[0].data.length > 0).to.eql(true); - expect(after.length).to.eql(0); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/aggregate.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/aggregate.js deleted file mode 100644 index 6177f7cb7bac4d..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/aggregate.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const filename = require('path').basename(__filename); -const fn = require(`../aggregate/index.js`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe(filename, () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('first', () => { - return invoke(fn, [seriesList, 'first']).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([100, 100, 100, 100]); - }); - }); - - it('last', () => { - return invoke(fn, [seriesList, 'last']).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([20, 20, 20, 20]); - }); - }); - - it('min', () => { - return invoke(fn, [seriesList, 'min']).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([20, 20, 20, 20]); - }); - }); - - it('max', () => { - return invoke(fn, [seriesList, 'max']).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([100, 100, 100, 100]); - }); - }); - - it('sum', () => { - return invoke(fn, [seriesList, 'sum']).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([220, 220, 220, 220]); - }); - }); - - it('cardinality', () => { - return invoke(fn, [seriesList, 'cardinality']).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([3, 3, 3, 3]); - }); - }); - - it('avg', () => { - return invoke(fn, [seriesList, 'avg']).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([55, 55, 55, 55]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/bars.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/bars.js deleted file mode 100644 index 90b66759f7341b..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/bars.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../bars`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('bars.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('creates the bars property, with defaults, on all series', () => { - return invoke(fn, [seriesList]).then(r => { - const bars = _.map(r.output.list, 'bars'); - _.each(bars, bar => expect(bar).to.be.a('object')); - _.each(bars, bar => expect(bar.lineWidth).to.equal(6)); - _.each(bars, bar => expect(bar.show).to.equal(1)); - }); - }); - - it('leaves existing bars alone when called without option, if they exist', () => { - seriesList.list[0].bars = { foo: true }; - return invoke(fn, [seriesList]).then(r => { - const bars = _.map(r.output.list, 'bars'); - expect(bars[0].foo).to.equal(true); - expect(bars[1].foo).to.equal(undefined); - }); - }); - - it('sets lineWidth and show to the same value', () => { - return invoke(fn, [seriesList, 0]).then(r => { - const bars = _.map(r.output.list, 'bars'); - expect(bars[0].lineWidth).to.equal(0); - expect(bars[0].show).to.equal(0); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/color.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/color.js deleted file mode 100644 index f333a39bec5baf..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/color.js +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../color`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('color.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('sets the color, on all series', () => { - return invoke(fn, [seriesList, '#eee']).then(r => { - const colors = _.map(r.output.list, 'color'); - _.each(colors, color => expect(color).to.equal('#eee')); - }); - }); - - it('generates a gradient', () => { - const expected = ['#000000', '#111111', '#222222', '#333333']; - const fourLongList = { - type: 'seriesList', - list: seriesList.list.slice(0, 4), - }; - return invoke(fn, [fourLongList, '#000:#333']).then(r => { - const colors = _.map(r.output.list, 'color'); - _.each(colors, (color, i) => expect(color).to.equal(expected[i])); - }); - }); - - it('should handle more colors than number of series', async () => { - const colorsArg = '#000:#111:#222:#333:#444:#555'; - const numColors = colorsArg.split(':').length; - expect(numColors).to.be.above(seriesList.list.length); - - const r = await invoke(fn, [seriesList, colorsArg]); - const seriesColors = _.map(r.output.list, 'color'); - expect(seriesColors).to.eql(['#000000', '#111111', '#222222', '#333333', '#444444']); - }); - - it('should work with series.length=1 and more colors', async () => { - const oneLongList = { - type: 'seriesList', - list: seriesList.list.slice(0, 1), - }; - const colorsArg = '#000:#111'; - - const r = await invoke(fn, [oneLongList, colorsArg]); - const seriesColors = _.map(r.output.list, 'color'); - expect(seriesColors).to.eql(['#000']); - }); - - it('throws if you do not pass a color', () => { - invoke(fn, [seriesList, '']).catch(e => { - expect(e).to.be.an(Error); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/condition.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/condition.js deleted file mode 100644 index 533c5adfd62aba..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/condition.js +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../condition`); -import moment from 'moment'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; -import getSeriesList from './helpers/get_single_series_list'; -import _ from 'lodash'; - -describe('condition.js', function() { - let comparable; - let seriesList; - beforeEach(function() { - seriesList = require('./fixtures/seriesList.js')(); - comparable = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), 12], - [moment.utc('1981-01-01T00:00:00.000Z'), 33], - [moment.utc('1982-01-01T00:00:00.000Z'), 82], - [moment.utc('1983-01-01T00:00:00.000Z'), -101], - ]); - }); - - describe('a single number with', function() { - it('eq', function() { - return invoke(fn, [seriesList, 'eq', 17, 0]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([-51, 0, 82, 20]); - }); - }); - - it('ne', function() { - return invoke(fn, [seriesList, 'ne', 17, 0]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([0, 17, 0, 0]); - }); - }); - - it('gte', function() { - return invoke(fn, [seriesList, 'gte', 17, 0]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([-51, 0, 0, 0]); - }); - }); - - it('gt', function() { - return invoke(fn, [seriesList, 'gt', 17, 0]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([-51, 17, 0, 0]); - }); - }); - - it('lt', function() { - return invoke(fn, [seriesList, 'lt', 17, 0]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([0, 17, 82, 20]); - }); - }); - - it('lte', function() { - return invoke(fn, [seriesList, 'lte', 17, 0]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([0, 0, 82, 20]); - }); - }); - }); - - it('can compare against another series', function() { - return invoke(fn, [seriesList, 'ne', comparable, 0]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([0, 0, 82, 0]); - }); - }); - - it('can set the resultant value to that of another series', function() { - return invoke(fn, [seriesList, 'lt', comparable, comparable]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([12, 33, 82, 20]); - }); - }); - - it('can set the resultant value to null', function() { - return invoke(fn, [seriesList, 'lt', 17, null]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([null, 17, 82, 20]); - }); - }); - - describe('else', function() { - it('has else', function() { - return invoke(fn, [seriesList, 'lt', 30, 0, 1]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([0, 0, 1, 0]); - }); - }); - - it('works with other series', function() { - return invoke(fn, [seriesList, 'lt', 30, 0, comparable]).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([0, 0, 82, 0]); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/cusum.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/cusum.js deleted file mode 100644 index d9f534555b9d7e..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/cusum.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../cusum`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('cusum.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('progressively adds the numbers in the list', () => { - return invoke(fn, [seriesList]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([100, 150, 200, 220]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/derivative.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/derivative.js deleted file mode 100644 index 88ef4778ef2f16..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/derivative.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../derivative`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('derivative.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('gets the change in the set', () => { - return invoke(fn, [seriesList]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([null, -50, 0, -30]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/divide.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/divide.js deleted file mode 100644 index afe531922522fa..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/divide.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../divide`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('divide.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('divides by a single number', () => { - return invoke(fn, [seriesList, 2]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([50, 25, 25, 10]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/es.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/es.js deleted file mode 100644 index f2b364afb723ba..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/es.js +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const filename = require('path').basename(__filename); -import es from '../es'; - -import tlConfigFn from './fixtures/tlConfig'; -import * as aggResponse from '../es/lib/agg_response_to_series_list'; -import buildRequest from '../es/lib/build_request'; -import createDateAgg from '../es/lib/create_date_agg'; -import esResponse from './fixtures/es_response'; - -import Bluebird from 'bluebird'; -import _ from 'lodash'; -import { expect } from 'chai'; -import sinon from 'sinon'; -import invoke from './helpers/invoke_series_fn.js'; - -function stubRequestAndServer(response, indexPatternSavedObjects = []) { - return { - server: { - plugins: { - elasticsearch: { - getCluster: sinon - .stub() - .withArgs('data') - .returns({ - callWithRequest: function() { - return Bluebird.resolve(response); - }, - }), - }, - }, - }, - request: { - getSavedObjectsClient: function() { - return { - find: function() { - return Bluebird.resolve({ - saved_objects: indexPatternSavedObjects, - }); - }, - }; - }, - }, - }; -} - -describe(filename, () => { - let tlConfig; - - describe('seriesList processor', () => { - it('throws an error then the index is missing', () => { - tlConfig = stubRequestAndServer({ - _shards: { total: 0 }, - }); - return invoke(es, [5], tlConfig) - .then(expect.fail) - .catch(e => { - expect(e).to.be.an('error'); - }); - }); - - it('returns a seriesList', () => { - tlConfig = stubRequestAndServer(esResponse); - return invoke(es, [5], tlConfig).then(r => { - expect(r.output.type).to.eql('seriesList'); - }); - }); - }); - - describe('createDateAgg', () => { - let tlConfig; - let config; - let agg; - beforeEach(() => { - tlConfig = tlConfigFn(); - config = { - timefield: '@timestamp', - interval: '1y', - }; - agg = createDateAgg(config, tlConfig); - }); - - it('creates a date_histogram with meta.type of time_buckets', () => { - expect(agg.time_buckets.meta.type).to.eql('time_buckets'); - expect(agg.time_buckets.date_histogram).to.be.an('object'); - }); - - it('has extended_bounds that match tlConfig', () => { - expect(agg.time_buckets.date_histogram.extended_bounds.min).to.equal(tlConfig.time.from); - expect(agg.time_buckets.date_histogram.extended_bounds.max).to.equal(tlConfig.time.to); - }); - - it('sets the timezone', () => { - expect(agg.time_buckets.date_histogram.time_zone).to.equal('Etc/UTC'); - }); - - it('sets the field and interval', () => { - expect(agg.time_buckets.date_histogram.field).to.equal('@timestamp'); - expect(agg.time_buckets.date_histogram.interval).to.equal('1y'); - }); - - it('sets min_doc_count to 0', () => { - expect(agg.time_buckets.date_histogram.min_doc_count).to.equal(0); - }); - - describe('metric aggs', () => { - const emptyScriptedFields = []; - - it('adds a metric agg for each metric', () => { - config.metric = ['sum:beer', 'avg:bytes', 'percentiles:bytes']; - agg = createDateAgg(config, tlConfig, emptyScriptedFields); - expect(agg.time_buckets.aggs['sum(beer)']).to.eql({ sum: { field: 'beer' } }); - expect(agg.time_buckets.aggs['avg(bytes)']).to.eql({ avg: { field: 'bytes' } }); - expect(agg.time_buckets.aggs['percentiles(bytes)']).to.eql({ - percentiles: { field: 'bytes' }, - }); - }); - - it('adds a scripted metric agg for each scripted metric', () => { - config.metric = ['avg:scriptedBytes']; - const scriptedFields = [ - { - name: 'scriptedBytes', - script: 'doc["bytes"].value', - lang: 'painless', - }, - ]; - agg = createDateAgg(config, tlConfig, scriptedFields); - expect(agg.time_buckets.aggs['avg(scriptedBytes)']).to.eql({ - avg: { - script: { - source: 'doc["bytes"].value', - lang: 'painless', - }, - }, - }); - }); - - it('has a special `count` metric that uses a script', () => { - config.metric = ['count']; - agg = createDateAgg(config, tlConfig, emptyScriptedFields); - expect(agg.time_buckets.aggs.count.bucket_script).to.be.an('object'); - expect(agg.time_buckets.aggs.count.bucket_script.buckets_path).to.eql('_count'); - }); - }); - }); - - describe('buildRequest', () => { - const fn = buildRequest; - const emptyScriptedFields = []; - let tlConfig; - let config; - beforeEach(() => { - tlConfig = tlConfigFn(); - config = { - timefield: '@timestamp', - interval: '1y', - index: 'beer', - }; - }); - - it('sets the index on the request', () => { - config.index = 'beer'; - const request = fn(config, tlConfig, emptyScriptedFields); - - expect(request.index).to.equal('beer'); - }); - - it('always sets body.size to 0', () => { - const request = fn(config, tlConfig, emptyScriptedFields); - - expect(request.body.size).to.equal(0); - }); - - it('creates a filters agg that contains each of the queries passed', () => { - config.q = ['foo', 'bar']; - const request = fn(config, tlConfig, emptyScriptedFields); - - expect(request.body.aggs.q.meta.type).to.equal('split'); - - const filters = request.body.aggs.q.filters.filters; - expect(filters.foo.query_string.query).to.eql('foo'); - expect(filters.bar.query_string.query).to.eql('bar'); - }); - - describe('timeouts', () => { - it('sets the timeout on the request', () => { - config.index = 'beer'; - const request = fn(config, tlConfig, emptyScriptedFields, 30000); - - expect(request.timeout).to.equal('30000ms'); - }); - - it('sets no timeout if elasticsearch.shardTimeout is set to 0', () => { - config.index = 'beer'; - const request = fn(config, tlConfig, emptyScriptedFields, 0); - - expect(request).to.not.have.property('timeout'); - }); - }); - - describe('frozen indices', () => { - let sandbox; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('sets ignore_throttled=true on the request', () => { - config.index = 'beer'; - tlConfig.settings['search:includeFrozen'] = false; - const request = fn(config, tlConfig, emptyScriptedFields); - - expect(request.ignore_throttled).to.equal(true); - }); - - it('sets no timeout if elasticsearch.shardTimeout is set to 0', () => { - tlConfig.settings['search:includeFrozen'] = true; - config.index = 'beer'; - const request = fn(config, tlConfig, emptyScriptedFields); - - expect(request.ignore_throttled).to.equal(false); - }); - }); - - describe('query body', () => { - beforeEach(() => { - tlConfig = _.merge(tlConfigFn(), { - time: { - from: 1, - to: 5, - }, - request: { - payload: { - extended: { - es: { - filter: { - bool: { - must: [{ query: { query_string: { query: 'foo' } } }], - must_not: [ - { query: { query_string: { query: 'bar' } } }, - { query: { query_string: { query: 'baz' } } }, - ], - }, - }, - }, - }, - }, - }, - }); - }); - - it('adds the contents of payload.extended.es.filter to a filter clause of the bool', () => { - config.kibana = true; - const request = fn(config, tlConfig, emptyScriptedFields); - const filter = request.body.query.bool.filter.bool; - expect(filter.must.length).to.eql(1); - expect(filter.must_not.length).to.eql(2); - }); - - it('does not include filters if config.kibana = false', () => { - config.kibana = false; - const request = fn(config, tlConfig, emptyScriptedFields); - expect(request.body.query.bool.filter).to.eql(undefined); - }); - - it('adds a time filter to the bool querys must clause', () => { - let request = fn(config, tlConfig, emptyScriptedFields); - expect(request.body.query.bool.must.length).to.eql(1); - expect(request.body.query.bool.must[0]).to.eql({ - range: { - '@timestamp': { - format: 'strict_date_optional_time', - gte: '1970-01-01T00:00:00.001Z', - lte: '1970-01-01T00:00:00.005Z', - }, - }, - }); - - config.kibana = true; - request = fn(config, tlConfig, emptyScriptedFields); - expect(request.body.query.bool.must.length).to.eql(1); - }); - }); - - describe('config.split', () => { - it('adds terms aggs, in order, under the filters agg', () => { - config.split = ['beer:5', 'wine:10']; - const request = fn(config, tlConfig, emptyScriptedFields); - - const aggs = request.body.aggs.q.aggs; - - expect(aggs.beer.meta.type).to.eql('split'); - expect(aggs.beer.terms.field).to.eql('beer'); - expect(aggs.beer.terms.size).to.eql(5); - - expect(aggs.beer.aggs.wine.meta.type).to.eql('split'); - expect(aggs.beer.aggs.wine.terms.field).to.eql('wine'); - expect(aggs.beer.aggs.wine.terms.size).to.eql(10); - }); - - it('adds scripted terms aggs, in order, under the filters agg', () => { - config.split = ['scriptedBeer:5', 'scriptedWine:10']; - const scriptedFields = [ - { - name: 'scriptedBeer', - script: 'doc["beer"].value', - lang: 'painless', - }, - { - name: 'scriptedWine', - script: 'doc["wine"].value', - lang: 'painless', - }, - ]; - const request = fn(config, tlConfig, scriptedFields); - - const aggs = request.body.aggs.q.aggs; - - expect(aggs.scriptedBeer.meta.type).to.eql('split'); - expect(aggs.scriptedBeer.terms.script).to.eql({ - source: 'doc["beer"].value', - lang: 'painless', - }); - expect(aggs.scriptedBeer.terms.size).to.eql(5); - - expect(aggs.scriptedBeer.aggs.scriptedWine.meta.type).to.eql('split'); - expect(aggs.scriptedBeer.aggs.scriptedWine.terms.script).to.eql({ - source: 'doc["wine"].value', - lang: 'painless', - }); - expect(aggs.scriptedBeer.aggs.scriptedWine.terms.size).to.eql(10); - }); - }); - }); - - describe('Aggregation flattening', () => { - let config; - beforeEach(() => { - config = { fit: 'nearest' }; - }); - - describe('timeBucketsToPairs', () => { - const fn = aggResponse.timeBucketsToPairs; - - it('Should convert a single metric agg', () => { - const buckets = [ - { key: 1000, count: { value: 3 } }, - { key: 2000, count: { value: 14 } }, - { key: 3000, count: { value: 15 } }, - ]; - - expect(fn(buckets)).to.eql({ - count: [ - [1000, 3], - [2000, 14], - [3000, 15], - ], - }); - }); - - it('Should convert multiple metric aggs', () => { - const buckets = [ - { key: 1000, count: { value: 3 }, max: { value: 92 } }, - { key: 2000, count: { value: 14 }, max: { value: 65 } }, - { key: 3000, count: { value: 15 }, max: { value: 35 } }, - ]; - - expect(fn(buckets)).to.eql({ - count: [ - [1000, 3], - [2000, 14], - [3000, 15], - ], - max: [ - [1000, 92], - [2000, 65], - [3000, 35], - ], - }); - }); - - it('Should convert percentiles metric aggs', () => { - const buckets = [ - { - key: 1000, - percentiles: { values: { '50.0': 'NaN', '75.0': 65, '95.0': 73, '99.0': 75 } }, - }, - { - key: 2000, - percentiles: { values: { '50.0': 25, '75.0': 32, '95.0': 'NaN', '99.0': 67 } }, - }, - { - key: 3000, - percentiles: { values: { '50.0': 15, '75.0': 15, '95.0': 15, '99.0': 15 } }, - }, - ]; - - expect(fn(buckets)).to.eql({ - 'percentiles:50.0': [ - [1000, NaN], - [2000, 25], - [3000, 15], - ], - 'percentiles:75.0': [ - [1000, 65], - [2000, 32], - [3000, 15], - ], - 'percentiles:95.0': [ - [1000, 73], - [2000, NaN], - [3000, 15], - ], - 'percentiles:99.0': [ - [1000, 75], - [2000, 67], - [3000, 15], - ], - }); - }); - }); - - it('should throw an error', () => { - expect(aggResponse.default(esResponse.aggregations, config)).to.eql([ - { - data: [ - [1000, 264], - [2000, 264], - ], - fit: 'nearest', - label: 'q:QueryA > FieldA:ValueA > FieldB:Value2A > MetricA', - split: 'Value2A', - type: 'series', - }, - { - data: [ - [1000, 398], - [2000, 1124], - ], - fit: 'nearest', - label: 'q:QueryA > FieldA:ValueA > FieldB:Value2A > MetricB', - split: 'Value2A', - type: 'series', - }, - { - data: [ - [1000, 699], - [2000, 110], - ], - fit: 'nearest', - label: 'q:QueryA > FieldA:ValueA > FieldB:Value2B > MetricA', - split: 'Value2B', - type: 'series', - }, - { - data: [ - [1000, 457], - [2000, 506], - ], - fit: 'nearest', - label: 'q:QueryA > FieldA:ValueA > FieldB:Value2B > MetricB', - split: 'Value2B', - type: 'series', - }, - { - data: [ - [1000, 152], - [2000, 518], - ], - fit: 'nearest', - label: 'q:QueryA > FieldA:ValueB > FieldB:Value2B > MetricA', - split: 'Value2B', - type: 'series', - }, - { - data: [ - [1000, 61], - [2000, 77], - ], - fit: 'nearest', - label: 'q:QueryA > FieldA:ValueB > FieldB:Value2B > MetricB', - split: 'Value2B', - type: 'series', - }, - { - data: [ - [1000, 114], - [2000, 264], - ], - fit: 'nearest', - label: 'q:QueryA > FieldA:ValueB > FieldB:Value2A > MetricA', - split: 'Value2A', - type: 'series', - }, - { - data: [ - [1000, 23], - [2000, 45], - ], - fit: 'nearest', - label: 'q:QueryA > FieldA:ValueB > FieldB:Value2A > MetricB', - split: 'Value2A', - type: 'series', - }, - { - data: [ - [1000, 621], - [2000, 751], - ], - fit: 'nearest', - label: 'q:QueryB > FieldA:ValueA > FieldB:Value2B > MetricA', - split: 'Value2B', - type: 'series', - }, - { - data: [ - [1000, 12], - [2000, 12], - ], - fit: 'nearest', - label: 'q:QueryB > FieldA:ValueA > FieldB:Value2B > MetricB', - split: 'Value2B', - type: 'series', - }, - { - data: [ - [1000, 110], - [2000, 648], - ], - fit: 'nearest', - label: 'q:QueryB > FieldA:ValueA > FieldB:Value2A > MetricA', - split: 'Value2A', - type: 'series', - }, - { - data: [ - [1000, 11], - [2000, 12], - ], - fit: 'nearest', - label: 'q:QueryB > FieldA:ValueA > FieldB:Value2A > MetricB', - split: 'Value2A', - type: 'series', - }, - { - data: [ - [1000, 755], - [2000, 713], - ], - fit: 'nearest', - label: 'q:QueryB > FieldA:ValueC > FieldB:Value2C > MetricA', - split: 'Value2C', - type: 'series', - }, - { - data: [ - [1000, 10], - [2000, 18], - ], - fit: 'nearest', - label: 'q:QueryB > FieldA:ValueC > FieldB:Value2C > MetricB', - split: 'Value2C', - type: 'series', - }, - { - data: [ - [1000, 391], - [2000, 802], - ], - fit: 'nearest', - label: 'q:QueryB > FieldA:ValueC > FieldB:Value2A > MetricA', - split: 'Value2A', - type: 'series', - }, - { - data: [ - [1000, 4], - [2000, 4], - ], - fit: 'nearest', - label: 'q:QueryB > FieldA:ValueC > FieldB:Value2A > MetricB', - split: 'Value2A', - type: 'series', - }, - ]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/first.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/first.js deleted file mode 100644 index 3e86554e843b0c..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/first.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../first`); - -const expect = require('chai').expect; -const seriesList = require('./fixtures/seriesList.js')(); -import invoke from './helpers/invoke_series_fn.js'; - -describe('first.js', function() { - it('should return exactly the data input', function() { - return invoke(fn, [seriesList]).then(function(result) { - expect(result.input[0]).to.eql(result.output); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fit.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fit.js deleted file mode 100644 index db9360da3f5921..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fit.js +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../fit`); -import moment from 'moment'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; -import getSeriesList from './helpers/get_single_series_list'; -import _ from 'lodash'; - -describe('fit.js', function() { - describe('should not filter out zeros', function() { - it('all zeros', function() { - const seriesList = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), 0], - [moment.utc('1981-01-01T00:00:00.000Z'), null], - [moment.utc('1982-01-01T00:00:00.000Z'), 0], - [moment.utc('1983-01-01T00:00:00.000Z'), 0], - ]); - - return invoke(fn, [seriesList, 'carry']).then(function(r) { - expect(r.input[0].list[0].data[1][1]).to.equal(null); - expect(_.map(r.output.list[0].data, 1)).to.eql([0, 0, 0, 0]); - expect(r.output.list[0].data[1][0]).to.not.equal(r.output.list[0].data[0][0]); - }); - }); - - it('mixed zeros and numbers', function() { - const seriesList = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), 26], - [moment.utc('1981-01-01T00:00:00.000Z'), 42], - [moment.utc('1982-01-01T00:00:00.000Z'), 0], - [moment.utc('1983-01-01T00:00:00.000Z'), null], - [moment.utc('1984-01-01T00:00:00.000Z'), 1], - ]); - - return invoke(fn, [seriesList, 'carry']).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([26, 42, 0, 0, 1]); - }); - }); - }); - - it('should return original series when all values are null', function() { - const seriesList = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), null], - [moment.utc('1981-01-01T00:00:00.000Z'), null], - [moment.utc('1982-01-01T00:00:00.000Z'), null], - [moment.utc('1983-01-01T00:00:00.000Z'), null], - ]); - - return invoke(fn, [seriesList, 'carry']).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([null, null, null, null]); - }); - }); - - describe('carry', function() { - it('should maintain the previous value until it changes', function() { - const seriesList = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), 5], - [moment.utc('1981-01-01T00:00:00.000Z'), null], - [moment.utc('1982-01-01T00:00:00.000Z'), 3.4], - [moment.utc('1983-01-01T00:00:00.000Z'), 171], - ]); - - return invoke(fn, [seriesList, 'carry']).then(function(r) { - expect(r.input[0].list[0].data[1][1]).to.equal(null); - expect(_.map(r.output.list[0].data, 1)).to.eql([5, 5, 3.4, 171]); - expect(r.output.list[0].data[1][0]).to.not.equal(r.output.list[0].data[0][0]); - }); - }); - }); - - describe('nearest', function() { - it('should use the closest temporal value to fill the null', function() { - const seriesList = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), 5], - [moment.utc('1981-01-01T00:00:00.000Z'), null], - [moment.utc('1981-05-01T00:00:00.000Z'), 3.4], - [moment.utc('1983-01-01T00:00:00.000Z'), 171], - ]); - - return invoke(fn, [seriesList, 'nearest']).then(function(r) { - expect(r.input[0].list[0].data[1][1]).to.equal(null); - expect(_.map(r.output.list[0].data, 1)).to.eql([5, 3.4, 3.4, 171]); - expect(r.output.list[0].data[1][0]).to.not.equal(r.output.list[0].data[0][0]); - }); - }); - }); - - describe('average', function() { - it('should produce a smooth, straight line between points', function() { - const seriesList = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), 10], - [moment.utc('1981-07-01T00:00:00.000Z'), null], - [moment.utc('1982-01-01T00:00:00.000Z'), null], - [moment.utc('1983-01-01T00:00:00.000Z'), 40], - [moment.utc('1984-01-01T00:00:00.000Z'), 50], - ]); - - return invoke(fn, [seriesList, 'average']).then(function(r) { - expect(r.input[0].list[0].data[1][1]).to.eql(null); - expect(_.map(r.output.list[0].data, 1)).to.eql([10, 20, 30, 40, 50]); - }); - }); - }); - - describe('scale', function() { - it('should distribute the next points value across the preceeding nulls', function() { - const seriesList = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), 10], - [moment.utc('1981-07-01T00:00:00.000Z'), null], - [moment.utc('1982-01-01T00:00:00.000Z'), null], - [moment.utc('1983-01-01T00:00:00.000Z'), 60], - [moment.utc('1984-01-01T00:00:00.000Z'), 50], - ]); - - return invoke(fn, [seriesList, 'scale']).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([10, 20, 20, 20, 50]); - }); - }); - }); - - describe('none', function() { - it('basically just drops the nulls. This is going to screw you', function() { - const seriesList = getSeriesList('', [ - [moment.utc('1980-01-01T00:00:00.000Z'), 10], - [moment.utc('1981-07-01T00:00:00.000Z'), null], - [moment.utc('1982-01-01T00:00:00.000Z'), null], - [moment.utc('1983-01-01T00:00:00.000Z'), 40], - [moment.utc('1984-01-01T00:00:00.000Z'), 50], - ]); - - return invoke(fn, [seriesList, 'none']).then(function(r) { - expect(_.map(r.output.list[0].data, 1)).to.eql([10, 40, 50]); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/seriesList.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/seriesList.js deleted file mode 100644 index 29b759af521ed0..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/seriesList.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import buckets from './bucketList'; -import getSeries from '../helpers/get_series'; -import getSeriesList from '../helpers/get_series_list'; - -export default function() { - return getSeriesList([ - getSeries('Negative', buckets, [-51, 17, 82, 20]), - getSeries('Nice', buckets, [100, 50, 50, 20]), - getSeries('All the same', buckets, [1, 1, 1, 1]), - getSeries('Decimals', buckets, [3.1415926535, 2, 1.439, 0.3424235]), - getSeries('PowerOfTen', buckets, [10, 100, 10, 1]), - ]); -} diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js deleted file mode 100644 index 6eea99424c4abe..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import moment from 'moment'; -import { of } from 'rxjs'; -import sinon from 'sinon'; -import timelionDefaults from '../../../lib/get_namespaced_settings'; -import esResponse from './es_response'; - -export default function() { - const functions = require('../../../lib/load_functions')('series_functions'); - const kibanaServerConfigs = { - 'timelion.graphiteUrls': ['https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite'], - }; - const server = { - plugins: { - timelion: { - getFunction: name => { - if (!functions[name]) throw new Error('No such function: ' + name); - return functions[name]; - }, - }, - elasticsearch: { - getCluster: sinon - .stub() - .withArgs('data') - .returns({ - callWithRequest: function() { - return Promise.resolve(esResponse); - }, - }), - }, - }, - newPlatform: { - __internals: { - elasticsearch: { - legacy: { config$: of({ shardTimeout: moment.duration(30000) }) }, - }, - }, - }, - config: () => ({ get: key => kibanaServerConfigs[key] }), - }; - - const tlConfig = require('../../../handlers/lib/tl_config.js')({ - server, - request: {}, - }); - - tlConfig.time = { - interval: '1y', - from: moment('1980-01-01T00:00:00Z').valueOf(), - to: moment('1983-01-01T00:00:00Z').valueOf(), - timezone: 'Etc/UTC', - }; - - tlConfig.settings = timelionDefaults(); - - tlConfig.setTargetSeries(); - - return tlConfig; -} diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/graphite.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/graphite.js deleted file mode 100644 index b7ee96ef77575f..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/graphite.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import proxyquire from 'proxyquire'; -import Bluebird from 'bluebird'; -const expect = require('chai').expect; - -const graphiteResponse = function() { - return Bluebird.resolve({ - json: function() { - return [ - { - target: '__beer__', - datapoints: [ - [3, 1000], - [14, 2000], - [1.5, 3000], - [92.6535, 4000], - ], - }, - ]; - }, - }); -}; - -const filename = require('path').basename(__filename); -const fn = proxyquire(`../${filename}`, { 'node-fetch': graphiteResponse }); - -import invoke from './helpers/invoke_series_fn.js'; - -describe(filename, function() { - it('should wrap the graphite response up in a seriesList', function() { - return invoke(fn, []).then(function(result) { - expect(result.output.list[0].data[0][1]).to.eql(3); - expect(result.output.list[0].data[1][1]).to.eql(14); - }); - }); - - it('should convert the seconds to milliseconds', function() { - return invoke(fn, []).then(function(result) { - expect(result.output.list[0].data[1][0]).to.eql(2000 * 1000); - }); - }); - - it('should set the label to that of the graphite target', function() { - return invoke(fn, []).then(function(result) { - expect(result.output.list[0].label).to.eql('__beer__'); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/hide.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/hide.js deleted file mode 100644 index 5d4b6246708471..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/hide.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../hide`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('hide.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('hides a series', () => { - return invoke(fn, [seriesList, true]).then(r => { - _.each(r.output.list, series => expect(series._hide).to.equal(true)); - }); - }); - - it('unhides a series', () => { - return invoke(fn, [seriesList, false]).then(r => { - _.each(r.output.list, series => expect(series._hide).to.equal(false)); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/label.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/label.js deleted file mode 100644 index 9e0a92b1e40042..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/label.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../label`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('label.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('changes the label on the series', () => { - return invoke(fn, [seriesList, 'free beer']).then(r => { - _.each(r.output.list, series => expect(series.label).to.equal('free beer')); - }); - }); - - it('can use a regex to capture parts of a series label', () => { - return invoke(fn, [seriesList, 'beer$1', 'Neg(.*)']).then(r => { - expect(r.output.list[0].label).to.equal('beerative'); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/legend.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/legend.js deleted file mode 100644 index 205f0c4431fccd..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/legend.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../legend`); - -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('legend.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('should create the _global object if it does not exist', () => { - expect(seriesList.list[0]._global).to.equal(undefined); - return invoke(fn, [seriesList, 'nw', 3, true, 'YYYY']).then(r => { - expect(r.output.list[0]._global).to.eql({ - legend: { noColumns: 3, position: 'nw', showTime: true, timeFormat: 'YYYY' }, - }); - }); - }); - - it('should provide default values for time axis display', () => { - return invoke(fn, [seriesList, 'nw', 3]).then(r => { - expect(r.output.list[0]._global.legend.showTime).to.equal(true); - expect(r.output.list[0]._global.legend.timeFormat).to.equal('MMMM Do YYYY, HH:mm:ss.SSS'); - }); - }); - - it('should hide the legend is position is false', () => { - return invoke(fn, [seriesList, false]).then(r => { - expect(r.output.list[0]._global.legend.show).to.equal(false); - expect(r.output.list[0]._global.legend.showTime).to.equal(false); - }); - }); - - it('should set legend.showTime to false when showTime parameter is false', () => { - return invoke(fn, [seriesList, 'nw', 3, false]).then(r => { - expect(r.output.list[0]._global.legend.showTime).to.equal(false); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/lines.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/lines.js deleted file mode 100644 index 32974495b40eb4..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/lines.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../lines`); - -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('lines.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('should simply set show, steps, stack and lineWidth', () => { - expect(seriesList.list[0]._global).to.equal(undefined); - return invoke(fn, [seriesList, 1, 2, true, true, false]).then(r => { - expect(r.output.list[0].lines.lineWidth).to.equal(1); - expect(r.output.list[0].lines.show).to.equal(true); - expect(r.output.list[0].stack).to.equal(true); - expect(r.output.list[0].lines.steps).to.equal(false); - }); - }); - - it('should set lineWidth to 3 by default, and nothing else', () => { - expect(seriesList.list[0]._global).to.equal(undefined); - return invoke(fn, [seriesList]).then(r => { - expect(r.output.list[0].lines.lineWidth).to.equal(3); - expect(r.output.list[0].lines.fill).to.equal(undefined); - expect(r.output.list[0].lines.show).to.equal(undefined); - expect(r.output.list[0].stack).to.equal(undefined); - expect(r.output.list[0].lines.steps).to.equal(undefined); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/log.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/log.js deleted file mode 100644 index 8cd2e2caa2c470..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/log.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../log`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('log.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('should return the log10 value of every value', () => { - return invoke(fn, [seriesList]).then(r => { - expect(_.map(r.output.list[4].data, 1)).to.eql([1, 2, 1, 0]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/max.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/max.js deleted file mode 100644 index 9cc4afffb22ba9..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/max.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../max`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('max.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('keeps the max of a series vs a number', () => { - return invoke(fn, [seriesList, 20]).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([20, 20, 82, 20]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/min.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/min.js deleted file mode 100644 index a89183ee90c6b6..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/min.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../min`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('min.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('keeps the min of a series vs a number', () => { - return invoke(fn, [seriesList, 20]).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([-51, 17, 20, 20]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/movingaverage.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/movingaverage.js deleted file mode 100644 index dceef96b1d1664..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/movingaverage.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../movingaverage`); -const expect = require('chai').expect; - -import moment from 'moment'; -import _ from 'lodash'; -import buckets from './fixtures/bucketList'; -import getSeries from './helpers/get_series'; -import getSeriesList from './helpers/get_series_list'; -import invoke from './helpers/invoke_series_fn.js'; - -function getFivePointSeries() { - return getSeriesList([ - getSeries('Five', [].concat(buckets).push(moment('1984-01-01T00:00:00.000Z')), [ - 10, - 20, - 30, - 40, - 50, - ]), - ]); -} - -describe('movingaverage.js', () => { - let seriesList; - beforeEach(() => { - seriesList = getFivePointSeries(); - }); - - it('centers the averaged series by default', () => { - return invoke(fn, [seriesList, 3]).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([null, 20, 30, 40, null]); - }); - }); - - it('aligns the moving average to the left', () => { - return invoke(fn, [seriesList, 3, 'left']).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([null, null, 20, 30, 40]); - }); - }); - - it('aligns the moving average to the right', () => { - return invoke(fn, [seriesList, 3, 'right']).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([20, 30, 40, null, null]); - }); - }); - - describe('date math', () => { - it('accepts 2 years', () => { - return invoke(fn, [seriesList, '2y', 'left']).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([null, 15, 25, 35, 45]); - }); - }); - - it('accepts 3 years', () => { - return invoke(fn, [seriesList, '3y', 'left']).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([null, null, 20, 30, 40]); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/movingstd.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/movingstd.js deleted file mode 100644 index d2ef271293afc6..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/movingstd.js +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../movingstd`); - -import moment from 'moment'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; -import getSeries from './helpers/get_series'; -import getSeriesList from './helpers/get_series_list'; - -describe('movingstd.js', () => { - it('computes the moving standard deviation of a list', async () => { - const points = [ - 108.48, - 111.56, - 112.13, - 113.75, - 114.25, - 110.79, - 111.21, - 116.82, - 117.16, - 120.38, - 116.96, - 119.56, - 118.97, - 117.54, - 114.42, - 111.01, - 114.2, - 116.43, - 117.74, - 119.9, - 124.65, - 124.98, - 124.7, - 123.6, - 124.5, - 126.85, - ]; - const buckets = []; - buckets[0] = moment('2018-01-01T00:00:00.000Z'); - for (let i = 1; i < points.length; i++) { - buckets[i] = buckets[i - 1].add(1, 'hours'); - } - const series = getSeries('test data', buckets, points); - const seriesList = getSeriesList([series]); - const numWindows = 5; - const position = 'left'; - const results = await invoke(fn, [seriesList, numWindows, position]); - - const resultPoints = results.output.list[0].data.map(row => { - // row is an array; index 0 is the time bucket, index 1 is the value - return row[1]; - }); - // First 5 result buckets are null since moving window is filling up. - const trimmedResultPoints = resultPoints.slice(numWindows); - - const expectedPoints = [ - 2.28, - 1.46, - 1.53, - 2.46, - 3.0, - 4.14, - 3.31, - 1.67, - 1.5, - 1.41, - 2.01, - 3.56, - 3.12, - 2.5, - 2.56, - 3.41, - 3.97, - 3.92, - 3.35, - 2.12, - 0.52, - ]; - - expectedPoints.forEach((value, index) => { - expect(trimmedResultPoints[index]).to.be.within(value - 0.01, value + 0.01); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/multiply.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/multiply.js deleted file mode 100644 index 0cc5665fb919a0..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/multiply.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../multiply`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('multiply.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('multiplies by a number', () => { - return invoke(fn, [seriesList, 2]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([200, 100, 100, 40]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/points.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/points.js deleted file mode 100644 index 53831f0f6138de..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/points.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../points`); - -import _ from 'lodash'; -import assert from 'chai'; -const expect = assert.expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('points.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('should set the point radius', () => { - return invoke(fn, [seriesList, 1]).then(r => { - expect(r.output.list[0].points.radius).to.equal(1); - }); - }); - - it('should set the point lineWidth', () => { - return invoke(fn, [seriesList, null, 3]).then(r => { - expect(r.output.list[0].points.lineWidth).to.equal(3); - }); - }); - - it('should set the point fill', () => { - return invoke(fn, [seriesList, null, null, 3]).then(r => { - expect(r.output.list[0].points.fill).to.equal(3 / 10); - }); - }); - - it('should not set the fill color if fill is not specified', () => { - return invoke(fn, [seriesList, null, null, null, '#333']).then(r => { - expect(r.output.list[0].points.fillColor).to.equal(undefined); - }); - }); - - it('should set the fill color ', () => { - return invoke(fn, [seriesList, null, null, 10, '#333']).then(r => { - expect(r.output.list[0].points.fillColor).to.equal('#333'); - }); - }); - - describe('symbol', () => { - const symbols = ['triangle', 'cross', 'square', 'diamond', 'circle']; - _.each(symbols, symbol => { - it(`is ${symbol}`, () => { - return invoke(fn, [seriesList, null, null, null, null, symbol]).then(r => { - expect(r.output.list[0].points.symbol).to.equal(symbol); - }); - }); - }); - - it('does not allow undefined symbols', () => { - return invoke(fn, [seriesList, null, null, null, null, 'beer']) - .then(expect.fail) - .catch(e => { - expect(e).to.be.an('error'); - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/precision.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/precision.js deleted file mode 100644 index 29e3bc1ab66f8f..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/precision.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../precision`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('precision.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('keeps the min of a series vs a number', () => { - return invoke(fn, [seriesList, 2]).then(r => { - expect(_.map(r.output.list[3].data, 1)).to.eql([3.14, 2, 1.43, 0.34]); - }); - }); - - it('Adds a _meta to describe the precision to display', () => { - return invoke(fn, [seriesList, 2]).then(r => { - expect(r.output.list[3]._meta.precision).to.eql(2); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/quandl.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/quandl.js deleted file mode 100644 index 009c0e4e025cd9..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/quandl.js +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import proxyquire from 'proxyquire'; -import Bluebird from 'bluebird'; -import assert from 'chai'; -const expect = assert.expect; - -const parseURL = require('url').parse; -const parseQueryString = require('querystring').parse; -const tlConfig = require('./fixtures/tlConfig')(); -import moment from 'moment'; - -const filename = require('path').basename(__filename); -import invoke from './helpers/invoke_series_fn.js'; - -let fn; -let response; -let calledWith; -describe(filename, function() { - beforeEach(function() { - response = function(url) { - calledWith = { - params: parseQueryString(parseURL(url).query), - code: url.match(/datasets\/(.*).json/)[1], - }; - return Bluebird.resolve({ - json: function() { - return { - name: '__beer__', - data: [ - ['2015-01-01', 3], - ['2015-01-02', 14], - ['2015-01-03', 15.92], - ['2015-01-04', 65.35], - ], - }; - }, - }); - }; - fn = proxyquire(`../${filename}`, { 'node-fetch': response }); - }); - - it('should wrap the quandl response up in a seriesList', function() { - return invoke(fn, []).then(function(result) { - expect(result.output.list[0].data[0][1]).to.eql(3); - expect(result.output.list[0].data[1][1]).to.eql(14); - }); - }); - - it('should set the label to that of the quandl name', function() { - return invoke(fn, []).then(function(result) { - expect(result.output.list[0].label).to.eql('__beer__'); - }); - }); - - it('should call the quandl API with the quandl code that has been passed', function() { - return invoke(fn, ['BEER/IS_GOOD']).then(function() { - expect(calledWith.code).to.eql('BEER/IS_GOOD'); - }); - }); - - it('should limit the time span and interval to the stuff attached to tlConfig', function() { - return invoke(fn, []).then(function() { - expect(calledWith.params.trim_start).to.eql( - moment.utc(tlConfig.time.from).format('YYYY-MM-DD') - ); - expect(calledWith.params.trim_end).to.eql(moment.utc(tlConfig.time.to).format('YYYY-MM-DD')); - }); - }); - - it('should throw an error is passed an unsupported interval', function() { - return invoke(fn, [], { time: { interval: '2d' } }) - .then(expect.fail) - .catch(function(r) { - expect(r).to.be.an('error'); - }); - }); - - it('should use the configured API key when talking to quandl', function() { - return invoke(fn, [], { settings: { 'timelion:quandl.key': 'bEeR' } }).then(function() { - expect(calledWith.params.auth_token).to.eql('bEeR'); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/range.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/range.js deleted file mode 100644 index 38bee7d45565e6..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/range.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../range`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('range.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - seriesList.list[0].data = [ - [1000, 20], - [2000, 10], - [3000, 30], - [4000, 40], - ]; - }); - - it('keeps the min of a series vs a number', () => { - return invoke(fn, [seriesList, 1, 4]).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([2, 1, 3, 4]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/scale_interval.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/scale_interval.js deleted file mode 100644 index 12ad5503e69bfe..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/scale_interval.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../scale_interval`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('scale_interval.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('Can multiply to transform one interval to another', () => { - return invoke(fn, [seriesList, '5y']).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([500, 250, 250, 100]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/static.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/static.js deleted file mode 100644 index cea9525694ab3d..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/static.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../static`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('static.js', () => { - it('returns a series in which all numbers are the same', () => { - return invoke(fn, [5]).then(r => { - expect(_.unique(_.map(r.output.list[0].data, 1))).to.eql([5]); - }); - }); - - it('plots a provided series', () => { - return invoke(fn, ['4:3:2:1']).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([4, 3, 2, 1]); - }); - }); - - it('leaves interpolation up to the data source wrapper', () => { - return invoke(fn, ['1:4']).then(r => { - expect(_.map(r.output.list[0].data, 1)).to.eql([1, 4]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/subtract.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/subtract.js deleted file mode 100644 index 55d661ea95485e..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/subtract.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../subtract`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('subtract.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('it throws an error if first argument is not seriesList', async () => { - const notSeriesList = [1, 2, 3, 4]; - try { - await invoke(fn, [notSeriesList]); - expect.fail(); - } catch (e) { - expect(e.message).to.eql('input must be a seriesList'); - } - }); - - it('it subtracts all series in seriesList to single series when only one argument is supplied', async () => { - const outputSeries = await invoke(fn, [seriesList]); - expect(outputSeries.output.list.length).to.eql(1); - expect(_.map(outputSeries.output.list[0].data, 1)).to.eql([ - -165.1415926535, - -136, - 19.561, - -2.3424234999999998, - ]); - }); - - it('it subtracts a number', async () => { - const outputSeries = await invoke(fn, [seriesList, 2]); - expect(_.map(outputSeries.output.list[1].data, 1)).to.eql([98, 48, 48, 18]); - }); - - it('it subtracts an array of numbers', async () => { - const outputSeries = await invoke(fn, [seriesList, [5, 10, 15]]); - expect(_.map(outputSeries.output.list[1].data, 1)).to.eql([70, 20, 20, -10]); - }); - - it('it subtracts a seriesList with one series', async () => { - const seriesListWithOneSeries = { - type: 'seriesList', - list: [_.cloneDeep(seriesList.list[1])], - }; - const outputSeries = await invoke(fn, [seriesList, seriesListWithOneSeries]); - expect(_.map(outputSeries.output.list[1].data, 1)).to.eql([0, 0, 0, 0]); - }); - - it('it subtracts a seriesList with multiple series', async () => { - const outputSeries = await invoke(fn, [seriesList, seriesList]); - expect(_.map(outputSeries.output.list[0].data, 1)).to.eql([0, 0, 0, 0]); - expect(_.map(outputSeries.output.list[1].data, 1)).to.eql([0, 0, 0, 0]); - expect(_.map(outputSeries.output.list[2].data, 1)).to.eql([0, 0, 0, 0]); - expect(_.map(outputSeries.output.list[3].data, 1)).to.eql([0, 0, 0, 0]); - expect(_.map(outputSeries.output.list[4].data, 1)).to.eql([0, 0, 0, 0]); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/sum.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/sum.js deleted file mode 100644 index 61e3a254d0b5de..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/sum.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../sum`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('sum.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('it adds a number', () => { - return invoke(fn, [seriesList, 2]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([102, 52, 52, 22]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/title.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/title.js deleted file mode 100644 index 973bb2ed0ea32d..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/title.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../title`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('title.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('sets the title property', () => { - return invoke(fn, [seriesList, 'beer']).then(r => { - _.each(r.output.list, series => expect(series._title).to.equal('beer')); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/trim.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/trim.js deleted file mode 100644 index ed7a8999d706a7..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/trim.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../trim`); - -import _ from 'lodash'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('trim.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('Sets the first and last values to null by default', () => { - return invoke(fn, [seriesList]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([null, 50, 50, null]); - }); - }); - - it('Trims more from the beginning', () => { - return invoke(fn, [seriesList, 2]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([null, null, 50, null]); - }); - }); - - it('Trims more from the end', () => { - return invoke(fn, [seriesList, null, 2]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([null, 50, null, null]); - }); - }); - - it('Trims nothing from the end', () => { - return invoke(fn, [seriesList, 1, 0]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([null, 50, 50, 20]); - }); - }); - - it('Trims nothing from the beginning', () => { - return invoke(fn, [seriesList, 0, 2]).then(r => { - expect(_.map(r.output.list[1].data, 1)).to.eql([100, 50, null, null]); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/yaxis.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/yaxis.js deleted file mode 100644 index 9210a2cd300b09..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/yaxis.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fn = require(`../yaxis`); -import Bluebird from 'bluebird'; -const expect = require('chai').expect; -import invoke from './helpers/invoke_series_fn.js'; - -describe('yaxis.js', () => { - let seriesList; - beforeEach(() => { - seriesList = require('./fixtures/seriesList.js')(); - }); - - it('creates the yaxes array', () => { - expect(seriesList._global).to.equal(undefined); - return invoke(fn, [seriesList, 2]).then(r => { - expect(r.output.list[0]._global.yaxes).to.be.an('array'); - }); - }); - - it('puts odd numbers of the left, even on the right, by default', () => { - return Bluebird.all([ - invoke(fn, [seriesList, 1]).then(r => { - expect(r.output.list[0]._global.yaxes[0].position).to.equal('left'); - }), - invoke(fn, [seriesList, 2]).then(r => { - expect(r.output.list[0]._global.yaxes[1].position).to.equal('right'); - }), - invoke(fn, [seriesList, 3]).then(r => { - expect(r.output.list[0]._global.yaxes[2].position).to.equal('left'); - }), - ]); - }); - - it('it lets you override default positions', () => { - return Bluebird.all([ - invoke(fn, [seriesList, 1, null, null, 'right']).then(r => { - expect(r.output.list[0]._global.yaxes[0].position).to.equal('right'); - }), - invoke(fn, [seriesList, 2, null, null, 'right']).then(r => { - expect(r.output.list[0]._global.yaxes[1].position).to.equal('right'); - }), - ]); - }); - - it('sets the minimum (default: no min)', () => { - return Bluebird.all([ - invoke(fn, [seriesList, 1, null]).then(r => { - expect(r.output.list[0]._global.yaxes[0].min).to.equal(null); - }), - invoke(fn, [seriesList, 2, 10]).then(r => { - expect(r.output.list[0]._global.yaxes[1].min).to.equal(10); - }), - ]); - }); - - it('sets the max (default: no max)', () => { - return Bluebird.all([ - invoke(fn, [seriesList, 1, null]).then(r => { - expect(r.output.list[0]._global.yaxes[0].max).to.equal(undefined); - }), - invoke(fn, [seriesList, 2, null, 10]).then(r => { - expect(r.output.list[0]._global.yaxes[1].max).to.equal(10); - }), - ]); - }); - - it('sets the units (default: no unit', () => { - return Bluebird.all([ - invoke(fn, [seriesList, 1, null, null, null, null, null, null]).then(r => { - expect(r.output.list[0]._global.yaxes[0].units).to.equal(undefined); - }), - invoke(fn, [seriesList, 2, null, null, null, null, null, 'bits']).then(r => { - expect(r.output.list[0]._global.yaxes[1].units).to.be.an('object'); - }), - ]); - }); - - it('throws an error if currency is not three letter code', () => { - invoke(fn, [seriesList, 1, null, null, null, null, null, 'currency:abcde']).catch(e => { - expect(e).to.be.an.instanceof(Error); - }); - invoke(fn, [seriesList, 1, null, null, null, null, null, 'currency:12']).catch(e => { - expect(e).to.be.an.instanceof(Error); - }); - invoke(fn, [seriesList, 1, null, null, null, null, null, 'currency:$#']).catch(e => { - expect(e).to.be.an.instanceof(Error); - }); - invoke(fn, [seriesList, 1, null, null, null, null, null, 'currency:ab']).catch(e => { - expect(e).to.be.an.instanceof(Error); - }); - }); -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/es/index.js b/src/legacy/core_plugins/timelion/server/series_functions/es/index.js deleted file mode 100644 index 4ce2752fbf9be3..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/es/index.js +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { first, map } from 'rxjs/operators'; -import { i18n } from '@kbn/i18n'; -import _ from 'lodash'; -import Datasource from '../../lib/classes/datasource'; -import buildRequest from './lib/build_request'; -import toSeriesList from './lib/agg_response_to_series_list'; - -export default new Datasource('es', { - args: [ - { - name: 'q', - types: ['string', 'null'], - multi: true, - help: i18n.translate('timelion.help.functions.es.args.qHelpText', { - defaultMessage: 'Query in lucene query string syntax', - }), - }, - { - name: 'metric', - types: ['string', 'null'], - multi: true, - help: i18n.translate('timelion.help.functions.es.args.metricHelpText', { - defaultMessage: - 'An elasticsearch metric agg: avg, sum, min, max, percentiles or cardinality, followed by a field. ' + - 'E.g., "sum:bytes", "percentiles:bytes:95,99,99.9" or just "count"', - description: - `avg, sum, min, max, percentiles and cardinality are keywords in the expression ` + - `and must not be translated. Also don't translate the examples.`, - }), - }, - { - name: 'split', - types: ['string', 'null'], - multi: true, - help: i18n.translate('timelion.help.functions.es.args.splitHelpText', { - defaultMessage: - 'An elasticsearch field to split the series on and a limit. E.g., "{hostnameSplitArg}" to get the top 10 hostnames', - values: { - hostnameSplitArg: 'hostname:10', - }, - }), - }, - { - name: 'index', - types: ['string', 'null'], - help: i18n.translate('timelion.help.functions.es.args.indexHelpText', { - defaultMessage: - 'Index to query, wildcards accepted. Provide Index Pattern name for scripted fields and ' + - 'field name type ahead suggestions for metrics, split, and timefield arguments.', - description: - '"metrics", "split" and "timefield" are referring to parameter names and should not be translated.', - }), - }, - { - name: 'timefield', - types: ['string', 'null'], - help: i18n.translate('timelion.help.functions.es.args.timefieldHelpText', { - defaultMessage: 'Field of type "date" to use for x-axis', - description: '"date" is a field type and should not be translated.', - }), - }, - { - name: 'kibana', - types: ['boolean', 'null'], - help: i18n.translate('timelion.help.functions.es.args.kibanaHelpText', { - defaultMessage: - 'Respect filters on Kibana dashboards. Only has an effect when using on Kibana dashboards', - }), - }, - { - name: 'interval', // You really shouldn't use this, use the interval picker instead - types: ['string', 'null'], - help: i18n.translate('timelion.help.functions.es.args.intervalHelpText', { - defaultMessage: `**DO NOT USE THIS**. It's fun for debugging fit functions, but you really should use the interval picker`, - }), - }, - ], - help: i18n.translate('timelion.help.functions.esHelpText', { - defaultMessage: 'Pull data from an elasticsearch instance', - }), - aliases: ['elasticsearch'], - fn: async function esFn(args, tlConfig) { - const config = _.defaults(_.clone(args.byName), { - q: '*', - metric: ['count'], - index: tlConfig.settings['timelion:es.default_index'], - timefield: tlConfig.settings['timelion:es.timefield'], - interval: tlConfig.time.interval, - kibana: true, - fit: 'nearest', - }); - - const findResp = await tlConfig.request.getSavedObjectsClient().find({ - type: 'index-pattern', - fields: ['title', 'fields'], - search: `"${config.index}"`, - search_fields: ['title'], - }); - const indexPatternSavedObject = findResp.saved_objects.find(savedObject => { - return savedObject.attributes.title === config.index; - }); - let scriptedFields = []; - if (indexPatternSavedObject) { - const fields = JSON.parse(indexPatternSavedObject.attributes.fields); - scriptedFields = fields.filter(field => { - return field.scripted; - }); - } - - const esShardTimeout = await tlConfig.server.newPlatform.__internals.elasticsearch.legacy.config$ - .pipe( - first(), - map(config => config.shardTimeout.asMilliseconds()) - ) - .toPromise(); - - const body = buildRequest(config, tlConfig, scriptedFields, esShardTimeout); - - const { callWithRequest } = tlConfig.server.plugins.elasticsearch.getCluster('data'); - const resp = await callWithRequest(tlConfig.request, 'search', body); - if (!resp._shards.total) { - throw new Error( - i18n.translate('timelion.serverSideErrors.esFunction.indexNotFoundErrorMessage', { - defaultMessage: 'Elasticsearch index not found: {index}', - values: { - index: config.index, - }, - }) - ); - } - return { - type: 'seriesList', - list: toSeriesList(resp.aggregations, config), - }; - }, -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/graphite.js b/src/legacy/core_plugins/timelion/server/series_functions/graphite.js deleted file mode 100644 index a80dd2f3ff29e7..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/graphite.js +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import _ from 'lodash'; -import fetch from 'node-fetch'; -import moment from 'moment'; -import Datasource from '../lib/classes/datasource'; - -export default new Datasource('graphite', { - args: [ - { - name: 'metric', // _test-data.users.*.data - types: ['string'], - help: i18n.translate('timelion.help.functions.graphite.args.metricHelpText', { - defaultMessage: 'Graphite metric to pull, e.g., {metricExample}', - values: { - metricExample: '_test-data.users.*.data', - }, - }), - }, - ], - help: i18n.translate('timelion.help.functions.graphiteHelpText', { - defaultMessage: `[experimental] Pull data from graphite. Configure your graphite server in Kibana's Advanced Settings`, - }), - fn: function graphite(args, tlConfig) { - const config = args.byName; - - const time = { - min: moment(tlConfig.time.from).format('HH:mm[_]YYYYMMDD'), - max: moment(tlConfig.time.to).format('HH:mm[_]YYYYMMDD'), - }; - const allowedUrls = tlConfig.server.config().get('timelion.graphiteUrls'); - const configuredUrl = tlConfig.settings['timelion:graphite.url']; - if (!allowedUrls.includes(configuredUrl)) { - throw new Error( - i18n.translate('timelion.help.functions.notAllowedGraphiteUrl', { - defaultMessage: `This graphite URL is not configured on the kibana.yml file. - Please configure your graphite server list in the kibana.yml file under 'timelion.graphiteUrls' and - select one from Kibana's Advanced Settings`, - }) - ); - } - - const URL = - tlConfig.settings['timelion:graphite.url'] + - '/render/' + - '?format=json' + - '&from=' + - time.min + - '&until=' + - time.max + - '&target=' + - config.metric; - - return fetch(URL) - .then(function(resp) { - return resp.json(); - }) - .then(function(resp) { - const list = _.map(resp, function(series) { - const data = _.map(series.datapoints, function(point) { - return [point[1] * 1000, point[0]]; - }); - return { - data: data, - type: 'series', - fit: 'nearest', // TODO make this customizable - label: series.target, - }; - }); - - return { - type: 'seriesList', - list: list, - }; - }) - .catch(function(e) { - throw e; - }); - }, -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/holt/index.js b/src/legacy/core_plugins/timelion/server/series_functions/holt/index.js deleted file mode 100644 index 0cc41df933e8c8..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/holt/index.js +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import _ from 'lodash'; -import Chainable from '../../lib/classes/chainable'; -import ses from './lib/ses'; -import des from './lib/des'; -import tes from './lib/tes'; -import { toMS } from '../../../../vis_type_timelion/common/lib'; - -export default new Chainable('holt', { - args: [ - { - name: 'inputSeries', - types: ['seriesList'], - }, - { - name: 'alpha', - types: ['number'], - help: i18n.translate('timelion.help.functions.holt.args.alphaHelpText', { - defaultMessage: ` - Smoothing weight from 0 to 1. - Increasing alpha will make the new series more closely follow the original. - Lowering it will make the series smoother`, - }), - }, - { - name: 'beta', - types: ['number'], - help: i18n.translate('timelion.help.functions.holt.args.betaHelpText', { - defaultMessage: ` - Trending weight from 0 to 1. - Increasing beta will make rising/falling lines continue to rise/fall longer. - Lowering it will make the function learn the new trend faster`, - }), - }, - { - name: 'gamma', - types: ['number'], - help: i18n.translate('timelion.help.functions.holt.args.gammaHelpText', { - defaultMessage: ` - Seasonal weight from 0 to 1. Does your data look like a wave? - Increasing this will give recent seasons more importance, thus changing the wave form faster. - Lowering it will reduce the importance of new seasons, making history more important. - `, - }), - }, - { - name: 'season', - types: ['string'], - help: i18n.translate('timelion.help.functions.holt.args.seasonHelpText', { - defaultMessage: - 'How long is the season, e.g., 1w if your pattern repeats weekly. (Only useful with gamma)', - description: - '"1w" is an expression value and should not be translated. "gamma" is a parameter name and should not be translated.', - }), - }, - { - name: 'sample', - types: ['number', 'null'], - help: i18n.translate('timelion.help.functions.holt.args.sampleHelpText', { - defaultMessage: ` - The number of seasons to sample before starting to "predict" in a seasonal series. - (Only useful with gamma, Default: all)`, - description: '"gamma" and "all" are parameter names and values and must not be translated.', - }), - }, - ], - help: i18n.translate('timelion.help.functions.holtHelpText', { - defaultMessage: ` - Sample the beginning of a series and use it to forecast what should happen - via several optional parameters. In general, this doesn't really predict the - future, but predicts what should be happening right now according to past data, - which can be useful for anomaly detection. Note that nulls will be filled with forecasted values.`, - description: '"null" is a data value here and must not be translated.', - }), - fn: function expsmoothFn(args, tlConfig) { - const newSeries = _.cloneDeep(args.byName.inputSeries); - - const alpha = args.byName.alpha; - const beta = args.byName.beta; - const gamma = args.byName.gamma; - - _.each(newSeries.list, function(series) { - const sample = args.byName.sample || series.data.length; // If we use length it should simply never predict - - // Single exponential smoothing - // This is basically a weighted moving average in which the older - // points exponentially degrade relative to the alpha, e.g.: - // 0.8^1, 0.8^2, 0.8^3, etc - - const times = _.map(series.data, 0); - let points = _.map(series.data, 1); - - if (alpha != null && beta == null && gamma == null) { - points = ses(points, alpha); - } - - if (alpha != null && beta != null && gamma == null) { - points = des(points, alpha, beta); - } - - if (alpha != null && beta != null && gamma != null) { - if (!sample || !args.byName.season || sample < 2) { - throw new Error( - i18n.translate('timelion.serverSideErrors.holtFunction.missingParamsErrorMessage', { - defaultMessage: 'Must specify a season length and a sample size >= 2', - }) - ); - } - const season = Math.round(toMS(args.byName.season) / toMS(tlConfig.time.interval)); - points = tes(points, alpha, beta, gamma, season, sample); - } - - _.assign(series.data, _.zip(times, points)); - }); - - return newSeries; - }, -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/legend.js b/src/legacy/core_plugins/timelion/server/series_functions/legend.js deleted file mode 100644 index fd9ff53a1391f9..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/legend.js +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import alter from '../lib/alter.js'; -import Chainable from '../lib/classes/chainable'; -import { DEFAULT_TIME_FORMAT } from '../../../vis_type_timelion/common/lib'; - -export default new Chainable('legend', { - args: [ - { - name: 'inputSeries', - types: ['seriesList'], - }, - { - name: 'position', - types: ['string', 'boolean', 'null'], - help: i18n.translate('timelion.help.functions.legend.args.positionHelpText', { - defaultMessage: - 'Corner to place the legend in: nw, ne, se, or sw. You can also pass false to disable the legend', - description: '"nw", "ne", "se", "sw" and "false" are keywords and must not be translated.', - }), - suggestions: [ - { - name: 'false', - help: i18n.translate( - 'timelion.help.functions.legend.args.position.suggestions.falseHelpText', - { - defaultMessage: 'disable legend', - } - ), - }, - { - name: 'nw', - help: i18n.translate( - 'timelion.help.functions.legend.args.position.suggestions.nwHelpText', - { - defaultMessage: 'place legend in north west corner', - } - ), - }, - { - name: 'ne', - help: i18n.translate( - 'timelion.help.functions.legend.args.position.suggestions.neHelpText', - { - defaultMessage: 'place legend in north east corner', - } - ), - }, - { - name: 'se', - help: i18n.translate( - 'timelion.help.functions.legend.args.position.suggestions.seHelpText', - { - defaultMessage: 'place legend in south east corner', - } - ), - }, - { - name: 'sw', - help: i18n.translate( - 'timelion.help.functions.legend.args.position.suggestions.swHelpText', - { - defaultMessage: 'place legend in south west corner', - } - ), - }, - ], - }, - { - name: 'columns', - types: ['number', 'null'], - help: i18n.translate('timelion.help.functions.legend.args.columnsHelpText', { - defaultMessage: 'Number of columns to divide the legend into', - }), - }, - { - name: 'showTime', - types: ['boolean'], - help: i18n.translate('timelion.help.functions.legend.args.showTimeHelpText', { - defaultMessage: 'Show time value in legend when hovering over graph. Default: true', - }), - }, - { - name: 'timeFormat', - types: ['string'], - help: i18n.translate('timelion.help.functions.legend.args.timeFormatHelpText', { - defaultMessage: 'moment.js format pattern. Default: {defaultTimeFormat}', - values: { - defaultTimeFormat: DEFAULT_TIME_FORMAT, - }, - }), - }, - ], - help: i18n.translate('timelion.help.functions.legendHelpText', { - defaultMessage: 'Set the position and style of the legend on the plot', - }), - fn: function legendFn(args) { - return alter(args, function( - eachSeries, - position, - columns, - showTime = true, - timeFormat = DEFAULT_TIME_FORMAT - ) { - eachSeries._global = eachSeries._global || {}; - eachSeries._global.legend = eachSeries._global.legend || {}; - eachSeries._global.legend.noColumns = columns; - eachSeries._global.legend.showTime = showTime; - eachSeries._global.legend.timeFormat = timeFormat; - - if (position === false) { - eachSeries._global.legend.show = false; - eachSeries._global.legend.showTime = false; - } else { - eachSeries._global.legend.position = position; - } - - return eachSeries; - }); - }, -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/movingaverage.js b/src/legacy/core_plugins/timelion/server/series_functions/movingaverage.js deleted file mode 100644 index a4b458991c1bc0..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/movingaverage.js +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import alter from '../lib/alter.js'; -import _ from 'lodash'; -import Chainable from '../lib/classes/chainable'; -import { toMS } from '../../../vis_type_timelion/common/lib'; - -const validPositions = ['left', 'right', 'center']; -const defaultPosition = 'center'; - -export default new Chainable('movingaverage', { - args: [ - { - name: 'inputSeries', - types: ['seriesList'], - }, - { - name: 'window', - types: ['number', 'string'], - help: i18n.translate('timelion.help.functions.movingaverage.args.windowHelpText', { - defaultMessage: - 'Number of points, or a date math expression (eg 1d, 1M) to average over. If a date math expression ' + - 'is specified, the function will get as close as possible given the currently select interval. ' + - 'If the date math expression is not evenly divisible by the interval the results may appear abnormal.', - }), - }, - { - name: 'position', - types: ['string', 'null'], - help: i18n.translate('timelion.help.functions.movingaverage.args.positionHelpText', { - defaultMessage: - 'Position of the averaged points relative to the result time. One of: {validPositions}', - values: { - validPositions: validPositions.join(', '), - }, - }), - suggestions: validPositions.map(position => { - const suggestion = { name: position }; - if (position === defaultPosition) { - suggestion.help = 'default'; - } - return suggestion; - }), - }, - ], - aliases: ['mvavg'], - help: i18n.translate('timelion.help.functions.movingaverageHelpText', { - defaultMessage: - 'Calculate the moving average over a given window. Nice for smoothing noisy series', - }), - fn: function movingaverageFn(args, tlConfig) { - return alter(args, function(eachSeries, _window, _position) { - // _window always needs to be a number, if isn't we have to make it into one. - if (typeof _window !== 'number') { - // Ok, I guess its a datemath expression - const windowMilliseconds = toMS(_window); - - // calculate how many buckets that _window represents - const intervalMilliseconds = toMS(tlConfig.time.interval); - - // Round, floor, ceil? We're going with round because it splits the difference. - _window = Math.round(windowMilliseconds / intervalMilliseconds) || 1; - } - - _position = _position || defaultPosition; - if (!_.contains(validPositions, _position)) { - throw new Error( - i18n.translate( - 'timelion.serverSideErrors.movingaverageFunction.notValidPositionErrorMessage', - { - defaultMessage: 'Valid positions are: {validPositions}', - values: { - validPositions: validPositions.join(', '), - }, - } - ) - ); - } - - const pairs = eachSeries.data; - const pairsLen = pairs.length; - eachSeries.label = eachSeries.label + ' mvavg=' + _window; - - function toPoint(point, pairSlice) { - const average = - _.chain(pairSlice) - .map(1) - .reduce(function(memo, num) { - return memo + num; - }) - .value() / _window; - - return [point[0], average]; - } - - if (_position === 'center') { - const windowLeft = Math.floor(_window / 2); - const windowRight = _window - windowLeft; - eachSeries.data = _.map(pairs, function(point, i) { - if (i < windowLeft || i > pairsLen - windowRight) return [point[0], null]; - return toPoint(point, pairs.slice(i - windowLeft, i + windowRight)); - }); - } else if (_position === 'left') { - eachSeries.data = _.map(pairs, function(point, i) { - const cursor = i + 1; - if (cursor < _window) return [point[0], null]; - return toPoint(point, pairs.slice(cursor - _window, cursor)); - }); - } else if (_position === 'right') { - eachSeries.data = _.map(pairs, function(point, i) { - if (i > pairsLen - _window) return [point[0], null]; - return toPoint(point, pairs.slice(i, i + _window)); - }); - } - - return eachSeries; - }); - }, -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/quandl.js b/src/legacy/core_plugins/timelion/server/series_functions/quandl.js deleted file mode 100644 index fd7de05464da33..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/quandl.js +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import _ from 'lodash'; -import fetch from 'node-fetch'; -import moment from 'moment'; -fetch.Promise = require('bluebird'); - -import Datasource from '../lib/classes/datasource'; - -export default new Datasource('quandl', { - dataSource: true, - args: [ - { - name: 'code', - types: ['string', 'null'], - help: i18n.translate('timelion.help.functions.quandl.args.codeHelpText', { - defaultMessage: 'The quandl code to plot. You can find these on quandl.com.', - }), - }, - { - name: 'position', - types: ['number', 'null'], - help: i18n.translate('timelion.help.functions.quandl.args.positionHelpText', { - defaultMessage: - 'Some quandl sources return multiple series, which one should I use? 1 based index.', - }), - }, - ], - help: i18n.translate('timelion.help.functions.quandlHelpText', { - defaultMessage: ` - [experimental] - Pull data from quandl.com using the quandl code. Set {quandlKeyField} to your free API key in Kibana's - Advanced Settings. The API has a really low rate limit without a key.`, - values: { - quandlKeyField: '"timelion:quandl.key"', - }, - }), - fn: function quandlFn(args, tlConfig) { - const intervalMap = { - '1d': 'daily', - '1w': 'weekly', - '1M': 'monthly', - '1y': 'annual', - }; - - const config = _.defaults(args.byName, { - code: 'WIKI/AAPL', - position: 1, - interval: intervalMap[tlConfig.time.interval], - apikey: tlConfig.settings['timelion:quandl.key'], - }); - - if (!config.interval) { - throw new Error( - i18n.translate('timelion.serverSideErrors.quandlFunction.unsupportedIntervalErrorMessage', { - defaultMessage: - 'quandl() unsupported interval: {interval}. quandl() supports: {intervals}', - values: { - interval: tlConfig.time.interval, - intervals: _.keys(intervalMap).join(', '), - }, - }) - ); - } - - const time = { - min: moment.utc(tlConfig.time.from).format('YYYY-MM-DD'), - max: moment.utc(tlConfig.time.to).format('YYYY-MM-DD'), - }; - - // POSITIONS - // 1. open - // 2. high - // 3. low - // 4. close - // 5. volume - - const URL = - 'https://www.quandl.com/api/v1/datasets/' + - config.code + - '.json' + - '?sort_order=asc' + - '&trim_start=' + - time.min + - '&trim_end=' + - time.max + - '&collapse=' + - config.interval + - '&auth_token=' + - config.apikey; - - return fetch(URL) - .then(function(resp) { - return resp.json(); - }) - .then(function(resp) { - const data = _.map(resp.data, function(bucket) { - return [moment(bucket[0]).valueOf(), bucket[config.position]]; - }); - - return { - type: 'seriesList', - list: [ - { - data: data, - type: 'series', - fit: 'nearest', - label: resp.name, - }, - ], - }; - }) - .catch(function(e) { - throw e; - }); - }, -}); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/scale_interval.js b/src/legacy/core_plugins/timelion/server/series_functions/scale_interval.js deleted file mode 100644 index b604015624dfd6..00000000000000 --- a/src/legacy/core_plugins/timelion/server/series_functions/scale_interval.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import alter from '../lib/alter.js'; -import { toMS } from '../../../vis_type_timelion/common/lib'; -import _ from 'lodash'; -import Chainable from '../lib/classes/chainable'; - -export default new Chainable('scale_interval', { - args: [ - { - name: 'inputSeries', - types: ['seriesList'], - }, - { - name: 'interval', - types: ['string'], - help: i18n.translate('timelion.help.functions.scaleInterval.args.intervalHelpText', { - defaultMessage: - 'The new interval in date math notation, e.g., 1s for 1 second. 1m, 5m, 1M, 1w, 1y, etc.', - }), - }, - ], - help: i18n.translate('timelion.help.functions.scaleIntervalHelpText', { - defaultMessage: - 'Changes scales a value (usually a sum or a count) to a new interval. For example, as a per-second rate', - }), - fn: function scaleIntervalFn(args, tlConfig) { - const currentInterval = toMS(tlConfig.time.interval); - const scaleInterval = toMS(args.byName.interval); - - return alter(args, function(eachSeries) { - const data = _.map(eachSeries.data, function(point) { - return [point[0], (point[1] / currentInterval) * scaleInterval]; - }); - eachSeries.data = data; - return eachSeries; - }); - }, -}); diff --git a/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx b/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx index 125577815c207b..18852b549b1ed0 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx +++ b/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx @@ -22,7 +22,7 @@ import { EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { VisOptionsProps } from 'ui/vis/editors/default'; -import { RangeOption, SwitchOption } from '../../vis_type_vislib/public/components'; +import { RangeOption, SwitchOption } from '../../vis_type_vislib/public'; import { MarkdownVisParams } from './types'; function SettingsOptions({ stateParams, setValue }: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.tsx b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.tsx index f8398f5c83146c..3a6d60a89e6106 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.tsx +++ b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.tsx @@ -24,7 +24,7 @@ import { isColorDark } from '@elastic/eui'; import { getHeatmapColors, getFormat, Vis } from '../legacy_imports'; import { MetricVisValue } from './metric_vis_value'; -import { FieldFormat, ContentType } from '../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../plugins/data/public'; import { Context } from '../metric_vis_fn'; import { KibanaDatatable } from '../../../../../plugins/expressions/public'; import { VisParams, MetricVisMetric } from '../types'; @@ -100,9 +100,9 @@ export class MetricVisComponent extends Component { } private getFormattedValue = ( - fieldFormatter: FieldFormat, + fieldFormatter: fieldFormats.FieldFormat, value: any, - format: ContentType = 'text' + format: fieldFormats.ContentType = 'text' ) => { if (isNaN(value)) return '-'; return fieldFormatter.convert(value, format); @@ -119,7 +119,7 @@ export class MetricVisComponent extends Component { const metrics: MetricVisMetric[] = []; let bucketColumnId: string; - let bucketFormatter: FieldFormat; + let bucketFormatter: fieldFormats.FieldFormat; if (dimensions.bucket) { bucketColumnId = table.columns[dimensions.bucket.accessor].id; diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx index 032f66d92624cc..e144c055d80238 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx +++ b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx @@ -31,13 +31,13 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { VisOptionsProps } from '../legacy_imports'; import { + ColorModes, ColorRanges, ColorSchemaOptions, SwitchOption, RangeOption, SetColorSchemaOptionsValue, -} from '../../../vis_type_vislib/public/components'; -import { ColorModes } from '../../../vis_type_vislib/public/utils/collections'; +} from '../../../vis_type_vislib/public'; import { MetricVisParam, VisParams } from '../types'; import { SetColorRangeValue } from '../../../vis_type_vislib/public/components/common/color_ranges'; diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts index 45110ca1130030..4ebd8bf97c55a0 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts @@ -27,7 +27,7 @@ import { Render, Style, } from '../../../../plugins/expressions/public'; -import { ColorModes } from '../../vis_type_vislib/public/utils/collections'; +import { ColorModes } from '../../vis_type_vislib/public'; import { visType, DimensionsVisParam, VisParams } from './types'; export type Context = KibanaDatatable; diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts index 649959054416c7..c2b7e6da3f7bd9 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts @@ -24,7 +24,7 @@ import { npStart } from 'ui/new_platform'; import getStubIndexPattern from 'fixtures/stubbed_logstash_index_pattern'; import { Vis } from '../../visualizations/public'; -import { UrlFormat } from '../../../../plugins/data/public'; +import { fieldFormats } from '../../../../plugins/data/public'; import { setup as visualizationsSetup, start as visualizationsStart, @@ -39,7 +39,7 @@ describe('metric_vis - createMetricVisTypeDefinition', () => { beforeAll(() => { visualizationsSetup.types.createReactVisualization(metricVisTypeDefinition); (npStart.plugins.data.fieldFormats.getType as jest.Mock).mockImplementation(() => { - return UrlFormat; + return fieldFormats.UrlFormat; }); }); diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts index 0d9019ee0579c1..ee7ead0b7331b4 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts @@ -21,8 +21,8 @@ import { i18n } from '@kbn/i18n'; import { MetricVisComponent } from './components/metric_vis_component'; import { MetricVisOptions } from './components/metric_vis_options'; +import { ColorModes } from '../../vis_type_vislib/public'; import { Schemas, AggGroupNames, colorSchemas, ColorSchemas } from './legacy_imports'; -import { ColorModes } from '../../vis_type_vislib/public/utils/collections'; export const metricVisTypeDefinition = { name: 'metric', diff --git a/src/legacy/core_plugins/vis_type_metric/public/types.ts b/src/legacy/core_plugins/vis_type_metric/public/types.ts index 71c1c12b4f8f02..34cb1b209a3aed 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/types.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/types.ts @@ -20,8 +20,7 @@ import { ColorSchemas } from './legacy_imports'; import { Range } from '../../../../plugins/expressions/public'; import { SchemaConfig } from '../../visualizations/public'; -import { ColorModes } from '../../vis_type_vislib/public/utils/collections'; -import { Labels, Style } from '../../vis_type_vislib/public/types'; +import { ColorModes, Labels, Style } from '../../vis_type_vislib/public'; export const visType = 'metric'; diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js index 0e85ae2f0d452a..fc5a24a66dab3d 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js @@ -23,7 +23,7 @@ import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; import sinon from 'sinon'; -import { legacyResponseHandlerProvider, tabifyAggResponse, npStart } from '../../legacy_imports'; +import { tabifyAggResponse, npStart } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { round } from 'lodash'; @@ -32,13 +32,13 @@ import { tableVisTypeDefinition } from '../../table_vis_type'; import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy'; import { getAngularModule } from '../../get_inner_angular'; import { initTableVisLegacyModule } from '../../table_vis_legacy_module'; +import { tableVisResponseHandler } from '../../table_vis_response_handler'; describe('Table Vis - AggTable Directive', function() { let $rootScope; let $compile; let indexPattern; let settings; - let tableAggResponse; const tabifiedData = {}; const init = () => { @@ -111,7 +111,6 @@ describe('Table Vis - AggTable Directive', function() { beforeEach(ngMock.module('kibana/table_vis')); beforeEach( ngMock.inject(function($injector, Private, config) { - tableAggResponse = legacyResponseHandlerProvider().handler; indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); settings = config; @@ -130,12 +129,12 @@ describe('Table Vis - AggTable Directive', function() { $scope.$destroy(); }); - it('renders a simple response properly', async function() { + it('renders a simple response properly', function() { $scope.dimensions = { metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], buckets: [], }; - $scope.table = (await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions)).tables[0]; + $scope.table = tableVisResponseHandler(tabifiedData.metricOnly, $scope.dimensions).tables[0]; const $el = $compile('')( $scope @@ -171,8 +170,9 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, params: {} }, ], }; - $scope.table = ( - await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions) + $scope.table = tableVisResponseHandler( + tabifiedData.threeTermBuckets, + $scope.dimensions ).tables[0]; const $el = $(''); $compile($el)($scope); @@ -237,7 +237,7 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, format: { id: 'number' } }, ], }; - const response = await tableAggResponse( + const response = tableVisResponseHandler( tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative, $scope.dimensions ); @@ -337,8 +337,9 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, params: {} }, ], }; - $scope.table = ( - await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions) + $scope.table = tableVisResponseHandler( + tabifiedData.threeTermBuckets, + $scope.dimensions ).tables[0]; const $el = $compile('')( @@ -394,8 +395,9 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, params: {} }, ], }; - $scope.table = ( - await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions) + $scope.table = tableVisResponseHandler( + tabifiedData.threeTermBuckets, + $scope.dimensions ).tables[0]; const $el = $compile('')( @@ -455,7 +457,7 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, format: { id: 'number' } }, ], }; - const response = await tableAggResponse( + const response = tableVisResponseHandler( tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative, $scope.dimensions ); diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js index da4f479554a2c0..3c633f21cbabb2 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js @@ -21,17 +21,17 @@ import $ from 'jquery'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; -import { legacyResponseHandlerProvider, tabifyAggResponse, npStart } from '../../legacy_imports'; +import { tabifyAggResponse, npStart } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { Vis } from '../../../../visualizations/public'; import { getAngularModule } from '../../get_inner_angular'; import { initTableVisLegacyModule } from '../../table_vis_legacy_module'; +import { tableVisResponseHandler } from '../../table_vis_response_handler'; describe('Table Vis - AggTableGroup Directive', function() { let $rootScope; let $compile; let indexPattern; - let tableAggResponse; const tabifiedData = {}; const init = () => { @@ -74,9 +74,7 @@ describe('Table Vis - AggTableGroup Directive', function() { visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition(legacyDependencies)); */ - tableAggResponse = legacyResponseHandlerProvider().handler; indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - $rootScope = $injector.get('$rootScope'); $compile = $injector.get('$compile'); @@ -92,12 +90,12 @@ describe('Table Vis - AggTableGroup Directive', function() { $scope.$destroy(); }); - it('renders a simple split response properly', async function() { + it('renders a simple split response properly', function() { $scope.dimensions = { metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], buckets: [], }; - $scope.group = await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions); + $scope.group = tableVisResponseHandler(tabifiedData.metricOnly, $scope.dimensions); $scope.sort = { columnIndex: null, direction: null, @@ -129,7 +127,7 @@ describe('Table Vis - AggTableGroup Directive', function() { expect($subTables.length).to.be(0); }); - it('renders a complex response properly', async function() { + it('renders a complex response properly', function() { $scope.dimensions = { splitRow: [{ accessor: 0, params: {} }], buckets: [ @@ -142,7 +140,7 @@ describe('Table Vis - AggTableGroup Directive', function() { { accessor: 5, params: {} }, ], }; - const group = ($scope.group = await tableAggResponse( + const group = ($scope.group = tableVisResponseHandler( tabifiedData.threeTermBuckets, $scope.dimensions )); diff --git a/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx b/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx index 33d7480de5a8e3..529439a8006823 100644 --- a/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx +++ b/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx @@ -24,11 +24,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { tabifyGetColumns, VisOptionsProps } from '../legacy_imports'; -import { - NumberInputOption, - SwitchOption, - SelectOption, -} from '../../../vis_type_vislib/public/components/common'; +import { NumberInputOption, SwitchOption, SelectOption } from '../../../vis_type_vislib/public'; import { TableVisParams } from '../types'; import { totalAggregations, isAggConfigNumeric } from './utils'; diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts index a372eced3e34b6..b3eb017c223082 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts @@ -23,9 +23,6 @@ export { AggConfig } from 'ui/vis'; export { AggGroupNames, VisOptionsProps } from 'ui/vis/editors/default'; // @ts-ignore export { Schemas } from 'ui/vis/editors/default/schemas'; -// @ts-ignore -export { legacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy'; - // @ts-ignore export { PrivateProvider } from 'ui/private/private'; // @ts-ignore diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts index 1f6600ea56a128..16181a3f70ff12 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -27,12 +27,7 @@ import './table_vis.mock'; import StubIndexPattern from 'test_utils/stub_index_pattern'; import { getAngularModule } from './get_inner_angular'; import { initTableVisLegacyModule } from './table_vis_legacy_module'; -import { - npStart, - legacyResponseHandlerProvider, - AggConfig, - tabifyAggResponse, -} from './legacy_imports'; +import { npStart, AggConfig, tabifyAggResponse } from './legacy_imports'; import { tableVisTypeDefinition } from './table_vis_type'; import { Vis } from '../../visualizations/public'; import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; @@ -40,6 +35,7 @@ import { setup as visualizationsSetup } from '../../visualizations/public/np_rea import { stubFields } from '../../../../plugins/data/public/stubs'; // eslint-disable-next-line import { setFieldFormats } from '../../../../plugins/data/public/services'; +import { tableVisResponseHandler } from './table_vis_response_handler'; interface TableVisScope extends IScope { [key: string]: any; @@ -97,7 +93,7 @@ describe('Table Vis - Controller', () => { angular.mock.inject((_$rootScope_: IRootScopeService, _$compile_: ICompileService) => { $rootScope = _$rootScope_; $compile = _$compile_; - tableAggResponse = legacyResponseHandlerProvider().handler; + tableAggResponse = tableVisResponseHandler; }) ); diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts index c1def9b55aae20..c8a4cade0efcbd 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts @@ -18,24 +18,16 @@ */ import { createTableVisFn } from './table_vis_fn'; +import { tableVisResponseHandler } from './table_vis_response_handler'; // eslint-disable-next-line import { functionWrapper } from '../../../../plugins/expressions/public/functions/tests/utils'; -jest.mock('./legacy_imports', () => { - const mockResponseHandler = jest.fn().mockReturnValue( - Promise.resolve({ - tables: [{ columns: [], rows: [] }], - }) - ); - - return { - mockResponseHandler, - legacyResponseHandlerProvider: () => ({ handler: mockResponseHandler }), - }; -}); - -const { mockResponseHandler } = jest.requireMock('./legacy_imports'); +jest.mock('./table_vis_response_handler', () => ({ + tableVisResponseHandler: jest.fn().mockReturnValue({ + tables: [{ columns: [], rows: [] }], + }), +})); describe('interpreter/functions#table', () => { const fn = functionWrapper(createTableVisFn); @@ -80,7 +72,7 @@ describe('interpreter/functions#table', () => { it('calls response handler with correct values', async () => { await fn(context, { visConfig: JSON.stringify(visConfig) }, undefined); - expect(mockResponseHandler).toHaveBeenCalledTimes(1); - expect(mockResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions); + expect(tableVisResponseHandler).toHaveBeenCalledTimes(1); + expect(tableVisResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions); }); }); diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.ts index ab775d90133e6f..67dd3b7c90335f 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.ts @@ -18,7 +18,7 @@ */ import { i18n } from '@kbn/i18n'; -import { tableVisResponseHandler } from './table_vis_request_handler'; +import { tableVisResponseHandler, TableContext } from './table_vis_response_handler'; import { ExpressionFunction, @@ -28,7 +28,7 @@ import { const name = 'kibana_table'; -type Context = KibanaDatatable; +export type Context = KibanaDatatable; interface Arguments { visConfig: string | null; @@ -37,7 +37,7 @@ interface Arguments { type VisParams = Required; interface RenderValue { - visData: Context; + visData: TableContext; visType: 'table'; visConfig: VisParams; params: { @@ -45,7 +45,7 @@ interface RenderValue { }; } -type Return = Promise>; +type Return = Render; export const createTableVisFn = (): ExpressionFunction< typeof name, @@ -68,9 +68,9 @@ export const createTableVisFn = (): ExpressionFunction< help: '', }, }, - async fn(context, args) { + fn(context, args) { const visConfig = args.visConfig && JSON.parse(args.visConfig); - const convertedData = await tableVisResponseHandler(context, visConfig.dimensions); + const convertedData = tableVisResponseHandler(context, visConfig.dimensions); return { type: 'render', diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_request_handler.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_request_handler.ts deleted file mode 100644 index 1a6d4600025f19..00000000000000 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_request_handler.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { legacyResponseHandlerProvider } from './legacy_imports'; - -export const tableVisResponseHandler = legacyResponseHandlerProvider().handler; diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_response_handler.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_response_handler.ts new file mode 100644 index 00000000000000..c835d5361fc141 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_response_handler.ts @@ -0,0 +1,101 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Required } from '@kbn/utility-types'; + +import { getFormat } from './legacy_imports'; +import { Context } from './table_vis_fn'; + +export interface TableContext { + tables: Array; + direction?: 'row' | 'column'; +} + +export interface TableGroup { + $parent: TableContext; + table: Context; + tables: Table[]; + title: string; + name: string; + key: any; + column: number; + row: number; +} + +export interface Table { + $parent?: TableGroup; + columns: Context['columns']; + rows: Context['rows']; +} + +export function tableVisResponseHandler(table: Context, dimensions: any): TableContext { + const converted: TableContext = { + tables: [], + }; + + const split = dimensions.splitColumn || dimensions.splitRow; + + if (split) { + converted.direction = dimensions.splitRow ? 'row' : 'column'; + const splitColumnIndex = split[0].accessor; + const splitColumnFormatter = getFormat(split[0].format); + const splitColumn = table.columns[splitColumnIndex]; + const splitMap = {}; + let splitIndex = 0; + + table.rows.forEach((row, rowIndex) => { + const splitValue: any = row[splitColumn.id]; + + if (!splitMap.hasOwnProperty(splitValue as any)) { + // @ts-ignore + splitMap[splitValue] = splitIndex++; + const tableGroup: Required = { + $parent: converted, + title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`, + name: splitColumn.name, + key: splitValue, + column: splitColumnIndex, + row: rowIndex, + table, + tables: [], + }; + + tableGroup.tables.push({ + $parent: tableGroup, + columns: table.columns, + rows: [], + }); + + converted.tables.push(tableGroup); + } + + // @ts-ignore + const tableIndex = splitMap[splitValue]; + // @ts-ignore + converted.tables[tableIndex].tables[0].rows.push(row); + }); + } else { + converted.tables.push({ + columns: table.columns, + rows: table.rows, + }); + } + + return converted; +} diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts index 5186b6cf59dfdd..970bf1ba7ce644 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts @@ -20,7 +20,7 @@ import { i18n } from '@kbn/i18n'; import { AggGroupNames, Schemas } from './legacy_imports'; import { Vis } from '../../visualizations/public'; -import { tableVisResponseHandler } from './table_vis_request_handler'; +import { tableVisResponseHandler } from './table_vis_response_handler'; // @ts-ignore import tableVisTemplate from './table_vis.html'; import { TableOptions } from './components/table_vis_options'; diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx index c500b5d888b053..76117c8b6b3987 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { ValidatedDualRange } from 'ui/validated_range'; import { VisOptionsProps } from 'ui/vis/editors/default'; -import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public/components'; +import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; import { TagCloudVisParams } from '../types'; function TagCloudOptions({ stateParams, setValue, vis }: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_timelion/README.md b/src/legacy/core_plugins/vis_type_timelion/README.md new file mode 100644 index 00000000000000..c306e03abf2c60 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_timelion/README.md @@ -0,0 +1,10 @@ +# Vis type Timelion + +# Generate a parser +If your grammar was changed in `public/chain.peg` you need to re-generate the static parser. You could use a grunt task: + +``` +grunt peg:timelion_chain +``` + +The generated parser will be appeared at `public/_generated_` folder, which is included in `.eslintignore` \ No newline at end of file diff --git a/src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js b/src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js new file mode 100644 index 00000000000000..f812b94238d43d --- /dev/null +++ b/src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js @@ -0,0 +1,1780 @@ +module.exports = (function() { + "use strict"; + + /* + * Generated by PEG.js 0.9.0. + * + * http://pegjs.org/ + */ + + function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + } + + function peg$SyntaxError(message, expected, found, location) { + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; + + if (typeof Error.captureStackTrace === "function") { + Error.captureStackTrace(this, peg$SyntaxError); + } + } + + peg$subclass(peg$SyntaxError, Error); + + function peg$parse(input) { + var options = arguments.length > 1 ? arguments[1] : {}, + parser = this, + + peg$FAILED = {}, + + peg$startRuleFunctions = { start: peg$parsestart }, + peg$startRuleFunction = peg$parsestart, + + peg$c0 = function(tree) { + return { + tree: tree.filter(function (o) {return o != null}), + functions: functions, + args: args, + variables: variables + } + }, + peg$c1 = ",", + peg$c2 = { type: "literal", value: ",", description: "\",\"" }, + peg$c3 = function(first, arg) {return arg}, + peg$c4 = function(first, rest) { + return [first].concat(rest); + }, + peg$c5 = "=", + peg$c6 = { type: "literal", value: "=", description: "\"=\"" }, + peg$c7 = function(name, value) { + var arg = { + type: 'namedArg', + name: name, + value: value, + location: simpleLocation(location()), + text: text() + }; + currentArgs.push(arg); + return arg; + }, + peg$c8 = function(value) { + var exception = { + type: 'incompleteArgument', + currentArgs: currentArgs, + currentFunction: currentFunction, + location: simpleLocation(location()), + text: text() + } + error(JSON.stringify(exception)); + }, + peg$c9 = function(name) { + var exception = { + type: 'incompleteArgumentValue', + currentArgs: currentArgs, + currentFunction: currentFunction, + name: name, + location: simpleLocation(location()), + text: text() + } + error(JSON.stringify(exception)); + }, + peg$c10 = function(element) {return element}, + peg$c11 = function(literal) { + var result = ltoo(literal); + result.location = simpleLocation(location()), + result.text = text(); + return result; + }, + peg$c12 = "$", + peg$c13 = { type: "literal", value: "$", description: "\"$\"" }, + peg$c14 = function(name) { + if (variables[name]) { + return variables[name]; + } else { + error('$' + name + ' is not defined') + } + }, + peg$c15 = function(name, value) { + variables[name] = value; + }, + peg$c16 = function(first, series) {return series}, + peg$c17 = function(first, rest) { + return [first].concat(rest) + }, + peg$c18 = /^[a-zA-Z]/, + peg$c19 = { type: "class", value: "[a-zA-Z]", description: "[a-zA-Z]" }, + peg$c20 = /^[.a-zA-Z0-9_\-]/, + peg$c21 = { type: "class", value: "[.a-zA-Z0-9_-]", description: "[.a-zA-Z0-9_-]" }, + peg$c22 = function(first, rest) { + currentFunction = first.join('') + rest.join(''); + currentArgs = []; + return currentFunction; + }, + peg$c23 = function(first, rest) { return first.join('') + rest.join('') }, + peg$c24 = { type: "other", description: "function" }, + peg$c25 = ".", + peg$c26 = { type: "literal", value: ".", description: "\".\"" }, + peg$c27 = "(", + peg$c28 = { type: "literal", value: "(", description: "\"(\"" }, + peg$c29 = ")", + peg$c30 = { type: "literal", value: ")", description: "\")\"" }, + peg$c31 = function(name, arg_list) { + var result = { + type: 'function', + function: name, + arguments: arg_list || [], + location: simpleLocation(location()), + text: text() + } + + result.arguments.forEach(function (arg) { + arg.function = name; + args.push(arg); + }) + + functions.push(result) + return result; + }, + peg$c32 = function(func) { + var exception = { + type: 'incompleteFunction', + function: func, + location: simpleLocation(location()), + text: text() + } + error(JSON.stringify(exception)); + }, + peg$c33 = "@", + peg$c34 = { type: "literal", value: "@", description: "\"@\"" }, + peg$c35 = ":", + peg$c36 = { type: "literal", value: ":", description: "\":\"" }, + peg$c37 = function(plot, series) { + return { + type: 'reference', + plot: plot, + series: series + } + }, + peg$c38 = function(plot) { + return { + type: 'reference', + plot: plot + } + }, + peg$c39 = function(func, rest) {return {type: 'chain', chain: [func].concat(rest)}}, + peg$c40 = function(grouped, functions) { + var first = { + type: 'chainList', + list: grouped + } + first.label = text(); + + return {type: "chain", chain: [first].concat(functions)}; + }, + peg$c41 = { type: "other", description: "literal" }, + peg$c42 = "\"", + peg$c43 = { type: "literal", value: "\"", description: "\"\\\"\"" }, + peg$c44 = function(chars) { return chars.join(''); }, + peg$c45 = "'", + peg$c46 = { type: "literal", value: "'", description: "\"'\"" }, + peg$c47 = "true", + peg$c48 = { type: "literal", value: "true", description: "\"true\"" }, + peg$c49 = function() { return true; }, + peg$c50 = "false", + peg$c51 = { type: "literal", value: "false", description: "\"false\"" }, + peg$c52 = function() { return false; }, + peg$c53 = "null", + peg$c54 = { type: "literal", value: "null", description: "\"null\"" }, + peg$c55 = function() { return null; }, + peg$c56 = /^[^()"',= \t]/, + peg$c57 = { type: "class", value: "[^()\"',=\\ \\t]", description: "[^()\"',=\\ \\t]" }, + peg$c58 = function(string) { // this also matches numbers via Number() + var result = string.join(''); + // Sort of hacky, but PEG doesn't have backtracking so + // a number rule is hard to read, and performs worse + if (isNaN(Number(result))) return result; + return Number(result) + }, + peg$c59 = /^[ \t\r\n]/, + peg$c60 = { type: "class", value: "[\\ \\t\\r\\n]", description: "[\\ \\t\\r\\n]" }, + peg$c61 = "\\", + peg$c62 = { type: "literal", value: "\\", description: "\"\\\\\"" }, + peg$c63 = function(sequence) { return sequence; }, + peg$c64 = /^[^"]/, + peg$c65 = { type: "class", value: "[^\"]", description: "[^\"]" }, + peg$c66 = /^[^']/, + peg$c67 = { type: "class", value: "[^']", description: "[^']" }, + peg$c68 = /^[0-9]/, + peg$c69 = { type: "class", value: "[0-9]", description: "[0-9]" }, + peg$c70 = function(digits) {return parseInt(digits.join(''))}, + + peg$currPos = 0, + peg$savedPos = 0, + peg$posDetailsCache = [{ line: 1, column: 1, seenCR: false }], + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$silentFails = 0, + + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$savedPos, peg$currPos); + } + + function location() { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description) { + throw peg$buildException( + null, + [{ type: "other", description: description }], + input.substring(peg$savedPos, peg$currPos), + peg$computeLocation(peg$savedPos, peg$currPos) + ); + } + + function error(message) { + throw peg$buildException( + message, + null, + input.substring(peg$savedPos, peg$currPos), + peg$computeLocation(peg$savedPos, peg$currPos) + ); + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos], + p, ch; + + if (details) { + return details; + } else { + p = pos - 1; + while (!peg$posDetailsCache[p]) { + p--; + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column, + seenCR: details.seenCR + }; + + while (p < pos) { + ch = input.charAt(p); + if (ch === "\n") { + if (!details.seenCR) { details.line++; } + details.column = 1; + details.seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + details.line++; + details.column = 1; + details.seenCR = true; + } else { + details.column++; + details.seenCR = false; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + return details; + } + } + + function peg$computeLocation(startPos, endPos) { + var startPosDetails = peg$computePosDetails(startPos), + endPosDetails = peg$computePosDetails(endPos); + + return { + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildException(message, expected, found, location) { + function cleanupExpected(expected) { + var i = 1; + + expected.sort(function(a, b) { + if (a.description < b.description) { + return -1; + } else if (a.description > b.description) { + return 1; + } else { + return 0; + } + }); + + while (i < expected.length) { + if (expected[i - 1] === expected[i]) { + expected.splice(i, 1); + } else { + i++; + } + } + } + + function buildMessage(expected, found) { + function stringEscape(s) { + function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } + + return s + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\x08/g, '\\b') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\f/g, '\\f') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) + .replace(/[\u0100-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) + .replace(/[\u1000-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); + } + + var expectedDescs = new Array(expected.length), + expectedDesc, foundDesc, i; + + for (i = 0; i < expected.length; i++) { + expectedDescs[i] = expected[i].description; + } + + expectedDesc = expected.length > 1 + ? expectedDescs.slice(0, -1).join(", ") + + " or " + + expectedDescs[expected.length - 1] + : expectedDescs[0]; + + foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; + + return "Expected " + expectedDesc + " but " + foundDesc + " found."; + } + + if (expected !== null) { + cleanupExpected(expected); + } + + return new peg$SyntaxError( + message !== null ? message : buildMessage(expected, found), + expected, + found, + location + ); + } + + function peg$parsestart() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$parsespace(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = peg$parseseries(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c0(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsearg_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseargument(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parsespace(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 44) { + s5 = peg$c1; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsespace(); + if (s6 === peg$FAILED) { + s6 = null; + } + if (s6 !== peg$FAILED) { + s7 = peg$parseargument(); + if (s7 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c3(s1, s7); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parsespace(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 44) { + s5 = peg$c1; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsespace(); + if (s6 === peg$FAILED) { + s6 = null; + } + if (s6 !== peg$FAILED) { + s7 = peg$parseargument(); + if (s7 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c3(s1, s7); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsespace(); + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 44) { + s4 = peg$c1; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c4(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseargument() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseargument_name(); + if (s1 !== peg$FAILED) { + s2 = peg$parsespace(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s3 = peg$c5; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parsespace(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + s5 = peg$parsearg_type(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c7(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsespace(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s2 = peg$c5; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsespace(); + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + s4 = peg$parsearg_type(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c8(s4); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseargument_name(); + if (s1 !== peg$FAILED) { + s2 = peg$parsespace(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s3 = peg$c5; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c9(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsearg_type(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c10(s1); + } + s0 = s1; + } + } + } + + return s0; + } + + function peg$parsearg_type() { + var s0, s1; + + s0 = peg$parsevariable_get(); + if (s0 === peg$FAILED) { + s0 = peg$parseseries_type(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseliteral(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c11(s1); + } + s0 = s1; + } + } + + return s0; + } + + function peg$parsevariable_get() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 36) { + s1 = peg$c12; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c13); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseargument_name(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c14(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsevariable_set() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 36) { + s1 = peg$c12; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c13); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseargument_name(); + if (s2 !== peg$FAILED) { + s3 = peg$parsespace(); + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s4 = peg$c5; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + if (s4 !== peg$FAILED) { + s5 = peg$parsespace(); + if (s5 === peg$FAILED) { + s5 = null; + } + if (s5 !== peg$FAILED) { + s6 = peg$parsearg_type(); + if (s6 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c15(s2, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseseries_type() { + var s0; + + s0 = peg$parsevariable_set(); + if (s0 === peg$FAILED) { + s0 = peg$parsevariable_get(); + if (s0 === peg$FAILED) { + s0 = peg$parsegroup(); + if (s0 === peg$FAILED) { + s0 = peg$parsechain(); + if (s0 === peg$FAILED) { + s0 = peg$parsereference(); + } + } + } + } + + return s0; + } + + function peg$parseseries() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseseries_type(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parsespace(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 44) { + s5 = peg$c1; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsespace(); + if (s6 === peg$FAILED) { + s6 = null; + } + if (s6 !== peg$FAILED) { + s7 = peg$parseseries_type(); + if (s7 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c16(s1, s7); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parsespace(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 44) { + s5 = peg$c1; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsespace(); + if (s6 === peg$FAILED) { + s6 = null; + } + if (s6 !== peg$FAILED) { + s7 = peg$parseseries_type(); + if (s7 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c16(s1, s7); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 44) { + s3 = peg$c1; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c17(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsefunction_name() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = []; + if (peg$c18.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c19); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c18.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c19); } + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = []; + if (peg$c20.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c21); } + } + while (s3 !== peg$FAILED) { + s2.push(s3); + if (peg$c20.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c21); } + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c22(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseargument_name() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = []; + if (peg$c18.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c19); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c18.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c19); } + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = []; + if (peg$c20.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c21); } + } + while (s3 !== peg$FAILED) { + s2.push(s3); + if (peg$c20.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c21); } + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c23(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsefunction() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parsespace(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 46) { + s2 = peg$c25; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c26); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsefunction_name(); + if (s3 !== peg$FAILED) { + s4 = peg$parsespace(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 40) { + s5 = peg$c27; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c28); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsespace(); + if (s6 === peg$FAILED) { + s6 = null; + } + if (s6 !== peg$FAILED) { + s7 = peg$parsearg_list(); + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + s8 = peg$parsespace(); + if (s8 === peg$FAILED) { + s8 = null; + } + if (s8 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s9 = peg$c29; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c30); } + } + if (s9 !== peg$FAILED) { + s10 = peg$parsespace(); + if (s10 === peg$FAILED) { + s10 = null; + } + if (s10 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c31(s3, s7); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s1 = peg$c25; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c26); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsefunction_name(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c32(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c24); } + } + + return s0; + } + + function peg$parsereference() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 64) { + s1 = peg$c33; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c34); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseinteger(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 58) { + s3 = peg$c35; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c36); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parseinteger(); + if (s4 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c37(s2, s4); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 64) { + s1 = peg$c33; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c34); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseinteger(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c38(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsechain() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$parsefunction(); + if (s1 !== peg$FAILED) { + s2 = peg$parsespace(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsefunction(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsefunction(); + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c39(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsegroup() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 40) { + s1 = peg$c27; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c28); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsespace(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseseries(); + if (s3 !== peg$FAILED) { + s4 = peg$parsespace(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c29; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c30); } + } + if (s5 !== peg$FAILED) { + s6 = []; + s7 = peg$parsefunction(); + while (s7 !== peg$FAILED) { + s6.push(s7); + s7 = peg$parsefunction(); + } + if (s6 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c40(s3, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseliteral() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c42; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsedq_char(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsedq_char(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c42; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c44(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 39) { + s1 = peg$c45; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c46); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsesq_char(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsesq_char(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s3 = peg$c45; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c46); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c44(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c47) { + s1 = peg$c47; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c48); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c49(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 5) === peg$c50) { + s1 = peg$c50; + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c51); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c52(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c53) { + s1 = peg$c53; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c54); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c55(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = []; + if (peg$c56.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c57); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c56.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c57); } + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c58(s1); + } + s0 = s1; + } + } + } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c41); } + } + + return s0; + } + + function peg$parsespace() { + var s0, s1; + + s0 = []; + if (peg$c59.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c60); } + } + if (s1 !== peg$FAILED) { + while (s1 !== peg$FAILED) { + s0.push(s1); + if (peg$c59.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c60); } + } + } + } else { + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsedq_char() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c61; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s2 = peg$c42; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + if (s2 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 92) { + s2 = peg$c61; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c63(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + if (peg$c64.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c65); } + } + } + + return s0; + } + + function peg$parsesq_char() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c61; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s2 = peg$c45; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c46); } + } + if (s2 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 92) { + s2 = peg$c61; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c63(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + if (peg$c66.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c67); } + } + } + + return s0; + } + + function peg$parseinteger() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = []; + if (peg$c68.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c69); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c68.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c69); } + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c70(s1); + } + s0 = s1; + + return s0; + } + + + function ltoo (literal) { + return {type: 'literal', value: literal} + } + + function simpleLocation (location) { + // Returns an object representing the position of the function within the expression, + // demarcated by the position of its first character and last character. We calculate these values + // using the offset because the expression could span multiple lines, and we don't want to deal + // with column and line values. + return { + min: location.start.offset, + max: location.end.offset + } + } + + var currentFunction; + var currentArgs = []; + + var functions = []; + var args = []; + var variables = {}; + + + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail({ type: "end", description: "end of input" }); + } + + throw peg$buildException( + null, + peg$maxFailExpected, + peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, + peg$maxFailPos < input.length + ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) + : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) + ); + } + } + + return { + SyntaxError: peg$SyntaxError, + parse: peg$parse + }; +})(); \ No newline at end of file diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx b/src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx index 6095ba28443b8d..3b42fa7dfcbb88 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx +++ b/src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx @@ -24,7 +24,7 @@ import { debounce, compact, get, each, cloneDeep, last, map } from 'lodash'; import { useKibana } from '../../../../../plugins/kibana_react/public'; import '../flot'; -import { DEFAULT_TIME_FORMAT } from '../../common/lib'; +import { DEFAULT_TIME_FORMAT } from '../../../../../plugins/timelion/common/lib'; import { buildSeriesData, diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx b/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx index fa79e4eb6871a9..620bc26d9184d1 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx +++ b/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx @@ -24,8 +24,11 @@ import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { CodeEditor, useKibana } from '../../../../../plugins/kibana_react/public'; import { suggest, getSuggestion } from './timelion_expression_input_helpers'; -import { ITimelionFunction, TimelionFunctionArgs } from '../../common/types'; import { getArgValueSuggestions } from '../helpers/arg_value_suggestions'; +import { + ITimelionFunction, + TimelionFunctionArgs, +} from '../../../../../plugins/timelion/common/types'; const LANGUAGE_ID = 'timelion_expression'; monacoEditor.languages.register({ id: LANGUAGE_ID }); diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts b/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts new file mode 100644 index 00000000000000..cf40d2f791fc28 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts @@ -0,0 +1,306 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SUGGESTION_TYPE, suggest } from './timelion_expression_input_helpers'; +import { getArgValueSuggestions } from '../helpers/arg_value_suggestions'; +import { setIndexPatterns, setSavedObjectsClient } from '../helpers/plugin_services'; +import { IndexPatterns } from 'src/plugins/data/public'; +import { SavedObjectsClient } from 'kibana/public'; +import { ITimelionFunction } from '../../../../../plugins/timelion/common/types'; + +describe('Timelion expression suggestions', () => { + setIndexPatterns({} as IndexPatterns); + setSavedObjectsClient({} as SavedObjectsClient); + + const argValueSuggestions = getArgValueSuggestions(); + + describe('getSuggestions', () => { + const func1 = { + name: 'func1', + chainable: true, + args: [ + { name: 'inputSeries' }, + { name: 'argA' }, + { + name: 'argAB', + suggestions: [{ name: 'value1' }], + }, + ], + } as ITimelionFunction; + const myFunc2 = { + name: 'myFunc2', + chainable: false, + args: [{ name: 'argA' }, { name: 'argAB' }, { name: 'argABC' }], + } as ITimelionFunction; + const functionList = [func1, myFunc2]; + + describe('parse exception', () => { + describe('incompleteFunction', () => { + it('should return function suggestions', async () => { + const expression = '.'; + const cursorPosition = 1; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [func1, myFunc2], + type: SUGGESTION_TYPE.FUNCTIONS, + }); + }); + it('should filter function suggestions by function name', async () => { + const expression = '.myF'; + const cursorPosition = 4; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [myFunc2], + type: SUGGESTION_TYPE.FUNCTIONS, + }); + }); + }); + + describe('no argument name provided', () => { + it('should return no argument suggestions when none provided by help', async () => { + const expression = '.otherFunc(=)'; + const cursorPosition = 0; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [], + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + + it('should return argument suggestions when provided by help', async () => { + const expression = '.myFunc2(=)'; + const cursorPosition = 0; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: myFunc2.args, + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + + it('should return argument suggestions when argument value provided', async () => { + const expression = '.myFunc2(=whatArgumentAmI)'; + const cursorPosition = 0; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: myFunc2.args, + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + + it('should not show first argument for chainable functions', async () => { + const expression = '.func1(=)'; + const cursorPosition = 0; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [{ name: 'argA' }, { name: 'argAB', suggestions: [{ name: 'value1' }] }], + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + + it('should not provide argument suggestions for argument that is all ready set in function def', async () => { + const expression = '.myFunc2(argAB=provided,=)'; + const cursorPosition = 0; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [{ name: 'argA' }, { name: 'argABC' }], + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + }); + + describe('no argument value provided', () => { + it('should return no argument value suggestions when not provided by help', async () => { + const expression = '.func1(argA=)'; + const cursorPosition = 11; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [], + type: SUGGESTION_TYPE.ARGUMENT_VALUE, + }); + }); + + it('should return argument value suggestions when provided by help', async () => { + const expression = '.func1(argAB=)'; + const cursorPosition = 11; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [{ name: 'value1' }], + type: SUGGESTION_TYPE.ARGUMENT_VALUE, + }); + }); + }); + }); + + describe('parse cleanly', () => { + describe('cursor in function name', () => { + it('should return function suggestion', async () => { + const expression = '.func1()'; + const cursorPosition = 1; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [func1], + type: SUGGESTION_TYPE.FUNCTIONS, + }); + }); + }); + + describe('cursor in function parentheses', () => { + describe('cursor in argument name', () => { + it('should return argument suggestions', async () => { + const expression = '.myFunc2()'; + const cursorPosition = 9; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: myFunc2.args, + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + it('should not provide argument suggestions for argument that is all ready set in function def', async () => { + const expression = '.myFunc2(argAB=provided,)'; + const cursorPosition = 24; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [{ name: 'argA' }, { name: 'argABC' }], + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + it('should filter argument suggestions by argument name', async () => { + const expression = '.myFunc2(argAB,)'; + const cursorPosition = 14; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [{ name: 'argAB' }, { name: 'argABC' }], + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + it('should not show first argument for chainable functions', async () => { + const expression = '.func1()'; + const cursorPosition = 7; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [{ name: 'argA' }, { name: 'argAB', suggestions: [{ name: 'value1' }] }], + type: SUGGESTION_TYPE.ARGUMENTS, + }); + }); + }); + describe('cursor in argument value', () => { + it('should return no argument value suggestions when not provided by help', async () => { + const expression = '.myFunc2(argA=42)'; + const cursorPosition = 14; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [], + type: SUGGESTION_TYPE.ARGUMENT_VALUE, + }); + }); + + it('should return no argument value suggestions when provided by help', async () => { + const expression = '.func1(argAB=val)'; + const cursorPosition = 16; + const suggestions = await suggest( + expression, + functionList, + cursorPosition, + argValueSuggestions + ); + expect(suggestions).toEqual({ + list: [{ name: 'value1' }], + type: SUGGESTION_TYPE.ARGUMENT_VALUE, + }); + }); + }); + }); + }); + }); +}); diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts b/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts index 5aa05fb16466bb..93b6a0d463c01b 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts +++ b/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts @@ -18,17 +18,19 @@ */ import { get, startsWith } from 'lodash'; -import PEG from 'pegjs'; +import { i18n } from '@kbn/i18n'; import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { Parser } from 'pegjs'; + // @ts-ignore -import grammar from 'raw-loader!../chain.peg'; +import { parse } from '../_generated_/chain'; -import { i18n } from '@kbn/i18n'; -import { ITimelionFunction, TimelionFunctionArgs } from '../../common/types'; import { ArgValueSuggestions, FunctionArg, Location } from '../helpers/arg_value_suggestions'; - -const Parser = PEG.generate(grammar); +import { + ITimelionFunction, + TimelionFunctionArgs, +} from '../../../../../plugins/timelion/common/types'; export enum SUGGESTION_TYPE { ARGUMENTS = 'arguments', @@ -57,7 +59,7 @@ function getArgumentsHelp( } async function extractSuggestionsFromParsedResult( - result: ReturnType, + result: ReturnType, cursorPosition: number, functionList: ITimelionFunction[], argValueSuggestions: ArgValueSuggestions @@ -141,7 +143,7 @@ export async function suggest( argValueSuggestions: ArgValueSuggestions ) { try { - const result = await Parser.parse(expression); + const result = await parse(expression); return await extractSuggestionsFromParsedResult( result, diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts b/src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts index 8d133de51f6d9a..56562121397ce9 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts +++ b/src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts @@ -18,8 +18,9 @@ */ import { get } from 'lodash'; -import { TimelionFunctionArgs } from '../../common/types'; import { getIndexPatterns, getSavedObjectsClient } from './plugin_services'; +import { TimelionFunctionArgs } from '../../../../../plugins/timelion/common/types'; +import { isNestedField } from '../../../../../plugins/data/public'; export interface Location { min: number; @@ -120,7 +121,8 @@ export function getArgValueSuggestions() { return ( field.aggregatable && 'number' === field.type && - containsFieldName(valueSplit[1], field) + containsFieldName(valueSplit[1], field) && + !isNestedField(field) ); }) .map(field => { @@ -138,7 +140,8 @@ export function getArgValueSuggestions() { return ( field.aggregatable && ['number', 'boolean', 'date', 'ip', 'string'].includes(field.type) && - containsFieldName(partial, field) + containsFieldName(partial, field) && + !isNestedField(field) ); }) .map(field => { @@ -153,7 +156,9 @@ export function getArgValueSuggestions() { return indexPattern.fields .filter(field => { - return 'date' === field.type && containsFieldName(partial, field); + return ( + 'date' === field.type && containsFieldName(partial, field) && !isNestedField(field) + ); }) .map(field => { return { name: field.name }; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts b/src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts index db29d9112be8e8..f932e5ee4b2f46 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts +++ b/src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts @@ -23,7 +23,7 @@ import moment, { Moment } from 'moment-timezone'; import { TimefilterContract } from 'src/plugins/data/public'; import { IUiSettingsClient } from 'kibana/public'; -import { calculateInterval } from '../../common/lib'; +import { calculateInterval } from '../../../../../plugins/timelion/common/lib'; import { xaxisFormatterProvider } from './xaxis_formatter'; import { Series } from './timelion_request_handler'; diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_row.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_row.js index b07e1cef4fc812..a2f1640904dd02 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_row.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_row.js @@ -22,14 +22,13 @@ import React from 'react'; import { last } from 'lodash'; import { AddDeleteButtons } from '../add_delete_buttons'; import { EuiIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { injectI18n } from '@kbn/i18n/react'; import { SeriesDragHandler } from '../series_drag_handler'; +import { i18n } from '@kbn/i18n'; -function AggRowUi(props) { +export function AggRow(props) { let iconType = 'eyeClosed'; let iconColor = 'subdued'; const lastSibling = last(props.siblings); - const { intl } = props; if (lastSibling.id === props.model.id) { iconType = 'eye'; @@ -57,12 +56,10 @@ function AggRowUi(props) { { return value === option.value && isMetricEnabled(option.value, uiRestrictions); @@ -247,8 +247,7 @@ function AggSelectUi(props) { options = [ { - label: intl.formatMessage({ - id: 'visTypeTimeseries.aggSelect.aggGroups.metricAggLabel', + label: i18n.translate('visTypeTimeseries.aggSelect.aggGroups.metricAggLabel', { defaultMessage: 'Metric Aggregations', }), options: metricAggs.map(agg => ({ @@ -257,22 +256,19 @@ function AggSelectUi(props) { })), }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.aggSelect.aggGroups.parentPipelineAggLabel', + label: i18n.translate('visTypeTimeseries.aggSelect.aggGroups.parentPipelineAggLabel', { defaultMessage: 'Parent Pipeline Aggregations', }), options: pipelineAggs.filter(filterByPanelType(panelType)).map(disableSiblingAggs), }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.aggSelect.aggGroups.siblingPipelineAggLabel', + label: i18n.translate('visTypeTimeseries.aggSelect.aggGroups.siblingPipelineAggLabel', { defaultMessage: 'Sibling Pipeline Aggregations', }), options: siblingAggs.map(disableSiblingAggs), }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.aggSelect.aggGroups.specialAggLabel', + label: i18n.translate('visTypeTimeseries.aggSelect.aggGroups.specialAggLabel', { defaultMessage: 'Special Aggregations', }), options: specialAggs.map(disableSiblingAggs), @@ -289,8 +285,7 @@ function AggSelectUi(props) {
Array.isArray(model.variables) && model.script !== undefined; - render() { - const { siblings } = this.props; +export function CalculationAgg(props) { + const htmlId = htmlIdGenerator(); + const { siblings, model } = props; - const defaults = { script: '' }; - const model = { ...defaults, ...this.props.model }; + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - const handleTextChange = createTextHandler(handleChange); + useEffect(() => { + if (!checkModel(model)) { + handleChange({ + variables: [newVariable()], + script: '', + }); + } + }, [handleChange, model]); - const htmlId = htmlIdGenerator(); + return ( + + + + + + + + + - return ( - - - - - - - - + + - + + + + - - + + - - - - - - - - } - fullWidth - helpText={ -
- params, - paramsName: params.<name>, - paramsInterval: params._interval, - }} - /> -
- } - > - -
-
-
-
- ); - } + values={{ + params: params, + paramsName: params.<name>, + paramsInterval: params._interval, + }} + /> +
+ } + > + + +
+ + + ); } CalculationAgg.propTypes = { diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/math.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/math.js index c62012927f951b..5ffcef12c3fcb1 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/math.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/math.js @@ -17,17 +17,15 @@ * under the License. */ -import React, { Component } from 'react'; +import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; -import _ from 'lodash'; -import uuid from 'uuid'; import { AggRow } from './agg_row'; import { AggSelect } from './agg_select'; import { createChangeHandler } from '../lib/create_change_handler'; import { createSelectHandler } from '../lib/create_select_handler'; import { createTextHandler } from '../lib/create_text_handler'; -import { CalculationVars } from './vars'; +import { CalculationVars, newVariable } from './vars'; import { htmlIdGenerator, EuiFlexGroup, @@ -41,125 +39,121 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -export class MathAgg extends Component { - UNSAFE_componentWillMount() { - if (!this.props.model.variables) { - this.props.onChange( - _.assign({}, this.props.model, { - variables: [{ id: uuid.v1() }], - }) - ); - } - } +const checkModel = model => Array.isArray(model.variables) && model.script !== undefined; - render() { - const { siblings } = this.props; - const htmlId = htmlIdGenerator(); +export function MathAgg(props) { + const { siblings, model } = props; + const htmlId = htmlIdGenerator(); - const defaults = { script: '' }; - const model = { ...defaults, ...this.props.model }; + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - const handleTextChange = createTextHandler(handleChange); + useEffect(() => { + if (!checkModel(model)) { + handleChange({ + variables: [newVariable()], + script: '', + }); + } + }, [handleChange, model]); - return ( - - - - - - - - + + + + - + + + + - - - - - - + + - + + + + - - - } - fullWidth - helpText={ - + } + fullWidth + helpText={ + - - - ), - params: params, - paramsName: params.<name>, - paramsValues: params._all.<name>.values, - paramsTimestamps: params._all.<name>.timestamps, - paramsTimestamp: params._timestamp, - paramsIndex: params._index, - paramsInterval: params._interval, - }} - /> - } - > - + + + ), + params: params, + paramsName: params.<name>, + paramsValues: params._all.<name>.values, + paramsTimestamps: params._all.<name>.timestamps, + paramsTimestamp: params._timestamp, + paramsIndex: params._index, + paramsInterval: params._interval, + }} /> - - - - - ); - } + } + > + + + + + + ); } MathAgg.propTypes = { diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/percentile.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/percentile.js index 3ce5be5b6875a8..500bba14d66c93 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/percentile.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/percentile.js @@ -18,8 +18,7 @@ */ import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import _ from 'lodash'; +import React, { useEffect } from 'react'; import { AggSelect } from './agg_select'; import { FieldSelect } from './field_select'; import { AggRow } from './agg_row'; @@ -39,82 +38,78 @@ import { Percentiles, newPercentile } from './percentile_ui'; const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER]; -export class PercentileAgg extends Component { - // eslint-disable-line react/no-multi-comp +const checkModel = model => Array.isArray(model.percentiles); - UNSAFE_componentWillMount() { - if (!this.props.model.percentiles) { - this.props.onChange( - _.assign({}, this.props.model, { - percentiles: [newPercentile({ value: 50 })], - }) - ); - } - } +export function PercentileAgg(props) { + const { series, model, panel, fields } = props; + const htmlId = htmlIdGenerator(); - render() { - const { series, model, panel, fields } = this.props; + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const indexPattern = + (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern; - const handleChange = createChangeHandler(this.props.onChange, model); - const handleSelectChange = createSelectHandler(handleChange); - const indexPattern = - (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern; - const htmlId = htmlIdGenerator(); + useEffect(() => { + if (!checkModel(model)) { + handleChange({ + percentiles: [newPercentile({ value: 50 })], + }); + } + }, [handleChange, model]); - return ( - - - - + return ( + + + + + + + + + + + - - - + - - - - } - > - - - - + + + - + - - - ); - } + + + ); } PercentileAgg.propTypes = { diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/vars.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/vars.js index 8553f08af1353e..3d4ce601c7244b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/vars.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/vars.js @@ -19,14 +19,17 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; +import uuid from 'uuid'; +import { i18n } from '@kbn/i18n'; import _ from 'lodash'; import { AddDeleteButtons } from '../add_delete_buttons'; import { collectionActions } from '../lib/collection_actions'; import { MetricSelect } from './metric_select'; import { EuiFlexGroup, EuiFlexItem, EuiFieldText } from '@elastic/eui'; -import { injectI18n } from '@kbn/i18n/react'; -class CalculationVarsUi extends Component { +export const newVariable = opts => ({ id: uuid.v1(), name: '', field: '', ...opts }); + +export class CalculationVars extends Component { constructor(props) { super(props); this.renderRow = this.renderRow.bind(this); @@ -42,21 +45,19 @@ class CalculationVarsUi extends Component { } renderRow(row, i, items) { - const handleAdd = collectionActions.handleAdd.bind(null, this.props); + const handleAdd = collectionActions.handleAdd.bind(null, this.props, newVariable); const handleDelete = collectionActions.handleDelete.bind(null, this.props, row); - const { intl } = this.props; + return ( diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js index 10fc34fccd2cc6..a82d5bdb1588c7 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js @@ -26,7 +26,7 @@ import { calculateLabel } from '../../../../common/calculate_label'; import { isSortable } from './is_sortable'; import { EuiToolTip, EuiIcon } from '@elastic/eui'; import { replaceVars } from '../../lib/replace_vars'; -import { FIELD_FORMAT_IDS } from '../../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../../plugins/data/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { METRIC_TYPES } from '../../../../common/metric_types'; @@ -49,8 +49,8 @@ export class TableVis extends Component { constructor(props) { super(props); - const fieldFormats = npStart.plugins.data.fieldFormats; - const DateFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); + const fieldFormatsService = npStart.plugins.data.fieldFormats; + const DateFormat = fieldFormatsService.getType(fieldFormats.FIELD_FORMAT_IDS.DATE); this.dateFormatter = new DateFormat({}, this.props.getConfig); } diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_fields.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_fields.js index c16452ab4b8952..361ce132f17359 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_fields.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/get_fields.js @@ -19,6 +19,7 @@ import { SearchStrategiesRegister } from './search_strategies/search_strategies_register'; import { uniq } from 'lodash'; import { getIndexPatternObject } from './vis_data/helpers/get_index_pattern'; +import { isNestedField } from '../../../../../plugins/data/server'; export async function getFields(req) { const indexPattern = req.query.index; @@ -30,7 +31,7 @@ export async function getFields(req) { const fields = ( await searchStrategy.getFieldsForWildcard(req, indexPatternString, capabilities) - ).filter(field => field.aggregatable); + ).filter(field => field.aggregatable && !isNestedField(field)); return uniq(fields, field => field.name); } diff --git a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js index 0c12b3d928815c..60f1bed35b5185 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js +++ b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js @@ -43,6 +43,7 @@ import { SearchCache } from '../data_model/search_cache'; import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; import { createVegaTypeDefinition } from '../vega_type'; +import { npStart } from 'ui/new_platform'; const THRESHOLD = 0.1; const PIXEL_DIFF = 30; @@ -60,10 +61,9 @@ describe('VegaVisualizations', () => { beforeEach( ngMock.inject((Private, $injector) => { vegaVisualizationDependencies = { - es: $injector.get('es'), serviceSettings: $injector.get('serviceSettings'), core: { - uiSettings: $injector.get('config'), + uiSettings: npStart.core.uiSettings, }, plugins: { data: { @@ -72,6 +72,9 @@ describe('VegaVisualizations', () => { timefilter: {}, }, }, + __LEGACY: { + esClient: npStart.plugins.data.search.__LEGACY.esClient, + }, }, }, }; diff --git a/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts index af4425e3d55480..5cf65d62a6aede 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts @@ -19,12 +19,10 @@ import chrome from 'ui/chrome'; import 'ui/vis/map/service_settings'; -import 'ui/es'; // required for $injector.get('es') below import { CoreStart, Plugin } from 'kibana/public'; /** @internal */ export interface LegacyDependenciesPluginSetup { - es: any; serviceSettings: any; } @@ -34,9 +32,6 @@ export class LegacyDependenciesPlugin const $injector = await chrome.dangerouslyGetActiveInjector(); return { - // Client of Elastic Search. - es: $injector.get('es'), - // Settings for EMSClient. // EMSClient, which currently lives in the tile_map vis, // will probably end up being exposed from the future vis_type_maps plugin, diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts b/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts index 089cc3215d87d7..576786567a6f9d 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts @@ -16,6 +16,9 @@ * specific language governing permissions and limitations * under the License. */ + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getSearchService } from '../../../../plugins/data/public/services'; import { esFilters, esQuery, TimeRange, Query } from '../../../../plugins/data/public'; // @ts-ignore @@ -36,13 +39,13 @@ interface VegaRequestHandlerParams { } export function createVegaRequestHandler({ - es, - plugins, + plugins: { data }, core: { uiSettings }, serviceSettings, }: VegaVisualizationDependencies) { - const searchCache = new SearchCache(es, { max: 10, maxAge: 4 * 1000 }); - const { timefilter } = plugins.data.query.timefilter; + const { esClient } = getSearchService().__LEGACY; + const searchCache = new SearchCache(esClient, { max: 10, maxAge: 4 * 1000 }); + const { timefilter } = data.query.timefilter; const timeCache = new TimeCache(timefilter, 3 * 1000); return ({ timeRange, filters, query, visParams }: VegaRequestHandlerParams) => { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/area.ts b/src/legacy/core_plugins/vis_type_vislib/public/area.ts index 9484ddc16fe625..a96fb19a9321ca 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/area.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/area.ts @@ -42,9 +42,9 @@ import { KbnVislibVisTypesDependencies } from './plugin'; export const createAreaVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'area', - title: i18n.translate('kbnVislibVisTypes.area.areaTitle', { defaultMessage: 'Area' }), + title: i18n.translate('visTypeVislib.area.areaTitle', { defaultMessage: 'Area' }), icon: 'visArea', - description: i18n.translate('kbnVislibVisTypes.area.areaDescription', { + description: i18n.translate('visTypeVislib.area.areaDescription', { defaultMessage: 'Emphasize the quantity beneath a line chart', }), visualization: createVislibVisController(deps), @@ -136,7 +136,7 @@ export const createAreaVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.area.metricsTitle', { + title: i18n.translate('visTypeVislib.area.metricsTitle', { defaultMessage: 'Y-axis', }), aggFilter: ['!geo_centroid', '!geo_bounds'], @@ -146,7 +146,7 @@ export const createAreaVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Metrics, name: 'radius', - title: i18n.translate('kbnVislibVisTypes.area.radiusTitle', { + title: i18n.translate('visTypeVislib.area.radiusTitle', { defaultMessage: 'Dot size', }), min: 0, @@ -156,7 +156,7 @@ export const createAreaVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'segment', - title: i18n.translate('kbnVislibVisTypes.area.segmentTitle', { + title: i18n.translate('visTypeVislib.area.segmentTitle', { defaultMessage: 'X-axis', }), min: 0, @@ -166,7 +166,7 @@ export const createAreaVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'group', - title: i18n.translate('kbnVislibVisTypes.area.groupTitle', { + title: i18n.translate('visTypeVislib.area.groupTitle', { defaultMessage: 'Split series', }), min: 0, @@ -176,7 +176,7 @@ export const createAreaVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'split', - title: i18n.translate('kbnVislibVisTypes.area.splitTitle', { + title: i18n.translate('visTypeVislib.area.splitTitle', { defaultMessage: 'Split chart', }), min: 0, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx index 81174d63060e5c..229945621fe76d 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx @@ -37,7 +37,7 @@ function BasicOptions({ return ( <> ({ setValue={setValue} /> @@ -79,11 +79,11 @@ function ColorSchemaOptions({ disabled={disabled} helpText={ showHelpText && - i18n.translate('kbnVislibVisTypes.controls.colorSchema.howToChangeColorsDescription', { + i18n.translate('visTypeVislib.controls.colorSchema.howToChangeColorsDescription', { defaultMessage: 'Individual colors can be changed in the legend.', }) } - label={i18n.translate('kbnVislibVisTypes.controls.colorSchema.colorSchemaLabel', { + label={i18n.translate('visTypeVislib.controls.colorSchema.colorSchemaLabel', { defaultMessage: 'Color schema', })} labelAppend={isCustomColors && resetColorsButton} @@ -95,7 +95,7 @@ function ColorSchemaOptions({ ({ const [stateValue, setStateValue] = useState(value); const [isValidState, setIsValidState] = useState(true); - const error = i18n.translate('kbnVislibVisTypes.controls.rangeErrorMessage', { + const error = i18n.translate('visTypeVislib.controls.rangeErrorMessage', { defaultMessage: 'Values must be on or between {min} and {max}', values: { min, max }, }); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/select.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/select.tsx index 45b1bdd44f460c..8ce7f4d640898e 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/common/select.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/common/select.tsx @@ -30,6 +30,7 @@ interface SelectOptionProps void; + 'data-test-subj'?: string; } const emptyValue = { text: '', value: 'EMPTY_VALUE', disabled: true, hidden: true }; @@ -44,6 +45,7 @@ function SelectOption) { const availableOptions = useMemo(() => [emptyValue, ...options], [options]); @@ -63,6 +65,7 @@ function SelectOption setValue(paramName, ev.target.value as ValidParamValues)} fullWidth={true} + data-test-subj={dataTestSubj} /> ); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/truncate_labels.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/truncate_labels.tsx index 81772107bc729c..2f0cb701848d0c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/common/truncate_labels.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/common/truncate_labels.tsx @@ -33,7 +33,7 @@ function TruncateLabelsOption({ disabled, value = null, setValue }: TruncateLabe return (

@@ -39,7 +39,7 @@ function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInter

@@ -76,10 +76,10 @@ function RangesPanel({

@@ -44,7 +44,7 @@ function StylePanel({ aggs, setGaugeValue, stateParams, vis }: GaugeOptionsInter ) {

@@ -78,13 +78,13 @@ function HeatmapOptions(props: VisOptionsProps) { ) {

@@ -114,7 +114,7 @@ function HeatmapOptions(props: VisOptionsProps) { ) { /> ) { ) { data-test-subj="heatmapColorsNumber" disabled={stateParams.setColorRange} isInvalid={isColorsNumberInvalid} - label={i18n.translate('kbnVislibVisTypes.controls.heatmapOptions.colorsNumberLabel', { + label={i18n.translate('visTypeVislib.controls.heatmapOptions.colorsNumberLabel', { defaultMessage: 'Number of colors', })} max={10} @@ -160,7 +159,7 @@ function HeatmapOptions(props: VisOptionsProps) {

@@ -73,7 +73,7 @@ function LabelsPanel({ valueAxis, setValue }: LabelsPanelProps) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap index d88654cfdc0c43..037989a86af01f 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap @@ -10,7 +10,7 @@ exports[`CategoryAxisPanel component should init with the default set of props 1

@@ -19,6 +19,7 @@ exports[`CategoryAxisPanel component should init with the default set of props 1 size="s" /> diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap index 8d20765fe35918..f589a69eecbc3b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap @@ -18,7 +18,7 @@ exports[`ValueAxesPanel component should init with the default set of props 1`]

diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap index f2ee088450fbdd..caf38c09783f0f 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap @@ -85,6 +85,7 @@ exports[`ValueAxisOptions component should init with the default set of props 1` margin="m" />

@@ -70,17 +70,18 @@ function CategoryAxisPanel(props: CategoryAxisPanelProps) {

@@ -73,12 +73,9 @@ function LabelOptions({ stateParams, setValue, axis, axesName, index }: LabelOpt

@@ -57,7 +57,7 @@ function SeriesPanel(props: SeriesPanelProps) { buttonContent={chart.data.label} buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate" aria-label={i18n.translate( - 'kbnVislibVisTypes.controls.pointSeries.seriesAccordionAriaLabel', + 'visTypeVislib.controls.pointSeries.seriesAccordionAriaLabel', { defaultMessage: 'Toggle {agg} options', values: { agg: chart.data.label }, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx index eb0ab4333af599..b94f5ebbcce44f 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx @@ -60,7 +60,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) { const removeButtonTooltip = useMemo( () => - i18n.translate('kbnVislibVisTypes.controls.pointSeries.valueAxes.removeButtonTooltip', { + i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.removeButtonTooltip', { defaultMessage: 'Remove Y-axis', }), [] @@ -83,7 +83,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) { const addButtonTooltip = useMemo( () => - i18n.translate('kbnVislibVisTypes.controls.pointSeries.valueAxes.addButtonTooltip', { + i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.addButtonTooltip', { defaultMessage: 'Add Y-axis', }), [] @@ -111,7 +111,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) {

@@ -142,7 +142,7 @@ function ValueAxesPanel(props: ValueAxesPanelProps) { buttonClassName="eui-textTruncate" buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate" aria-label={i18n.translate( - 'kbnVislibVisTypes.controls.pointSeries.valueAxes.toggleOptionsAriaLabel', + 'visTypeVislib.controls.pointSeries.valueAxes.toggleOptionsAriaLabel', { defaultMessage: 'Toggle {axisName} options', values: { axisName: axis.name }, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx index b4ea4cb42ee60c..0ebe62a70a7b1c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx @@ -119,7 +119,7 @@ function ValueAxisOptions(props: ValueAxisOptionsParams) { return ( <> ) {

) {

) { setValue={setLabels} /> ) { setValue={setLabels} />

@@ -72,14 +72,14 @@ function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps)

@@ -46,7 +46,7 @@ function PointSeriesOptions(props: ValidationVisOptionsProps) {vis.hasSchemaAgg('segment', 'date_histogram') ? ( ) /> ) : ( ) {vis.type.type === 'histogram' && (

@@ -63,7 +63,7 @@ function ThresholdPanel({ diff --git a/src/legacy/core_plugins/vis_type_vislib/public/gauge.ts b/src/legacy/core_plugins/vis_type_vislib/public/gauge.ts index 5dcc8ad16918d0..f235ed4bb04e40 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/gauge.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/gauge.ts @@ -56,9 +56,9 @@ export interface GaugeVisParams { export const createGaugeVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'gauge', - title: i18n.translate('kbnVislibVisTypes.gauge.gaugeTitle', { defaultMessage: 'Gauge' }), + title: i18n.translate('visTypeVislib.gauge.gaugeTitle', { defaultMessage: 'Gauge' }), icon: 'visGauge', - description: i18n.translate('kbnVislibVisTypes.gauge.gaugeDescription', { + description: i18n.translate('visTypeVislib.gauge.gaugeDescription', { defaultMessage: "Gauges indicate the status of a metric. Use it to show how a metric's value relates to reference threshold values.", }), @@ -116,7 +116,7 @@ export const createGaugeVisTypeDefinition = (deps: KbnVislibVisTypesDependencies { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.gauge.metricTitle', { defaultMessage: 'Metric' }), + title: i18n.translate('visTypeVislib.gauge.metricTitle', { defaultMessage: 'Metric' }), min: 1, aggFilter: [ '!std_dev', @@ -134,7 +134,7 @@ export const createGaugeVisTypeDefinition = (deps: KbnVislibVisTypesDependencies { group: AggGroupNames.Buckets, name: 'group', - title: i18n.translate('kbnVislibVisTypes.gauge.groupTitle', { + title: i18n.translate('visTypeVislib.gauge.groupTitle', { defaultMessage: 'Split group', }), min: 0, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/goal.ts b/src/legacy/core_plugins/vis_type_vislib/public/goal.ts index 302d5f6393ef90..94262629669bec 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/goal.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/goal.ts @@ -27,9 +27,9 @@ import { KbnVislibVisTypesDependencies } from './plugin'; export const createGoalVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'goal', - title: i18n.translate('kbnVislibVisTypes.goal.goalTitle', { defaultMessage: 'Goal' }), + title: i18n.translate('visTypeVislib.goal.goalTitle', { defaultMessage: 'Goal' }), icon: 'visGoal', - description: i18n.translate('kbnVislibVisTypes.goal.goalDescription', { + description: i18n.translate('visTypeVislib.goal.goalDescription', { defaultMessage: 'A goal chart indicates how close you are to your final goal.', }), visualization: createVislibVisController(deps), @@ -80,7 +80,7 @@ export const createGoalVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.goal.metricTitle', { defaultMessage: 'Metric' }), + title: i18n.translate('visTypeVislib.goal.metricTitle', { defaultMessage: 'Metric' }), min: 1, aggFilter: [ '!std_dev', @@ -98,7 +98,7 @@ export const createGoalVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'group', - title: i18n.translate('kbnVislibVisTypes.goal.groupTitle', { + title: i18n.translate('visTypeVislib.goal.groupTitle', { defaultMessage: 'Split group', }), min: 0, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/heatmap.ts b/src/legacy/core_plugins/vis_type_vislib/public/heatmap.ts index eb5f84b409838a..470e978027ca2b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/heatmap.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/heatmap.ts @@ -41,9 +41,9 @@ export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaVislibP export const createHeatmapVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'heatmap', - title: i18n.translate('kbnVislibVisTypes.heatmap.heatmapTitle', { defaultMessage: 'Heat Map' }), + title: i18n.translate('visTypeVislib.heatmap.heatmapTitle', { defaultMessage: 'Heat Map' }), icon: 'visHeatmap', - description: i18n.translate('kbnVislibVisTypes.heatmap.heatmapDescription', { + description: i18n.translate('visTypeVislib.heatmap.heatmapDescription', { defaultMessage: 'Shade cells within a matrix', }), visualization: createVislibVisController(deps), @@ -90,7 +90,7 @@ export const createHeatmapVisTypeDefinition = (deps: KbnVislibVisTypesDependenci { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.heatmap.metricTitle', { defaultMessage: 'Value' }), + title: i18n.translate('visTypeVislib.heatmap.metricTitle', { defaultMessage: 'Value' }), min: 1, max: 1, aggFilter: [ @@ -109,7 +109,7 @@ export const createHeatmapVisTypeDefinition = (deps: KbnVislibVisTypesDependenci { group: AggGroupNames.Buckets, name: 'segment', - title: i18n.translate('kbnVislibVisTypes.heatmap.segmentTitle', { + title: i18n.translate('visTypeVislib.heatmap.segmentTitle', { defaultMessage: 'X-axis', }), min: 0, @@ -119,7 +119,7 @@ export const createHeatmapVisTypeDefinition = (deps: KbnVislibVisTypesDependenci { group: AggGroupNames.Buckets, name: 'group', - title: i18n.translate('kbnVislibVisTypes.heatmap.groupTitle', { defaultMessage: 'Y-axis' }), + title: i18n.translate('visTypeVislib.heatmap.groupTitle', { defaultMessage: 'Y-axis' }), min: 0, max: 1, aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], @@ -127,7 +127,7 @@ export const createHeatmapVisTypeDefinition = (deps: KbnVislibVisTypesDependenci { group: AggGroupNames.Buckets, name: 'split', - title: i18n.translate('kbnVislibVisTypes.heatmap.splitTitle', { + title: i18n.translate('visTypeVislib.heatmap.splitTitle', { defaultMessage: 'Split chart', }), min: 0, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/histogram.ts b/src/legacy/core_plugins/vis_type_vislib/public/histogram.ts index f92875a62cfd7d..490b557b7bafb9 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/histogram.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/histogram.ts @@ -42,11 +42,11 @@ import { KbnVislibVisTypesDependencies } from './plugin'; export const createHistogramVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'histogram', - title: i18n.translate('kbnVislibVisTypes.histogram.histogramTitle', { + title: i18n.translate('visTypeVislib.histogram.histogramTitle', { defaultMessage: 'Vertical Bar', }), icon: 'visBarVertical', - description: i18n.translate('kbnVislibVisTypes.histogram.histogramDescription', { + description: i18n.translate('visTypeVislib.histogram.histogramDescription', { defaultMessage: 'Assign a continuous variable to each axis', }), visualization: createVislibVisController(deps), @@ -139,7 +139,7 @@ export const createHistogramVisTypeDefinition = (deps: KbnVislibVisTypesDependen { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.histogram.metricTitle', { + title: i18n.translate('visTypeVislib.histogram.metricTitle', { defaultMessage: 'Y-axis', }), min: 1, @@ -149,7 +149,7 @@ export const createHistogramVisTypeDefinition = (deps: KbnVislibVisTypesDependen { group: AggGroupNames.Metrics, name: 'radius', - title: i18n.translate('kbnVislibVisTypes.histogram.radiusTitle', { + title: i18n.translate('visTypeVislib.histogram.radiusTitle', { defaultMessage: 'Dot size', }), min: 0, @@ -159,7 +159,7 @@ export const createHistogramVisTypeDefinition = (deps: KbnVislibVisTypesDependen { group: AggGroupNames.Buckets, name: 'segment', - title: i18n.translate('kbnVislibVisTypes.histogram.segmentTitle', { + title: i18n.translate('visTypeVislib.histogram.segmentTitle', { defaultMessage: 'X-axis', }), min: 0, @@ -169,7 +169,7 @@ export const createHistogramVisTypeDefinition = (deps: KbnVislibVisTypesDependen { group: AggGroupNames.Buckets, name: 'group', - title: i18n.translate('kbnVislibVisTypes.histogram.groupTitle', { + title: i18n.translate('visTypeVislib.histogram.groupTitle', { defaultMessage: 'Split series', }), min: 0, @@ -179,7 +179,7 @@ export const createHistogramVisTypeDefinition = (deps: KbnVislibVisTypesDependen { group: AggGroupNames.Buckets, name: 'split', - title: i18n.translate('kbnVislibVisTypes.histogram.splitTitle', { + title: i18n.translate('visTypeVislib.histogram.splitTitle', { defaultMessage: 'Split chart', }), min: 0, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts b/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts index ada0c6b44ff701..e8d51fe037a63e 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts @@ -42,11 +42,11 @@ import { KbnVislibVisTypesDependencies } from './plugin'; export const createHorizontalBarVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'horizontal_bar', - title: i18n.translate('kbnVislibVisTypes.horizontalBar.horizontalBarTitle', { + title: i18n.translate('visTypeVislib.horizontalBar.horizontalBarTitle', { defaultMessage: 'Horizontal Bar', }), icon: 'visBarHorizontal', - description: i18n.translate('kbnVislibVisTypes.horizontalBar.horizontalBarDescription', { + description: i18n.translate('visTypeVislib.horizontalBar.horizontalBarDescription', { defaultMessage: 'Assign a continuous variable to each axis', }), visualization: createVislibVisController(deps), @@ -138,7 +138,7 @@ export const createHorizontalBarVisTypeDefinition = (deps: KbnVislibVisTypesDepe { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.horizontalBar.metricTitle', { + title: i18n.translate('visTypeVislib.horizontalBar.metricTitle', { defaultMessage: 'Y-axis', }), min: 1, @@ -148,7 +148,7 @@ export const createHorizontalBarVisTypeDefinition = (deps: KbnVislibVisTypesDepe { group: AggGroupNames.Metrics, name: 'radius', - title: i18n.translate('kbnVislibVisTypes.horizontalBar.radiusTitle', { + title: i18n.translate('visTypeVislib.horizontalBar.radiusTitle', { defaultMessage: 'Dot size', }), min: 0, @@ -158,7 +158,7 @@ export const createHorizontalBarVisTypeDefinition = (deps: KbnVislibVisTypesDepe { group: AggGroupNames.Buckets, name: 'segment', - title: i18n.translate('kbnVislibVisTypes.horizontalBar.segmentTitle', { + title: i18n.translate('visTypeVislib.horizontalBar.segmentTitle', { defaultMessage: 'X-axis', }), min: 0, @@ -168,7 +168,7 @@ export const createHorizontalBarVisTypeDefinition = (deps: KbnVislibVisTypesDepe { group: AggGroupNames.Buckets, name: 'group', - title: i18n.translate('kbnVislibVisTypes.horizontalBar.groupTitle', { + title: i18n.translate('visTypeVislib.horizontalBar.groupTitle', { defaultMessage: 'Split series', }), min: 0, @@ -178,7 +178,7 @@ export const createHorizontalBarVisTypeDefinition = (deps: KbnVislibVisTypesDepe { group: AggGroupNames.Buckets, name: 'split', - title: i18n.translate('kbnVislibVisTypes.horizontalBar.splitTitle', { + title: i18n.translate('visTypeVislib.horizontalBar.splitTitle', { defaultMessage: 'Split chart', }), min: 0, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/index.ts b/src/legacy/core_plugins/vis_type_vislib/public/index.ts index 3b4bcb6bc3a7e2..80c078de1a10b4 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/index.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/index.ts @@ -24,4 +24,18 @@ export function plugin(initializerContext: PluginInitializerContext) { return new Plugin(initializerContext); } +export { + BasicOptions, + RangeOption, + ColorRanges, + SelectOption, + SetColorSchemaOptionsValue, + ColorSchemaOptions, + NumberInputOption, + SwitchOption, + TextInputOption, +} from './components'; + export { ColorModes } from './utils/collections'; + +export * from './types'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts b/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts index 3d4cf55adc5e0c..49d62bc70c8bb8 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts @@ -20,22 +20,6 @@ import { npSetup, npStart } from 'ui/new_platform'; import { PluginInitializerContext } from 'kibana/public'; -/* eslint-disable prettier/prettier */ -import { - initializeHierarchicalTooltipFormatter, - getHierarchicalTooltipFormatter, - // @ts-ignore -} from 'ui/vis/components/tooltip/_hierarchical_tooltip_formatter'; -import { - initializePointSeriesTooltipFormatter, - getPointSeriesTooltipFormatter, - // @ts-ignore -} from 'ui/vis/components/tooltip/_pointseries_tooltip_formatter'; -import { - vislibSeriesResponseHandlerProvider, - vislibSlicesResponseHandlerProvider, - // @ts-ignore -} from 'ui/vis/response_handlers/vislib'; // @ts-ignore import { vislibColor } from 'ui/vis/components/color/color'; @@ -53,12 +37,6 @@ const setupPlugins: Readonly = { expressions: npSetup.plugins.expressions, visualizations: visualizationsSetup, __LEGACY: { - initializeHierarchicalTooltipFormatter, - getHierarchicalTooltipFormatter, - initializePointSeriesTooltipFormatter, - getPointSeriesTooltipFormatter, - vislibSeriesResponseHandlerProvider, - vislibSlicesResponseHandlerProvider, vislibColor, }, }; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts index 2970942f221e80..704ccf01acfaf7 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts @@ -23,13 +23,14 @@ export { RangeValues, RangesParamEditor } from 'ui/vis/editors/default/controls/ export { ColorSchema, ColorSchemas, colorSchemas, getHeatmapColors } from 'ui/color_maps'; export { AggConfig, Vis, VisParams } from 'ui/vis'; export { AggType } from 'ui/agg_types'; -export { CUSTOM_LEGEND_VIS_TYPES, VisLegend } from 'ui/vis/vis_types/vislib_vis_legend'; -// @ts-ignore -export { Tooltip } from 'ui/vis/components/tooltip'; // @ts-ignore export { SimpleEmitter } from 'ui/utils/simple_emitter'; // @ts-ignore export { Binder } from 'ui/binder'; -export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; +export { getFormat, getTableAggs } from 'ui/visualize/loader/pipeline_helpers/utilities'; // @ts-ignore export { tabifyAggResponse } from 'ui/agg_response/tabify'; +// @ts-ignore +export { buildHierarchicalData } from 'ui/agg_response/hierarchical/build_hierarchical_data'; +// @ts-ignore +export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/line.ts b/src/legacy/core_plugins/vis_type_vislib/public/line.ts index 35a059fadddcb9..d3f2bc1bb684ca 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/line.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/line.ts @@ -42,9 +42,9 @@ import { KbnVislibVisTypesDependencies } from './plugin'; export const createLineVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'line', - title: i18n.translate('kbnVislibVisTypes.line.lineTitle', { defaultMessage: 'Line' }), + title: i18n.translate('visTypeVislib.line.lineTitle', { defaultMessage: 'Line' }), icon: 'visLine', - description: i18n.translate('kbnVislibVisTypes.line.lineDescription', { + description: i18n.translate('visTypeVislib.line.lineDescription', { defaultMessage: 'Emphasize trends', }), visualization: createVislibVisController(deps), @@ -136,7 +136,7 @@ export const createLineVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.line.metricTitle', { defaultMessage: 'Y-axis' }), + title: i18n.translate('visTypeVislib.line.metricTitle', { defaultMessage: 'Y-axis' }), min: 1, aggFilter: ['!geo_centroid', '!geo_bounds'], defaults: [{ schema: 'metric', type: 'count' }], @@ -144,7 +144,7 @@ export const createLineVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Metrics, name: 'radius', - title: i18n.translate('kbnVislibVisTypes.line.radiusTitle', { defaultMessage: 'Dot size' }), + title: i18n.translate('visTypeVislib.line.radiusTitle', { defaultMessage: 'Dot size' }), min: 0, max: 1, aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality', 'top_hits'], @@ -152,7 +152,7 @@ export const createLineVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'segment', - title: i18n.translate('kbnVislibVisTypes.line.segmentTitle', { defaultMessage: 'X-axis' }), + title: i18n.translate('visTypeVislib.line.segmentTitle', { defaultMessage: 'X-axis' }), min: 0, max: 1, aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], @@ -160,7 +160,7 @@ export const createLineVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'group', - title: i18n.translate('kbnVislibVisTypes.line.groupTitle', { + title: i18n.translate('visTypeVislib.line.groupTitle', { defaultMessage: 'Split series', }), min: 0, @@ -170,7 +170,7 @@ export const createLineVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'split', - title: i18n.translate('kbnVislibVisTypes.line.splitTitle', { + title: i18n.translate('visTypeVislib.line.splitTitle', { defaultMessage: 'Split chart', }), min: 0, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/pie.ts b/src/legacy/core_plugins/vis_type_vislib/public/pie.ts index 32307b7a117a1c..3c30030ca45f5b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/pie.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/pie.ts @@ -40,9 +40,9 @@ export interface PieVisParams extends CommonVislibParams { export const createPieVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'pie', - title: i18n.translate('kbnVislibVisTypes.pie.pieTitle', { defaultMessage: 'Pie' }), + title: i18n.translate('visTypeVislib.pie.pieTitle', { defaultMessage: 'Pie' }), icon: 'visPie', - description: i18n.translate('kbnVislibVisTypes.pie.pieDescription', { + description: i18n.translate('visTypeVislib.pie.pieDescription', { defaultMessage: 'Compare parts of a whole', }), visualization: createVislibVisController(deps), @@ -70,7 +70,7 @@ export const createPieVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.pie.metricTitle', { + title: i18n.translate('visTypeVislib.pie.metricTitle', { defaultMessage: 'Slice size', }), min: 1, @@ -81,7 +81,7 @@ export const createPieVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'segment', - title: i18n.translate('kbnVislibVisTypes.pie.segmentTitle', { + title: i18n.translate('visTypeVislib.pie.segmentTitle', { defaultMessage: 'Split slices', }), min: 0, @@ -91,7 +91,7 @@ export const createPieVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) { group: AggGroupNames.Buckets, name: 'split', - title: i18n.translate('kbnVislibVisTypes.pie.splitTitle', { + title: i18n.translate('visTypeVislib.pie.splitTitle', { defaultMessage: 'Split chart', }), mustBeFirst: true, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.test.ts b/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.test.ts index 786de0cc79b86d..d38c8b216a9958 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.test.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.test.ts @@ -20,15 +20,12 @@ // eslint-disable-next-line import { functionWrapper } from '../../../../plugins/expressions/public/functions/tests/utils'; import { createPieVisFn } from './pie_fn'; -import { KbnVislibVisTypesDependencies } from './plugin'; +// @ts-ignore +import { vislibSlicesResponseHandler } from './vislib/response_handler'; jest.mock('ui/new_platform'); - -const deps: KbnVislibVisTypesDependencies = { - vislibSlicesResponseHandlerProvider: () => ({ handler: mockResponseHandler }), -} as any; -const mockResponseHandler = jest.fn().mockReturnValue( - Promise.resolve({ +jest.mock('./vislib/response_handler', () => ({ + vislibSlicesResponseHandler: jest.fn().mockReturnValue({ hits: 1, names: ['Count'], raw: { @@ -41,11 +38,11 @@ const mockResponseHandler = jest.fn().mockReturnValue( tooltipFormatter: { id: 'number', }, - }) -); + }), +})); describe('interpreter/functions#pie', () => { - const fn = functionWrapper(createPieVisFn(deps)); + const fn = functionWrapper(createPieVisFn()); const context = { type: 'kibana_datatable', rows: [{ 'col-0-1': 0 }], @@ -86,7 +83,7 @@ describe('interpreter/functions#pie', () => { it('calls response handler with correct values', async () => { await fn(context, { visConfig: JSON.stringify(visConfig) }); - expect(mockResponseHandler).toHaveBeenCalledTimes(1); - expect(mockResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions); + expect(vislibSlicesResponseHandler).toHaveBeenCalledTimes(1); + expect(vislibSlicesResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions); }); }); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.ts b/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.ts index 4b536caedb1212..199ff82a969c7f 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.ts @@ -24,7 +24,8 @@ import { KibanaDatatable, Render, } from '../../../../plugins/expressions/public'; -import { KbnVislibVisTypesDependencies } from './plugin'; +// @ts-ignore +import { vislibSlicesResponseHandler } from './vislib/response_handler'; const name = 'kibana_pie'; @@ -40,9 +41,9 @@ interface RenderValue { visConfig: VisParams; } -type Return = Promise>; +type Return = Render; -export const createPieVisFn = (deps: KbnVislibVisTypesDependencies) => (): ExpressionFunction< +export const createPieVisFn = () => (): ExpressionFunction< typeof name, Context, Arguments, @@ -53,7 +54,7 @@ export const createPieVisFn = (deps: KbnVislibVisTypesDependencies) => (): Expre context: { types: ['kibana_datatable'], }, - help: i18n.translate('kbnVislibVisTypes.functions.pie.help', { + help: i18n.translate('visTypeVislib.functions.pie.help', { defaultMessage: 'Pie visualization', }), args: { @@ -63,11 +64,9 @@ export const createPieVisFn = (deps: KbnVislibVisTypesDependencies) => (): Expre help: '', }, }, - async fn(context, args) { + fn(context, args) { const visConfig = JSON.parse(args.visConfig); - - const responseHandler = deps.vislibSlicesResponseHandlerProvider().handler; - const convertedData = await responseHandler(context, visConfig.dimensions); + const convertedData = vislibSlicesResponseHandler(context, visConfig.dimensions); return { type: 'render', diff --git a/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts b/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts index a2e8512b2201b2..4ee7929387767b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts @@ -39,19 +39,9 @@ import { createGoalVisTypeDefinition, } from './vis_type_vislib_vis_types'; -type ResponseHandlerProvider = () => { - name: string; - handler: (response: any, dimensions: any) => Promise; -}; type KbnVislibVisTypesCoreSetup = CoreSetup; export interface LegacyDependencies { - initializeHierarchicalTooltipFormatter: () => Promise; - getHierarchicalTooltipFormatter: () => Promise; - initializePointSeriesTooltipFormatter: () => void; - getPointSeriesTooltipFormatter: () => void; - vislibSeriesResponseHandlerProvider: ResponseHandlerProvider; - vislibSlicesResponseHandlerProvider: ResponseHandlerProvider; vislibColor: (colors: Array, mappings: any) => (value: any) => any; } @@ -85,8 +75,8 @@ export class KbnVislibVisTypesPlugin implements Plugin, void> { uiSettings: core.uiSettings, }; - expressions.registerFunction(createKbnVislibVisTypesFn(visualizationDependencies)); - expressions.registerFunction(createPieVisFn(visualizationDependencies)); + expressions.registerFunction(createKbnVislibVisTypesFn()); + expressions.registerFunction(createPieVisFn()); [ createHistogramVisTypeDefinition, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts b/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts index 810ddeea738341..d8f9fbf7d756ae 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts @@ -31,25 +31,25 @@ export type Positions = $Values; const getPositions = () => [ { - text: i18n.translate('kbnVislibVisTypes.legendPositions.topText', { + text: i18n.translate('visTypeVislib.legendPositions.topText', { defaultMessage: 'Top', }), value: Positions.TOP, }, { - text: i18n.translate('kbnVislibVisTypes.legendPositions.leftText', { + text: i18n.translate('visTypeVislib.legendPositions.leftText', { defaultMessage: 'Left', }), value: Positions.LEFT, }, { - text: i18n.translate('kbnVislibVisTypes.legendPositions.rightText', { + text: i18n.translate('visTypeVislib.legendPositions.rightText', { defaultMessage: 'Right', }), value: Positions.RIGHT, }, { - text: i18n.translate('kbnVislibVisTypes.legendPositions.bottomText', { + text: i18n.translate('visTypeVislib.legendPositions.bottomText', { defaultMessage: 'Bottom', }), value: Positions.BOTTOM, @@ -65,19 +65,19 @@ export type ChartTypes = $Values; const getChartTypes = () => [ { - text: i18n.translate('kbnVislibVisTypes.chartTypes.lineText', { + text: i18n.translate('visTypeVislib.chartTypes.lineText', { defaultMessage: 'Line', }), value: ChartTypes.LINE, }, { - text: i18n.translate('kbnVislibVisTypes.chartTypes.areaText', { + text: i18n.translate('visTypeVislib.chartTypes.areaText', { defaultMessage: 'Area', }), value: ChartTypes.AREA, }, { - text: i18n.translate('kbnVislibVisTypes.chartTypes.barText', { + text: i18n.translate('visTypeVislib.chartTypes.barText', { defaultMessage: 'Bar', }), value: ChartTypes.HISTOGRAM, @@ -92,13 +92,13 @@ export type ChartModes = $Values; const getChartModes = () => [ { - text: i18n.translate('kbnVislibVisTypes.chartModes.normalText', { + text: i18n.translate('visTypeVislib.chartModes.normalText', { defaultMessage: 'Normal', }), value: ChartModes.NORMAL, }, { - text: i18n.translate('kbnVislibVisTypes.chartModes.stackedText', { + text: i18n.translate('visTypeVislib.chartModes.stackedText', { defaultMessage: 'Stacked', }), value: ChartModes.STACKED, @@ -114,19 +114,19 @@ export type InterpolationModes = $Values; const getInterpolationModes = () => [ { - text: i18n.translate('kbnVislibVisTypes.interpolationModes.straightText', { + text: i18n.translate('visTypeVislib.interpolationModes.straightText', { defaultMessage: 'Straight', }), value: InterpolationModes.LINEAR, }, { - text: i18n.translate('kbnVislibVisTypes.interpolationModes.smoothedText', { + text: i18n.translate('visTypeVislib.interpolationModes.smoothedText', { defaultMessage: 'Smoothed', }), value: InterpolationModes.CARDINAL, }, { - text: i18n.translate('kbnVislibVisTypes.interpolationModes.steppedText', { + text: i18n.translate('visTypeVislib.interpolationModes.steppedText', { defaultMessage: 'Stepped', }), value: InterpolationModes.STEP_AFTER, @@ -148,19 +148,19 @@ export type ScaleTypes = $Values; const getScaleTypes = () => [ { - text: i18n.translate('kbnVislibVisTypes.scaleTypes.linearText', { + text: i18n.translate('visTypeVislib.scaleTypes.linearText', { defaultMessage: 'Linear', }), value: ScaleTypes.LINEAR, }, { - text: i18n.translate('kbnVislibVisTypes.scaleTypes.logText', { + text: i18n.translate('visTypeVislib.scaleTypes.logText', { defaultMessage: 'Log', }), value: ScaleTypes.LOG, }, { - text: i18n.translate('kbnVislibVisTypes.scaleTypes.squareRootText', { + text: i18n.translate('visTypeVislib.scaleTypes.squareRootText', { defaultMessage: 'Square root', }), value: ScaleTypes.SQUARE_ROOT, @@ -177,25 +177,25 @@ export type AxisModes = $Values; const getAxisModes = () => [ { - text: i18n.translate('kbnVislibVisTypes.axisModes.normalText', { + text: i18n.translate('visTypeVislib.axisModes.normalText', { defaultMessage: 'Normal', }), value: AxisModes.NORMAL, }, { - text: i18n.translate('kbnVislibVisTypes.axisModes.percentageText', { + text: i18n.translate('visTypeVislib.axisModes.percentageText', { defaultMessage: 'Percentage', }), value: AxisModes.PERCENTAGE, }, { - text: i18n.translate('kbnVislibVisTypes.axisModes.wiggleText', { + text: i18n.translate('visTypeVislib.axisModes.wiggleText', { defaultMessage: 'Wiggle', }), value: AxisModes.WIGGLE, }, { - text: i18n.translate('kbnVislibVisTypes.axisModes.silhouetteText', { + text: i18n.translate('visTypeVislib.axisModes.silhouetteText', { defaultMessage: 'Silhouette', }), value: AxisModes.SILHOUETTE, @@ -219,19 +219,19 @@ export type ThresholdLineStyles = $Values; const getThresholdLineStyles = () => [ { value: ThresholdLineStyles.FULL, - text: i18n.translate('kbnVislibVisTypes.thresholdLine.style.fullText', { + text: i18n.translate('visTypeVislib.thresholdLine.style.fullText', { defaultMessage: 'Full', }), }, { value: ThresholdLineStyles.DASHED, - text: i18n.translate('kbnVislibVisTypes.thresholdLine.style.dashedText', { + text: i18n.translate('visTypeVislib.thresholdLine.style.dashedText', { defaultMessage: 'Dashed', }), }, { value: ThresholdLineStyles.DOT_DASHED, - text: i18n.translate('kbnVislibVisTypes.thresholdLine.style.dotdashedText', { + text: i18n.translate('visTypeVislib.thresholdLine.style.dotdashedText', { defaultMessage: 'Dot-dashed', }), }, @@ -239,19 +239,19 @@ const getThresholdLineStyles = () => [ const getRotateOptions = () => [ { - text: i18n.translate('kbnVislibVisTypes.categoryAxis.rotate.horizontalText', { + text: i18n.translate('visTypeVislib.categoryAxis.rotate.horizontalText', { defaultMessage: 'Horizontal', }), value: Rotates.HORIZONTAL, }, { - text: i18n.translate('kbnVislibVisTypes.categoryAxis.rotate.verticalText', { + text: i18n.translate('visTypeVislib.categoryAxis.rotate.verticalText', { defaultMessage: 'Vertical', }), value: Rotates.VERTICAL, }, { - text: i18n.translate('kbnVislibVisTypes.categoryAxis.rotate.angledText', { + text: i18n.translate('visTypeVislib.categoryAxis.rotate.angledText', { defaultMessage: 'Angled', }), value: Rotates.ANGLED, @@ -273,13 +273,13 @@ export type ColorModes = $Values; const getGaugeTypes = () => [ { - text: i18n.translate('kbnVislibVisTypes.gauge.gaugeTypes.arcText', { + text: i18n.translate('visTypeVislib.gauge.gaugeTypes.arcText', { defaultMessage: 'Arc', }), value: GaugeTypes.ARC, }, { - text: i18n.translate('kbnVislibVisTypes.gauge.gaugeTypes.circleText', { + text: i18n.translate('visTypeVislib.gauge.gaugeTypes.circleText', { defaultMessage: 'Circle', }), value: GaugeTypes.CIRCLE, @@ -295,19 +295,19 @@ export type Alignments = $Values; const getAlignments = () => [ { - text: i18n.translate('kbnVislibVisTypes.gauge.alignmentAutomaticTitle', { + text: i18n.translate('visTypeVislib.gauge.alignmentAutomaticTitle', { defaultMessage: 'Automatic', }), value: Alignments.AUTOMATIC, }, { - text: i18n.translate('kbnVislibVisTypes.gauge.alignmentHorizontalTitle', { + text: i18n.translate('visTypeVislib.gauge.alignmentHorizontalTitle', { defaultMessage: 'Horizontal', }), value: Alignments.HORIZONTAL, }, { - text: i18n.translate('kbnVislibVisTypes.gauge.alignmentVerticalTitle', { + text: i18n.translate('visTypeVislib.gauge.alignmentVerticalTitle', { defaultMessage: 'Vertical', }), value: Alignments.VERTICAL, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/utils/common_config.tsx b/src/legacy/core_plugins/vis_type_vislib/public/utils/common_config.tsx index adb93ca8011b2e..e2f6ba0d8b5620 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/utils/common_config.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/utils/common_config.tsx @@ -29,7 +29,7 @@ function getAreaOptionTabs() { return [ { name: 'advanced', - title: i18n.translate('kbnVislibVisTypes.area.tabs.metricsAxesTitle', { + title: i18n.translate('visTypeVislib.area.tabs.metricsAxesTitle', { defaultMessage: 'Metrics & axes', }), editor: (props: VisOptionsProps) => ( @@ -38,7 +38,7 @@ function getAreaOptionTabs() { }, { name: 'options', - title: i18n.translate('kbnVislibVisTypes.area.tabs.panelSettingsTitle', { + title: i18n.translate('visTypeVislib.area.tabs.panelSettingsTitle', { defaultMessage: 'Panel settings', }), editor: (props: VisOptionsProps) => ( @@ -48,7 +48,7 @@ function getAreaOptionTabs() { ]; } -const countLabel = i18n.translate('kbnVislibVisTypes.area.countText', { +const countLabel = i18n.translate('visTypeVislib.area.countText', { defaultMessage: 'Count', }); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx b/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx index cff9a0a2e85519..ca49f17e7c264d 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx @@ -20,12 +20,13 @@ import $ from 'jquery'; import React, { RefObject } from 'react'; -import { CUSTOM_LEGEND_VIS_TYPES, VisLegend, Vis, VisParams } from './legacy_imports'; +import { Vis, VisParams } from './legacy_imports'; // @ts-ignore import { Vis as Vislib } from './vislib/vis'; import { Positions } from './utils/collections'; import { KbnVislibVisTypesDependencies } from './plugin'; import { mountReactNode } from '../../../../core/public/utils'; +import { VisLegend, CUSTOM_LEGEND_VIS_TYPES } from './vislib/components/legend'; const legendClassName = { top: 'visLib--legend-top', @@ -76,9 +77,6 @@ export const createVislibVisController = (deps: KbnVislibVisTypesDependencies) = return resolve(); } - await deps.initializeHierarchicalTooltipFormatter(); - await deps.initializePointSeriesTooltipFormatter(); - this.vislibVis = new Vislib(this.chartEl, visParams, deps); this.vislibVis.on('brush', this.vis.API.events.brush); this.vislibVis.on('click', this.vis.API.events.filter); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts b/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts index 0a685cd70e0895..1f6c0d87b85205 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts @@ -24,7 +24,8 @@ import { KibanaDatatable, Render, } from '../../../../plugins/expressions/public'; -import { KbnVislibVisTypesDependencies } from './plugin'; +// @ts-ignore +import { vislibSeriesResponseHandler } from './vislib/response_handler'; const name = 'vislib'; @@ -42,17 +43,20 @@ interface RenderValue { visConfig: VisParams; } -type Return = Promise>; +type Return = Render; -export const createKbnVislibVisTypesFn = ( - deps: KbnVislibVisTypesDependencies -) => (): ExpressionFunction => ({ +export const createKbnVislibVisTypesFn = () => (): ExpressionFunction< + typeof name, + Context, + Arguments, + Return +> => ({ name: 'vislib', type: 'render', context: { types: ['kibana_datatable'], }, - help: i18n.translate('kbnVislibVisTypes.functions.vislib.help', { + help: i18n.translate('visTypeVislib.functions.vislib.help', { defaultMessage: 'Vislib visualization', }), args: { @@ -67,11 +71,9 @@ export const createKbnVislibVisTypesFn = ( help: '', }, }, - async fn(context, args) { - const responseHandler = deps.vislibSeriesResponseHandlerProvider().handler; + fn(context, args) { const visConfigParams = JSON.parse(args.visConfig); - - const convertedData = await responseHandler(context, visConfigParams.dimensions); + const convertedData = vislibSeriesResponseHandler(context, visConfigParams.dimensions); return { type: 'render', diff --git a/src/legacy/ui/public/vis/components/tooltip/__tests__/_tooltip_formatter.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/_tooltip_formatter.js similarity index 88% rename from src/legacy/ui/public/vis/components/tooltip/__tests__/_tooltip_formatter.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/_tooltip_formatter.js index d0cfab0b54f794..a3aabcb90be624 100644 --- a/src/legacy/ui/public/vis/components/tooltip/__tests__/_tooltip_formatter.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/_tooltip_formatter.js @@ -20,18 +20,11 @@ import _ from 'lodash'; import $ from 'jquery'; import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { PointSeriesTooltipFormatterProvider } from '../_pointseries_tooltip_formatter'; -describe('tooltipFormatter', function() { - let tooltipFormatter; +import { pointSeriesTooltipFormatter } from '../../components/tooltip'; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private) { - tooltipFormatter = Private(PointSeriesTooltipFormatterProvider)(); - }) - ); +describe('tooltipFormatter', function() { + const tooltipFormatter = pointSeriesTooltipFormatter(); function cell($row, i) { return $row diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/heatmap_color.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/heatmap_color.js index 36c5b60abf5c6b..c7ffc843876e37 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/heatmap_color.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/heatmap_color.js @@ -18,7 +18,6 @@ */ import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; import { getHeatmapColors } from '../../../legacy_imports'; @@ -27,8 +26,6 @@ describe('Vislib Heatmap Color Module Test Suite', function() { const nullValue = null; let notAValue; - beforeEach(ngMock.module('kibana')); - it('should throw an error if schema is invalid', function() { expect(function() { getHeatmapColors(4, 'invalid schema'); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/labels.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/labels.js index 55d629adaf2459..db99b881a6e380 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/labels.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/labels.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; + import { labels } from '../../components/labels/labels'; import { dataArray } from '../../components/labels/data_array'; import { uniqLabels } from '../../components/labels/uniq_labels'; @@ -161,21 +161,18 @@ const columnsData = { describe('Vislib Labels Module Test Suite', function() { let uniqSeriesLabels; describe('Labels (main)', function() { - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - seriesLabels = labels(seriesData); - rowsLabels = labels(rowsData); - seriesArr = Array.isArray(seriesLabels); - rowsArr = Array.isArray(rowsLabels); - uniqSeriesLabels = _.chain(rowsData.rows) - .pluck('series') - .flattenDeep() - .pluck('label') - .uniq() - .value(); - }) - ); + beforeEach(() => { + seriesLabels = labels(seriesData); + rowsLabels = labels(rowsData); + seriesArr = Array.isArray(seriesLabels); + rowsArr = Array.isArray(rowsLabels); + uniqSeriesLabels = _.chain(rowsData.rows) + .pluck('series') + .flattenDeep() + .pluck('label') + .uniq() + .value(); + }); it('should be a function', function() { expect(typeof labels).to.be('function'); @@ -224,15 +221,12 @@ describe('Vislib Labels Module Test Suite', function() { let testSeries; let testRows; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - seriesLabels = dataArray(seriesData); - rowsLabels = dataArray(rowsData); - testSeries = Array.isArray(seriesLabels); - testRows = Array.isArray(rowsLabels); - }) - ); + beforeEach(() => { + seriesLabels = dataArray(seriesData); + rowsLabels = dataArray(rowsData); + testSeries = Array.isArray(seriesLabels); + testRows = Array.isArray(rowsLabels); + }); it('should throw an error if the input is not an object', function() { expect(function() { @@ -333,15 +327,12 @@ describe('Vislib Labels Module Test Suite', function() { let uniq; let testArr; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - uniq = uniqLabels(arrObj, function(d) { - return d; - }); - testArr = Array.isArray(uniq); - }) - ); + beforeEach(() => { + uniq = uniqLabels(arrObj, function(d) { + return d; + }); + testArr = Array.isArray(uniq); + }); it('should throw an error if input is not an array', function() { expect(function() { @@ -407,15 +398,12 @@ describe('Vislib Labels Module Test Suite', function() { let columnsArr; let rowsArr; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - columnsLabels = getSeries(columnsData); - rowsLabels = getSeries(rowsData); - columnsArr = Array.isArray(columnsLabels); - rowsArr = Array.isArray(rowsLabels); - }) - ); + beforeEach(() => { + columnsLabels = getSeries(columnsData); + rowsLabels = getSeries(rowsData); + columnsArr = Array.isArray(columnsLabels); + rowsArr = Array.isArray(rowsLabels); + }); it('should throw an error if input is not an object', function() { expect(function() { diff --git a/src/legacy/ui/public/vis/components/tooltip/__tests__/positioning.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/positioning.js similarity index 99% rename from src/legacy/ui/public/vis/components/tooltip/__tests__/positioning.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/positioning.js index 89d547f2377bab..f1c80c99810204 100644 --- a/src/legacy/ui/public/vis/components/tooltip/__tests__/positioning.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/positioning.js @@ -21,7 +21,8 @@ import expect from '@kbn/expect'; import $ from 'jquery'; import _ from 'lodash'; import sinon from 'sinon'; -import { positionTooltip } from '../position_tooltip'; + +import { positionTooltip } from '../../components/tooltip/position_tooltip'; describe('Tooltip Positioning', function() { const sandbox = sinon.createSandbox(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/index.js index e30ca17a1fce7a..734c6d003278fd 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/index.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/index.js @@ -19,18 +19,15 @@ import _ from 'lodash'; import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; + import VislibProvider from '..'; describe('Vislib Index Test Suite', function() { let vislib; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private) { - vislib = Private(VislibProvider); - }) - ); + beforeEach(() => { + vislib = new VislibProvider(); + }); it('should return an object', function() { expect(_.isObject(vislib)).to.be(true); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis/axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis/axis.js index 3081c124150765..bc4a4f9925513c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis/axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis/axis.js @@ -19,17 +19,15 @@ import d3 from 'd3'; import _ from 'lodash'; -import ngMock from 'ng_mock'; -import 'ui/persisted_state'; - import expect from '@kbn/expect'; import $ from 'jquery'; import { Axis } from '../../../lib/axis'; import { VisConfig } from '../../../lib/vis_config'; +import { getMockUiState } from '../fixtures/_vis_fixture'; describe('Vislib Axis Class Test Suite', function() { - let persistedState; + let mockUiState; let yAxis; let el; let fixture; @@ -102,38 +100,34 @@ describe('Vislib Axis Class Test Suite', function() { yAxisLabel: 'Count', }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function($injector) { - persistedState = new ($injector.get('PersistedState'))(); - - el = d3 - .select('body') - .append('div') - .attr('class', 'visAxis--x') - .style('height', '40px'); + beforeEach(() => { + mockUiState = getMockUiState(); + el = d3 + .select('body') + .append('div') + .attr('class', 'visAxis--x') + .style('height', '40px'); - fixture = el.append('div').attr('class', 'x-axis-div'); + fixture = el.append('div').attr('class', 'x-axis-div'); - const visConfig = new VisConfig( - { - type: 'histogram', - }, - data, - persistedState, - $('.x-axis-div')[0], - () => undefined - ); - yAxis = new Axis(visConfig, { - type: 'value', - id: 'ValueAxis-1', - }); + const visConfig = new VisConfig( + { + type: 'histogram', + }, + data, + mockUiState, + $('.x-axis-div')[0], + () => undefined + ); + yAxis = new Axis(visConfig, { + type: 'value', + id: 'ValueAxis-1', + }); - seriesData = data.series.map(series => { - return series.values; - }); - }) - ); + seriesData = data.series.map(series => { + return series.values; + }); + }); afterEach(function() { fixture.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis_title.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis_title.js index cbb294c3b44e4e..fd25335dd2cd4c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis_title.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis_title.js @@ -20,18 +20,15 @@ import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; -import ngMock from 'ng_mock'; - import expect from '@kbn/expect'; -import 'ui/persisted_state'; import { AxisTitle } from '../../lib/axis/axis_title'; import { AxisConfig } from '../../lib/axis/axis_config'; import { VisConfig } from '../../lib/vis_config'; import { Data } from '../../lib/data'; +import { getMockUiState } from './fixtures/_vis_fixture'; describe('Vislib AxisTitle Class Test Suite', function() { - let PersistedState; let el; let dataObj; let xTitle; @@ -96,56 +93,53 @@ describe('Vislib AxisTitle Class Test Suite', function() { yAxisLabel: 'Count', }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function($injector) { - PersistedState = $injector.get('PersistedState'); - - el = d3 - .select('body') - .append('div') - .attr('class', 'visWrapper'); - - el.append('div') - .attr('class', 'visAxis__column--bottom') - .append('div') - .attr('class', 'axis-title y-axis-title') - .style('height', '20px') - .style('width', '20px'); - - el.append('div') - .attr('class', 'visAxis__column--left') - .append('div') - .attr('class', 'axis-title x-axis-title') - .style('height', '20px') - .style('width', '20px'); - - dataObj = new Data(data, new PersistedState(), () => undefined); - visConfig = new VisConfig( - { - type: 'histogram', - }, - data, - new PersistedState(), - el.node(), - () => undefined - ); - const xAxisConfig = new AxisConfig(visConfig, { - position: 'bottom', - title: { - text: dataObj.get('xAxisLabel'), - }, - }); - const yAxisConfig = new AxisConfig(visConfig, { - position: 'left', - title: { - text: dataObj.get('yAxisLabel'), - }, - }); - xTitle = new AxisTitle(xAxisConfig); - yTitle = new AxisTitle(yAxisConfig); - }) - ); + beforeEach(() => { + el = d3 + .select('body') + .append('div') + .attr('class', 'visWrapper'); + + el.append('div') + .attr('class', 'visAxis__column--bottom') + .append('div') + .attr('class', 'axis-title y-axis-title') + .style('height', '20px') + .style('width', '20px'); + + el.append('div') + .attr('class', 'visAxis__column--left') + .append('div') + .attr('class', 'axis-title x-axis-title') + .style('height', '20px') + .style('width', '20px'); + + const uiState = getMockUiState(); + uiState.set('vis.colors', []); + dataObj = new Data(data, getMockUiState(), () => undefined); + visConfig = new VisConfig( + { + type: 'histogram', + }, + data, + getMockUiState(), + el.node(), + () => undefined + ); + const xAxisConfig = new AxisConfig(visConfig, { + position: 'bottom', + title: { + text: dataObj.get('xAxisLabel'), + }, + }); + const yAxisConfig = new AxisConfig(visConfig, { + position: 'left', + title: { + text: dataObj.get('yAxisLabel'), + }, + }); + xTitle = new AxisTitle(xAxisConfig); + yTitle = new AxisTitle(yAxisConfig); + }); afterEach(function() { el.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/chart_title.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/chart_title.js index b2086d0749a419..b65571becd83c6 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/chart_title.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/chart_title.js @@ -19,14 +19,14 @@ import d3 from 'd3'; import _ from 'lodash'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import { ChartTitle } from '../../lib/chart_title'; import { VisConfig } from '../../lib/vis_config'; +import { getMockUiState } from './fixtures/_vis_fixture'; describe('Vislib ChartTitle Class Test Suite', function() { - let persistedState; + let mockUiState; let chartTitle; let el; const data = { @@ -88,36 +88,32 @@ describe('Vislib ChartTitle Class Test Suite', function() { yAxisLabel: 'Count', }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function($injector) { - persistedState = new ($injector.get('PersistedState'))(); + beforeEach(() => { + mockUiState = getMockUiState(); + el = d3 + .select('body') + .append('div') + .attr('class', 'visWrapper') + .datum(data); - el = d3 - .select('body') - .append('div') - .attr('class', 'visWrapper') - .datum(data); + el.append('div') + .attr('class', 'chart-title') + .style('height', '20px'); - el.append('div') - .attr('class', 'chart-title') - .style('height', '20px'); - - const visConfig = new VisConfig( - { - type: 'histogram', - title: { - text: 'rows', - }, + const visConfig = new VisConfig( + { + type: 'histogram', + title: { + text: 'rows', }, - data, - persistedState, - el.node(), - () => undefined - ); - chartTitle = new ChartTitle(visConfig); - }) - ); + }, + data, + mockUiState, + el.node(), + () => undefined + ); + chartTitle = new ChartTitle(visConfig); + }); afterEach(function() { el.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/data.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/data.js index 5811b1d238163a..d4ec6f363a75b0 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/data.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/data.js @@ -18,11 +18,10 @@ */ import _ from 'lodash'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import 'ui/persisted_state'; import { Data } from '../../lib/data'; +import { getMockUiState } from './fixtures/_vis_fixture'; const seriesData = { label: '', @@ -153,14 +152,11 @@ const colsData = { }; describe('Vislib Data Class Test Suite', function() { - let persistedState; + let mockUiState; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function($injector) { - persistedState = new ($injector.get('PersistedState'))(); - }) - ); + beforeEach(() => { + mockUiState = getMockUiState(); + }); describe('Data Class (main)', function() { it('should be a function', function() { @@ -168,7 +164,7 @@ describe('Vislib Data Class Test Suite', function() { }); it('should return an object', function() { - const rowIn = new Data(rowsData, persistedState, () => undefined); + const rowIn = new Data(rowsData, mockUiState, () => undefined); expect(_.isObject(rowIn)).to.be(true); }); }); @@ -182,7 +178,7 @@ describe('Vislib Data Class Test Suite', function() { }; beforeEach(function() { - data = new Data(pieData, persistedState, () => undefined); + data = new Data(pieData, mockUiState, () => undefined); }); it('should remove zero values', function() { @@ -196,7 +192,7 @@ describe('Vislib Data Class Test Suite', function() { let serOut; beforeEach(function() { - serIn = new Data(seriesData, persistedState, () => undefined); + serIn = new Data(seriesData, mockUiState, () => undefined); serOut = serIn.flatten(); }); @@ -210,7 +206,7 @@ describe('Vislib Data Class Test Suite', function() { function testLength(inputData) { return function() { - const data = new Data(inputData, persistedState, () => undefined); + const data = new Data(inputData, mockUiState, () => undefined); const len = _.reduce( data.chartData(), function(sum, chart) { @@ -266,7 +262,7 @@ describe('Vislib Data Class Test Suite', function() { }; beforeEach(function() { - data = new Data(geohashGridData, persistedState, () => undefined); + data = new Data(geohashGridData, mockUiState, () => undefined); }); describe('getVisData', function() { @@ -287,7 +283,7 @@ describe('Vislib Data Class Test Suite', function() { describe('null value check', function() { it('should return false', function() { - const data = new Data(rowsData, persistedState, () => undefined); + const data = new Data(rowsData, mockUiState, () => undefined); expect(data.hasNullValues()).to.be(false); }); @@ -307,7 +303,7 @@ describe('Vislib Data Class Test Suite', function() { ], }); - const data = new Data(nullRowData, persistedState, () => undefined); + const data = new Data(nullRowData, mockUiState, () => undefined); expect(data.hasNullValues()).to.be(true); }); }); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch.js index a93db5637c89d9..760c2e80d84284 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch.js @@ -19,14 +19,12 @@ import _ from 'lodash'; import d3 from 'd3'; -import ngMock from 'ng_mock'; - import expect from '@kbn/expect'; -import 'ui/persisted_state'; // Data import data from './fixtures/mock_data/date_histogram/_series'; -import getFixturesVislibVisFixtureProvider from './fixtures/_vis_fixture'; + +import { getVis, getMockUiState } from './fixtures/_vis_fixture'; import { SimpleEmitter } from '../../../legacy_imports'; describe('Vislib Dispatch Class Test Suite', function() { @@ -44,17 +42,13 @@ describe('Vislib Dispatch Class Test Suite', function() { describe('', function() { let vis; - let persistedState; - - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(); - persistedState = new ($injector.get('PersistedState'))(); - vis.render(data, persistedState); - }) - ); + let mockUiState; + + beforeEach(() => { + vis = getVis(); + mockUiState = getMockUiState(); + vis.render(data, mockUiState); + }); afterEach(function() { destroyVis(vis); @@ -71,18 +65,14 @@ describe('Vislib Dispatch Class Test Suite', function() { describe('Stock event handlers', function() { let vis; - let persistedState; - - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - persistedState = new ($injector.get('PersistedState'))(); - vis = getVis(); - vis.on('brush', _.noop); - vis.render(data, persistedState); - }) - ); + let mockUiState; + + beforeEach(() => { + mockUiState = getMockUiState(); + vis = getVis(); + vis.on('brush', _.noop); + vis.render(data, mockUiState); + }); afterEach(function() { destroyVis(vis); @@ -187,42 +177,30 @@ describe('Vislib Dispatch Class Test Suite', function() { describe('Custom event handlers', function() { it('should attach whatever gets passed on vis.on() to chart.events', function(done) { - let vis; - let persistedState; - ngMock.module('kibana'); - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(); - persistedState = new ($injector.get('PersistedState'))(); - vis.on('someEvent', _.noop); - vis.render(data, persistedState); - - vis.handler.charts.forEach(function(chart) { - expect(chart.events.listenerCount('someEvent')).to.be(1); - }); + const vis = getVis(); + const mockUiState = getMockUiState(); + vis.on('someEvent', _.noop); + vis.render(data, mockUiState); - destroyVis(vis); - done(); + vis.handler.charts.forEach(function(chart) { + expect(chart.events.listenerCount('someEvent')).to.be(1); }); + + destroyVis(vis); + done(); }); it('can be added after rendering', function() { - let vis; - let persistedState; - ngMock.module('kibana'); - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(); - persistedState = new ($injector.get('PersistedState'))(); - vis.render(data, persistedState); - vis.on('someEvent', _.noop); - - vis.handler.charts.forEach(function(chart) { - expect(chart.events.listenerCount('someEvent')).to.be(1); - }); + const vis = getVis(); + const mockUiState = getMockUiState(); + vis.render(data, mockUiState); + vis.on('someEvent', _.noop); - destroyVis(vis); + vis.handler.charts.forEach(function(chart) { + expect(chart.events.listenerCount('someEvent')).to.be(1); }); + + destroyVis(vis); }); }); }); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/error_handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/error_handler.js index 244386c1b51e67..4523e70ccbb4cb 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/error_handler.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/error_handler.js @@ -18,18 +18,15 @@ */ import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; + import { ErrorHandler } from '../../lib/_error_handler'; describe('Vislib ErrorHandler Test Suite', function() { let errorHandler; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - errorHandler = new ErrorHandler(); - }) - ); + beforeEach(() => { + errorHandler = new ErrorHandler(); + }); describe('validateWidthandHeight Method', function() { it('should throw an error when width and/or height is 0', function() { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/_vis_fixture.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/_vis_fixture.js index c49ca732f09159..966cac4c2b2f55 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/_vis_fixture.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/_vis_fixture.js @@ -20,23 +20,10 @@ import _ from 'lodash'; import $ from 'jquery'; -import { Vis } from '../../../vis'; - -// TODO: remove legacy imports when/of converting tests to jest -import { - setHierarchicalTooltipFormatter, - getHierarchicalTooltipFormatter, -} from 'ui/vis/components/tooltip/_hierarchical_tooltip_formatter'; -import { - setPointSeriesTooltipFormatter, - getPointSeriesTooltipFormatter, -} from 'ui/vis/components/tooltip/_pointseries_tooltip_formatter'; -import { - vislibSeriesResponseHandlerProvider, - vislibSlicesResponseHandlerProvider, -} from 'ui/vis/response_handlers/vislib'; import { vislibColor } from 'ui/vis/components/color/color'; +import { Vis } from '../../../vis'; + const $visCanvas = $('
') .attr('id', 'vislib-vis-fixtures') .css({ @@ -73,29 +60,31 @@ const getDeps = () => { return { uiSettings, vislibColor, - getHierarchicalTooltipFormatter, - getPointSeriesTooltipFormatter, - vislibSeriesResponseHandlerProvider, - vislibSlicesResponseHandlerProvider, }; }; -export default function getVislibFixtures(Private) { - setHierarchicalTooltipFormatter(Private); - setPointSeriesTooltipFormatter(Private); +export const getMockUiState = () => { + const map = new Map(); - return function(visLibParams, element) { - return new Vis( - element || $visCanvas.new(), - _.defaults({}, visLibParams || {}, { - addTooltip: true, - addLegend: true, - defaultYExtents: false, - setYExtents: false, - yAxis: {}, - type: 'histogram', - }), - getDeps() - ); - }; + return (() => ({ + get: (...args) => map.get(...args), + set: (...args) => map.set(...args), + setSilent: (...args) => map.set(...args), + on: () => undefined, + }))(); +}; + +export function getVis(visLibParams, element) { + return new Vis( + element || $visCanvas.new(), + _.defaults({}, visLibParams || {}, { + addTooltip: true, + addLegend: true, + defaultYExtents: false, + setYExtents: false, + yAxis: {}, + type: 'histogram', + }), + getDeps() + ); } diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/handler/handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/handler/handler.js index b309c97d240006..8e25015c101860 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/handler/handler.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/handler/handler.js @@ -17,36 +17,29 @@ * under the License. */ -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; +import $ from 'jquery'; // Data import series from '../fixtures/mock_data/date_histogram/_series'; import columns from '../fixtures/mock_data/date_histogram/_columns'; import rows from '../fixtures/mock_data/date_histogram/_rows'; import stackedSeries from '../fixtures/mock_data/date_histogram/_stacked_series'; -import $ from 'jquery'; -import 'ui/persisted_state'; -import getFixturesVislibVisFixtureProvider from '../fixtures/_vis_fixture'; +import { getVis, getMockUiState } from '../fixtures/_vis_fixture'; + const dateHistogramArray = [series, columns, rows, stackedSeries]; const names = ['series', 'columns', 'rows', 'stackedSeries']; dateHistogramArray.forEach(function(data, i) { describe('Vislib Handler Test Suite for ' + names[i] + ' Data', function() { - let vis; - let persistedState; const events = ['click', 'brush']; + let vis; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(); - persistedState = new ($injector.get('PersistedState'))(); - vis.render(data, persistedState); - }) - ); + beforeEach(() => { + vis = getVis(); + vis.render(data, getMockUiState()); + }); afterEach(function() { vis.destroy(); @@ -107,9 +100,7 @@ dateHistogramArray.forEach(function(data, i) { describe('removeAll Method', function() { beforeEach(function() { - ngMock.inject(function() { - vis.handler.removeAll(vis.element); - }); + vis.handler.removeAll(vis.element); }); it('should remove all DOM elements from the el', function() { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout.js index c8636f34ce6f8f..f72794e27e834a 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout.js @@ -18,18 +18,17 @@ */ import d3 from 'd3'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import 'ui/persisted_state'; +import $ from 'jquery'; // Data import series from '../fixtures/mock_data/date_histogram/_series'; import columns from '../fixtures/mock_data/date_histogram/_columns'; import rows from '../fixtures/mock_data/date_histogram/_rows'; import stackedSeries from '../fixtures/mock_data/date_histogram/_stacked_series'; -import $ from 'jquery'; + import { Layout } from '../../../lib/layout/layout'; -import getFixturesVislibVisFixtureProvider from '../fixtures/_vis_fixture'; +import { getVis, getMockUiState } from '../fixtures/_vis_fixture'; import { VisConfig } from '../../../lib/vis_config'; const dateHistogramArray = [series, columns, rows, stackedSeries]; @@ -38,23 +37,18 @@ const names = ['series', 'columns', 'rows', 'stackedSeries']; dateHistogramArray.forEach(function(data, i) { describe('Vislib Layout Class Test Suite for ' + names[i] + ' Data', function() { let vis; - let persistedState; + let mockUiState; let numberOfCharts; let testLayout; - beforeEach(ngMock.module('kibana')); - - beforeEach(function() { - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(); - persistedState = new ($injector.get('PersistedState'))(); - vis.render(data, persistedState); - numberOfCharts = vis.handler.charts.length; - }); + beforeEach(() => { + vis = getVis(); + mockUiState = getMockUiState(); + vis.render(data, mockUiState); + numberOfCharts = vis.handler.charts.length; }); - afterEach(function() { + afterEach(() => { vis.destroy(); }); @@ -81,7 +75,7 @@ dateHistogramArray.forEach(function(data, i) { type: 'histogram', }, data, - persistedState, + mockUiState, vis.element, () => undefined ); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout_types.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout_types.js index 4dc52309c76fde..cc6d33a2d98daf 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout_types.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout_types.js @@ -18,19 +18,16 @@ */ import _ from 'lodash'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; + import { layoutTypes as layoutType } from '../../../lib/layout/layout_types'; describe('Vislib Layout Types Test Suite', function() { let layoutFunc; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - layoutFunc = layoutType.point_series; - }) - ); + beforeEach(() => { + layoutFunc = layoutType.point_series; + }); it('should be an object', function() { expect(_.isObject(layoutType)).to.be(true); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js index 2626fd3ace2b0d..3942aa18891b84 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js @@ -18,9 +18,9 @@ */ import d3 from 'd3'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import $ from 'jquery'; + import { chartSplit } from '../../../../../lib/layout/splits/column_chart/chart_split'; import { chartTitleSplit } from '../../../../../lib/layout/splits/column_chart/chart_title_split'; import { xAxisSplit } from '../../../../../lib/layout/splits/column_chart/x_axis_split'; @@ -150,16 +150,13 @@ describe('Vislib Split Function Test Suite', function() { ], }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - el = d3 - .select('body') - .append('div') - .attr('class', 'visualization') - .datum(data); - }) - ); + beforeEach(() => { + el = d3 + .select('body') + .append('div') + .attr('class', 'visualization') + .datum(data); + }); afterEach(function() { el.remove(); @@ -168,11 +165,9 @@ describe('Vislib Split Function Test Suite', function() { describe('chart split function', function() { let fixture; - beforeEach( - ngMock.inject(function() { - fixture = d3.select('.visualization').call(chartSplit); - }) - ); + beforeEach(function() { + fixture = d3.select('.visualization').call(chartSplit); + }); afterEach(function() { fixture.remove(); @@ -192,28 +187,26 @@ describe('Vislib Split Function Test Suite', function() { let newEl; let fixture; - beforeEach( - ngMock.inject(function() { - visEl = el.append('div').attr('class', 'visWrapper'); - visEl.append('div').attr('class', 'visAxis__splitTitles--x'); - visEl.append('div').attr('class', 'visAxis__splitTitles--y'); - visEl.select('.visAxis__splitTitles--x').call(chartTitleSplit); - visEl.select('.visAxis__splitTitles--y').call(chartTitleSplit); + beforeEach(function() { + visEl = el.append('div').attr('class', 'visWrapper'); + visEl.append('div').attr('class', 'visAxis__splitTitles--x'); + visEl.append('div').attr('class', 'visAxis__splitTitles--y'); + visEl.select('.visAxis__splitTitles--x').call(chartTitleSplit); + visEl.select('.visAxis__splitTitles--y').call(chartTitleSplit); - newEl = d3 - .select('body') - .append('div') - .attr('class', 'visWrapper') - .datum({ series: [] }); + newEl = d3 + .select('body') + .append('div') + .attr('class', 'visWrapper') + .datum({ series: [] }); - newEl.append('div').attr('class', 'visAxis__splitTitles--x'); - newEl.append('div').attr('class', 'visAxis__splitTitles--y'); - newEl.select('.visAxis__splitTitles--x').call(chartTitleSplit); - newEl.select('.visAxis__splitTitles--y').call(chartTitleSplit); + newEl.append('div').attr('class', 'visAxis__splitTitles--x'); + newEl.append('div').attr('class', 'visAxis__splitTitles--y'); + newEl.select('.visAxis__splitTitles--x').call(chartTitleSplit); + newEl.select('.visAxis__splitTitles--y').call(chartTitleSplit); - fixture = newEl.selectAll(this.childNodes)[0].length; - }) - ); + fixture = newEl.selectAll(this.childNodes)[0].length; + }); afterEach(function() { newEl.remove(); @@ -237,17 +230,15 @@ describe('Vislib Split Function Test Suite', function() { let fixture; let divs; - beforeEach( - ngMock.inject(function() { - fixture = d3 - .select('body') - .append('div') - .attr('class', 'columns') - .datum({ columns: [{}, {}] }); - d3.select('.columns').call(xAxisSplit); - divs = d3.selectAll('.x-axis-div')[0]; - }) - ); + beforeEach(function() { + fixture = d3 + .select('body') + .append('div') + .attr('class', 'columns') + .datum({ columns: [{}, {}] }); + d3.select('.columns').call(xAxisSplit); + divs = d3.selectAll('.x-axis-div')[0]; + }); afterEach(function() { fixture.remove(); @@ -263,19 +254,17 @@ describe('Vislib Split Function Test Suite', function() { let fixture; let divs; - beforeEach( - ngMock.inject(function() { - fixture = d3 - .select('body') - .append('div') - .attr('class', 'rows') - .datum({ rows: [{}, {}] }); + beforeEach(function() { + fixture = d3 + .select('body') + .append('div') + .attr('class', 'rows') + .datum({ rows: [{}, {}] }); - d3.select('.rows').call(yAxisSplit); + d3.select('.rows').call(yAxisSplit); - divs = d3.selectAll('.y-axis-div')[0]; - }) - ); + divs = d3.selectAll('.y-axis-div')[0]; + }); afterEach(function() { fixture.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js index 0c744e4fa2b573..8978f80f58dde8 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js @@ -18,9 +18,9 @@ */ import d3 from 'd3'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import $ from 'jquery'; + import { chartSplit } from '../../../../../lib/layout/splits/gauge_chart/chart_split'; import { chartTitleSplit } from '../../../../../lib/layout/splits/gauge_chart/chart_title_split'; @@ -148,16 +148,13 @@ describe('Vislib Gauge Split Function Test Suite', function() { ], }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - el = d3 - .select('body') - .append('div') - .attr('class', 'visualization') - .datum(data); - }) - ); + beforeEach(function() { + el = d3 + .select('body') + .append('div') + .attr('class', 'visualization') + .datum(data); + }); afterEach(function() { el.remove(); @@ -166,11 +163,9 @@ describe('Vislib Gauge Split Function Test Suite', function() { describe('chart split function', function() { let fixture; - beforeEach( - ngMock.inject(function() { - fixture = d3.select('.visualization').call(chartSplit); - }) - ); + beforeEach(function() { + fixture = d3.select('.visualization').call(chartSplit); + }); afterEach(function() { fixture.remove(); @@ -188,15 +183,13 @@ describe('Vislib Gauge Split Function Test Suite', function() { describe('chart title split function', function() { let visEl; - beforeEach( - ngMock.inject(function() { - visEl = el.append('div').attr('class', 'visWrapper'); - visEl.append('div').attr('class', 'visAxis__splitTitles--x'); - visEl.append('div').attr('class', 'visAxis__splitTitles--y'); - visEl.select('.visAxis__splitTitles--x').call(chartTitleSplit); - visEl.select('.visAxis__splitTitles--y').call(chartTitleSplit); - }) - ); + beforeEach(function() { + visEl = el.append('div').attr('class', 'visWrapper'); + visEl.append('div').attr('class', 'visAxis__splitTitles--x'); + visEl.append('div').attr('class', 'visAxis__splitTitles--y'); + visEl.select('.visAxis__splitTitles--x').call(chartTitleSplit); + visEl.select('.visAxis__splitTitles--y').call(chartTitleSplit); + }); afterEach(function() { visEl.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/types/column_layout.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/types/column_layout.js index bdf886033d8d6f..e9c2ff0d2fa078 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/types/column_layout.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/types/column_layout.js @@ -19,8 +19,8 @@ import d3 from 'd3'; import _ from 'lodash'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; + import { layoutTypes } from '../../../../lib/layout/layout_types'; describe('Vislib Column Layout Test Suite', function() { @@ -85,16 +85,13 @@ describe('Vislib Column Layout Test Suite', function() { yAxisLabel: 'Count', }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - el = d3 - .select('body') - .append('div') - .attr('class', 'visualization'); - columnLayout = layoutTypes.point_series(el, data); - }) - ); + beforeEach(function() { + el = d3 + .select('body') + .append('div') + .attr('class', 'visualization'); + columnLayout = layoutTypes.point_series(el, data); + }); afterEach(function() { el.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/point_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/point_series.js index ee3f5a476cd9ac..03646d08298dd6 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/point_series.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/point_series.js @@ -17,12 +17,13 @@ * under the License. */ -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import { vislibPointSeriesTypes as pointSeriesConfig } from '../../../lib/types/point_series'; + import percentileTestdata from './testdata_linechart_percentile.json'; import percentileTestdataResult from './testdata_linechart_percentile_result.json'; +import { vislibPointSeriesTypes as pointSeriesConfig } from '../../../lib/types/point_series'; + describe('Point Series Config Type Class Test Suite', function() { let parsedConfig; const histogramConfig = { @@ -95,8 +96,6 @@ describe('Point Series Config Type Class Test Suite', function() { }, }; - beforeEach(ngMock.module('kibana')); - describe('histogram chart', function() { beforeEach(function() { parsedConfig = pointSeriesConfig.column(histogramConfig, data); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/vis_config.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/vis_config.js index 3f0253b4a46702..7dfd2ded36a667 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/vis_config.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/vis_config.js @@ -18,10 +18,10 @@ */ import d3 from 'd3'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import 'ui/persisted_state'; + import { VisConfig } from '../../lib/vis_config'; +import { getMockUiState } from './fixtures/_vis_fixture'; describe('Vislib VisConfig Class Test Suite', function() { let el; @@ -85,27 +85,23 @@ describe('Vislib VisConfig Class Test Suite', function() { yAxisLabel: 'Count', }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function($injector) { - const PersistedState = $injector.get('PersistedState'); - el = d3 - .select('body') - .append('div') - .attr('class', 'visWrapper') - .node(); + beforeEach(() => { + el = d3 + .select('body') + .append('div') + .attr('class', 'visWrapper') + .node(); - visConfig = new VisConfig( - { - type: 'point_series', - }, - data, - new PersistedState(), - el, - () => undefined - ); - }) - ); + visConfig = new VisConfig( + { + type: 'point_series', + }, + data, + getMockUiState(), + el, + () => undefined + ); + }); afterEach(() => { el.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/x_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/x_axis.js index 09fe067537c7f7..d42562a87b825a 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/x_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/x_axis.js @@ -19,15 +19,15 @@ import d3 from 'd3'; import _ from 'lodash'; -import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import 'ui/persisted_state'; import $ from 'jquery'; + import { Axis } from '../../lib/axis'; import { VisConfig } from '../../lib/vis_config'; +import { getMockUiState } from './fixtures/_vis_fixture'; describe('Vislib xAxis Class Test Suite', function() { - let persistedState; + let mockUiState; let xAxis; let el; let fixture; @@ -105,34 +105,30 @@ describe('Vislib xAxis Class Test Suite', function() { yAxisLabel: 'Count', }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function($injector) { - persistedState = new ($injector.get('PersistedState'))(); - - el = d3 - .select('body') - .append('div') - .attr('class', 'visAxis--x') - .style('height', '40px'); + beforeEach(() => { + mockUiState = getMockUiState(); + el = d3 + .select('body') + .append('div') + .attr('class', 'visAxis--x') + .style('height', '40px'); - fixture = el.append('div').attr('class', 'x-axis-div'); + fixture = el.append('div').attr('class', 'x-axis-div'); - const visConfig = new VisConfig( - { - type: 'histogram', - }, - data, - persistedState, - $('.x-axis-div')[0], - () => undefined - ); - xAxis = new Axis(visConfig, { - type: 'category', - id: 'CategoryAxis-1', - }); - }) - ); + const visConfig = new VisConfig( + { + type: 'histogram', + }, + data, + mockUiState, + $('.x-axis-div')[0], + () => undefined + ); + xAxis = new Axis(visConfig, { + type: 'category', + id: 'CategoryAxis-1', + }); + }); afterEach(function() { fixture.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/y_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/y_axis.js index e857aca3bf3edc..f73011d6616451 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/y_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/y_axis.js @@ -19,15 +19,15 @@ import _ from 'lodash'; import d3 from 'd3'; -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; -import 'ui/persisted_state'; import $ from 'jquery'; +import expect from '@kbn/expect'; + import { Axis } from '../../lib/axis'; import { VisConfig } from '../../lib/vis_config'; +import { getMockUiState } from './fixtures/_vis_fixture'; const YAxis = Axis; -let persistedState; +let mockUiState; let el; let buildYAxis; let yAxis; @@ -96,7 +96,7 @@ function createData(seriesData) { type: 'histogram', }, data, - persistedState, + mockUiState, node, () => undefined ); @@ -121,15 +121,10 @@ function createData(seriesData) { } describe('Vislib yAxis Class Test Suite', function() { - beforeEach(ngMock.module('kibana')); - - beforeEach( - ngMock.inject(function($injector) { - persistedState = new ($injector.get('PersistedState'))(); - - expect($('.y-axis-wrapper')).to.have.length(0); - }) - ); + beforeEach(() => { + mockUiState = getMockUiState(); + expect($('.y-axis-wrapper')).to.have.length(0); + }); afterEach(function() { if (el) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/response_handlers.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/response_handlers.js new file mode 100644 index 00000000000000..642a032d8b9c20 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/response_handlers.js @@ -0,0 +1,136 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import sinon from 'sinon'; +import ngMock from 'ng_mock'; +import expect from '@kbn/expect'; + +import { aggResponseIndex } from 'ui/agg_response'; + +import { vislibSeriesResponseHandler } from '../response_handler'; + +/** + * TODO: Fix these tests if still needed + * + * All these tests were not being run in master or prodiced false positive results + * Fixing them would require changes to the response handler logic. + */ + +describe.skip('Basic Response Handler', function() { + beforeEach(ngMock.module('kibana')); + + it('returns empty object if conversion failed', () => { + const data = vislibSeriesResponseHandler({}); + expect(data).to.not.be.an('undefined'); + expect(data).to.equal({}); + }); + + it('returns empty object if no data was found', () => { + const data = vislibSeriesResponseHandler({ + columns: [{ id: '1', title: '1', aggConfig: {} }], + rows: [], + }); + expect(data).to.not.be.an('undefined'); + expect(data.rows).to.equal([]); + }); +}); + +describe.skip('renderbot#buildChartData', function() { + describe('for hierarchical vis', function() { + it('defers to hierarchical aggResponse converter', function() { + const football = {}; + const stub = sinon.stub(aggResponseIndex, 'hierarchical').returns(football); + expect(vislibSeriesResponseHandler(football)).to.be(football); + expect(stub).to.have.property('callCount', 1); + expect(stub.firstCall.args[1]).to.be(football); + }); + }); + + describe('for point plot', function() { + it('calls tabify to simplify the data into a table', function() { + const football = { tables: [], hits: { total: 1 } }; + const stub = sinon.stub(aggResponseIndex, 'tabify').returns(football); + expect(vislibSeriesResponseHandler(football)).to.eql({ rows: [], hits: 1 }); + expect(stub).to.have.property('callCount', 1); + expect(stub.firstCall.args[1]).to.be(football); + }); + + it('returns a single chart if the tabify response contains only a single table', function() { + const chart = { hits: 1, rows: [], columns: [] }; + const esResp = { hits: { total: 1 } }; + const tabbed = { tables: [{}] }; + + sinon.stub(aggResponseIndex, 'tabify').returns(tabbed); + expect(vislibSeriesResponseHandler(esResp)).to.eql(chart); + }); + + it('converts table groups into rows/columns wrappers for charts', function() { + const converter = sinon.stub().returns('chart'); + const esResp = { hits: { total: 1 } }; + const tables = [{}, {}, {}, {}]; + + sinon.stub(aggResponseIndex, 'tabify').returns({ + tables: [ + { + aggConfig: { params: { row: true } }, + tables: [ + { + aggConfig: { params: { row: false } }, + tables: [tables[0]], + }, + { + aggConfig: { params: { row: false } }, + tables: [tables[1]], + }, + ], + }, + { + aggConfig: { params: { row: true } }, + tables: [ + { + aggConfig: { params: { row: false } }, + tables: [tables[2]], + }, + { + aggConfig: { params: { row: false } }, + tables: [tables[3]], + }, + ], + }, + ], + }); + + const chartData = vislibSeriesResponseHandler(esResp); + + // verify tables were converted + expect(converter).to.have.property('callCount', 4); + expect(converter.args[0][1]).to.be(tables[0]); + expect(converter.args[1][1]).to.be(tables[1]); + expect(converter.args[2][1]).to.be(tables[2]); + expect(converter.args[3][1]).to.be(tables[3]); + + expect(chartData).to.have.property('rows'); + expect(chartData.rows).to.have.length(2); + chartData.rows.forEach(function(row) { + expect(row).to.have.property('columns'); + expect(row.columns).to.eql(['chart', 'chart']); + }); + }); + }); +}); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/vis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/vis.js index a6d1c4daf5d2cf..4852f71d8c45b3 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/vis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/vis.js @@ -19,19 +19,15 @@ import _ from 'lodash'; import $ from 'jquery'; -import ngMock from 'ng_mock'; - import expect from '@kbn/expect'; -import 'ui/persisted_state'; import series from './lib/fixtures/mock_data/date_histogram/_series'; import columns from './lib/fixtures/mock_data/date_histogram/_columns'; import rows from './lib/fixtures/mock_data/date_histogram/_rows'; import stackedSeries from './lib/fixtures/mock_data/date_histogram/_stacked_series'; -import getFixturesVislibVisFixtureProvider from './lib/fixtures/_vis_fixture'; +import { getVis, getMockUiState } from './lib/fixtures/_vis_fixture'; const dataArray = [series, columns, rows, stackedSeries]; - const names = ['series', 'columns', 'rows', 'stackedSeries']; dataArray.forEach(function(data, i) { @@ -39,19 +35,15 @@ dataArray.forEach(function(data, i) { const beforeEvent = 'click'; const afterEvent = 'brush'; let vis; - let persistedState; + let mockUiState; let secondVis; let numberOfCharts; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(); - persistedState = new ($injector.get('PersistedState'))(); - secondVis = getVis(); - }) - ); + beforeEach(() => { + vis = getVis(); + secondVis = getVis(); + mockUiState = getMockUiState(); + }); afterEach(function() { vis.destroy(); @@ -60,7 +52,7 @@ dataArray.forEach(function(data, i) { describe('render Method', function() { beforeEach(function() { - vis.render(data, persistedState); + vis.render(data, mockUiState); numberOfCharts = vis.handler.charts.length; }); @@ -78,7 +70,7 @@ dataArray.forEach(function(data, i) { it('should throw an error if no data is provided', function() { expect(function() { - vis.render(null, persistedState); + vis.render(null, mockUiState); }).to.throwError(); }); }); @@ -91,8 +83,8 @@ dataArray.forEach(function(data, i) { describe('destroy Method', function() { beforeEach(function() { - vis.render(data, persistedState); - secondVis.render(data, persistedState); + vis.render(data, mockUiState); + secondVis.render(data, mockUiState); secondVis.destroy(); }); @@ -107,7 +99,7 @@ dataArray.forEach(function(data, i) { describe('set Method', function() { beforeEach(function() { - vis.render(data, persistedState); + vis.render(data, mockUiState); vis.set('addLegend', false); vis.set('offset', 'wiggle'); }); @@ -120,7 +112,7 @@ dataArray.forEach(function(data, i) { describe('get Method', function() { beforeEach(function() { - vis.render(data, persistedState); + vis.render(data, mockUiState); }); it('should get attribute values', function() { @@ -142,7 +134,7 @@ dataArray.forEach(function(data, i) { }); // Render chart - vis.render(data, persistedState); + vis.render(data, mockUiState); // Add event after charts have rendered listeners.forEach(function(listener) { @@ -196,7 +188,7 @@ dataArray.forEach(function(data, i) { vis.off(beforeEvent, listener1); // Render chart - vis.render(data, persistedState); + vis.render(data, mockUiState); // Add event after charts have rendered listeners.forEach(function(listener) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/area_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/area_chart.js index 7fe350bd85e052..c3f5859eb454cc 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/area_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/area_chart.js @@ -18,14 +18,11 @@ */ import d3 from 'd3'; -import ngMock from 'ng_mock'; import _ from 'lodash'; import $ from 'jquery'; - import expect from '@kbn/expect'; -import 'ui/persisted_state'; -import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; +import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; const dataTypesArray = { 'series pos': require('../lib/fixtures/mock_data/date_histogram/_series'), @@ -46,18 +43,14 @@ const visLibParams = { _.forOwn(dataTypesArray, function(dataType, dataTypeName) { describe('Vislib Area Chart Test Suite for ' + dataTypeName + ' Data', function() { let vis; - let persistedState; - - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(visLibParams); - persistedState = new ($injector.get('PersistedState'))(); - vis.on('brush', _.noop); - vis.render(dataType, persistedState); - }) - ); + let mockUiState; + + beforeEach(() => { + vis = getVis(visLibParams); + mockUiState = getMockUiState(); + vis.on('brush', _.noop); + vis.render(dataType, mockUiState); + }); afterEach(function() { vis.destroy(); @@ -97,17 +90,15 @@ _.forOwn(dataTypesArray, function(dataType, dataTypeName) { let d3selectedPath; let onMouseOver; - beforeEach( - ngMock.inject(function() { - vis.handler.charts.forEach(function(chart) { - path = $(chart.chartEl).find('path')[0]; - d3selectedPath = d3.select(path)[0][0]; + beforeEach(function() { + vis.handler.charts.forEach(function(chart) { + path = $(chart.chartEl).find('path')[0]; + d3selectedPath = d3.select(path)[0][0]; - // d3 instance of click and hover - onMouseOver = !!d3selectedPath.__onmouseover; - }); - }) - ); + // d3 instance of click and hover + onMouseOver = !!d3selectedPath.__onmouseover; + }); + }); it('should attach a hover event', function() { vis.handler.charts.forEach(function() { @@ -124,20 +115,18 @@ _.forOwn(dataTypesArray, function(dataType, dataTypeName) { let onClick; let onMouseOver; - beforeEach( - ngMock.inject(function() { - vis.handler.charts.forEach(function(chart) { - circle = $(chart.chartEl).find('circle')[0]; - brush = $(chart.chartEl).find('.brush'); - d3selectedCircle = d3.select(circle)[0][0]; - - // d3 instance of click and hover - onBrush = !!brush; - onClick = !!d3selectedCircle.__onclick; - onMouseOver = !!d3selectedCircle.__onmouseover; - }); - }) - ); + beforeEach(() => { + vis.handler.charts.forEach(function(chart) { + circle = $(chart.chartEl).find('circle')[0]; + brush = $(chart.chartEl).find('.brush'); + d3selectedCircle = d3.select(circle)[0][0]; + + // d3 instance of click and hover + onBrush = !!brush; + onClick = !!d3selectedCircle.__onclick; + onMouseOver = !!d3selectedCircle.__onmouseover; + }); + }); // D3 brushing requires that a g element is appended that // listens for mousedown events. This g element includes @@ -219,7 +208,7 @@ _.forOwn(dataTypesArray, function(dataType, dataTypeName) { describe('defaultYExtents is true', function() { beforeEach(function() { vis.visConfigArgs.defaultYExtents = true; - vis.render(dataType, persistedState); + vis.render(dataType, mockUiState); }); it('should return yAxis extents equal to data extents', function() { @@ -238,7 +227,7 @@ _.forOwn(dataTypesArray, function(dataType, dataTypeName) { beforeEach(function() { vis.visConfigArgs.defaultYExtents = true; vis.visConfigArgs.boundsMargin = boundsMarginValue; - vis.render(dataType, persistedState); + vis.render(dataType, mockUiState); }); it('should return yAxis extents equal to data extents with boundsMargin', function() { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/chart.js index 088d3377af4dd5..9653f9abab6fb8 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/chart.js @@ -18,16 +18,12 @@ */ import d3 from 'd3'; -import ngMock from 'ng_mock'; - import expect from '@kbn/expect'; -import 'ui/persisted_state'; import { Chart } from '../../visualizations/_chart'; -import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; +import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; describe('Vislib _chart Test Suite', function() { - let persistedState; let vis; let el; let myChart; @@ -109,30 +105,24 @@ describe('Vislib _chart Test Suite', function() { yAxisLabel: 'Count', }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - persistedState = new ($injector.get('PersistedState'))(); - - el = d3 - .select('body') - .append('div') - .attr('class', 'column-chart'); + beforeEach(() => { + el = d3 + .select('body') + .append('div') + .attr('class', 'column-chart'); - config = { - type: 'histogram', - addTooltip: true, - addLegend: true, - zeroFill: true, - }; + config = { + type: 'histogram', + addTooltip: true, + addLegend: true, + zeroFill: true, + }; - vis = getVis(config, el[0][0]); - vis.render(data, persistedState); + vis = getVis(config, el[0][0]); + vis.render(data, getMockUiState()); - myChart = vis.handler.charts[0]; - }) - ); + myChart = vis.handler.charts[0]; + }); afterEach(function() { el.remove(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/column_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/column_chart.js index d02060ef29bdd4..2216294fcbac11 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/column_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/column_chart.js @@ -17,12 +17,10 @@ * under the License. */ -import ngMock from 'ng_mock'; import _ from 'lodash'; import d3 from 'd3'; - +import $ from 'jquery'; import expect from '@kbn/expect'; -import 'ui/persisted_state'; // Data import series from '../lib/fixtures/mock_data/date_histogram/_series'; @@ -31,11 +29,11 @@ import seriesNeg from '../lib/fixtures/mock_data/date_histogram/_series_neg'; import termsColumns from '../lib/fixtures/mock_data/terms/_columns'; import histogramRows from '../lib/fixtures/mock_data/histogram/_rows'; import stackedSeries from '../lib/fixtures/mock_data/date_histogram/_stacked_series'; + import { seriesMonthlyInterval } from '../lib/fixtures/mock_data/date_histogram/_series_monthly_interval'; import { rowsSeriesWithHoles } from '../lib/fixtures/mock_data/date_histogram/_rows_series_with_holes'; import rowsWithZeros from '../lib/fixtures/mock_data/date_histogram/_rows'; -import $ from 'jquery'; -import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; +import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; // tuple, with the format [description, mode, data] const dataTypesArray = [ @@ -54,7 +52,7 @@ dataTypesArray.forEach(function(dataType) { describe('Vislib Column Chart Test Suite for ' + name + ' Data', function() { let vis; - let persistedState; + let mockUiState; const visLibParams = { type: 'histogram', addLegend: true, @@ -67,16 +65,12 @@ dataTypesArray.forEach(function(dataType) { }, }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(visLibParams); - persistedState = new ($injector.get('PersistedState'))(); - vis.on('brush', _.noop); - vis.render(data, persistedState); - }) - ); + beforeEach(() => { + vis = getVis(visLibParams); + mockUiState = getMockUiState(); + vis.on('brush', _.noop); + vis.render(data, mockUiState); + }); afterEach(function() { vis.destroy(); @@ -200,7 +194,7 @@ dataTypesArray.forEach(function(dataType) { describe('defaultYExtents is true', function() { beforeEach(function() { vis.visConfigArgs.defaultYExtents = true; - vis.render(data, persistedState); + vis.render(data, mockUiState); }); it('should return yAxis extents equal to data extents', function() { @@ -219,7 +213,7 @@ dataTypesArray.forEach(function(dataType) { beforeEach(function() { vis.visConfigArgs.defaultYExtents = true; vis.visConfigArgs.boundsMargin = boundsMarginValue; - vis.render(data, persistedState); + vis.render(data, mockUiState); }); it('should return yAxis extents equal to data extents with boundsMargin', function() { @@ -247,7 +241,7 @@ dataTypesArray.forEach(function(dataType) { describe('stackData method - data set with zeros in percentage mode', function() { let vis; - let persistedState; + let mockUiState; const visLibParams = { type: 'histogram', addLegend: true, @@ -256,22 +250,18 @@ describe('stackData method - data set with zeros in percentage mode', function() zeroFill: true, }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(visLibParams); - persistedState = new ($injector.get('PersistedState'))(); - vis.on('brush', _.noop); - }) - ); + beforeEach(() => { + vis = getVis(visLibParams); + mockUiState = getMockUiState(); + vis.on('brush', _.noop); + }); afterEach(function() { vis.destroy(); }); it('should not mutate the injected zeros', function() { - vis.render(seriesMonthlyInterval, persistedState); + vis.render(seriesMonthlyInterval, mockUiState); expect(vis.handler.charts).to.have.length(1); const chart = vis.handler.charts[0]; @@ -284,7 +274,7 @@ describe('stackData method - data set with zeros in percentage mode', function() }); it('should not mutate zeros that exist in the data', function() { - vis.render(rowsWithZeros, persistedState); + vis.render(rowsWithZeros, mockUiState); expect(vis.handler.charts).to.have.length(2); const chart = vis.handler.charts[0]; @@ -298,7 +288,7 @@ describe('stackData method - data set with zeros in percentage mode', function() describe('datumWidth - split chart data set with holes', function() { let vis; - let persistedState; + let mockUiState; const visLibParams = { type: 'histogram', addLegend: true, @@ -307,16 +297,12 @@ describe('datumWidth - split chart data set with holes', function() { zeroFill: true, }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(visLibParams); - persistedState = new ($injector.get('PersistedState'))(); - vis.on('brush', _.noop); - vis.render(rowsSeriesWithHoles, persistedState); - }) - ); + beforeEach(() => { + vis = getVis(visLibParams); + mockUiState = getMockUiState(); + vis.on('brush', _.noop); + vis.render(rowsSeriesWithHoles, mockUiState); + }); afterEach(function() { vis.destroy(); @@ -336,7 +322,7 @@ describe('datumWidth - split chart data set with holes', function() { describe('datumWidth - monthly interval', function() { let vis; - let persistedState; + let mockUiState; const visLibParams = { type: 'histogram', addLegend: true, @@ -345,16 +331,12 @@ describe('datumWidth - monthly interval', function() { zeroFill: true, }; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(visLibParams); - persistedState = new ($injector.get('PersistedState'))(); - vis.on('brush', _.noop); - vis.render(seriesMonthlyInterval, persistedState); - }) - ); + beforeEach(() => { + vis = getVis(visLibParams); + mockUiState = getMockUiState(); + vis.on('brush', _.noop); + vis.render(seriesMonthlyInterval, mockUiState); + }); afterEach(function() { vis.destroy(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/gauge_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/gauge_chart.js index 074b34e1c03c43..fe25734fcbfde5 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/gauge_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/gauge_chart.js @@ -17,21 +17,15 @@ * under the License. */ -import ngMock from 'ng_mock'; import $ from 'jquery'; import _ from 'lodash'; - import expect from '@kbn/expect'; -import 'ui/persisted_state'; import data from '../lib/fixtures/mock_data/terms/_seriesMultiple'; -import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; +import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; describe('Vislib Gauge Chart Test Suite', function() { - let PersistedState; - let vislibVis; let vis; - let persistedState; let chartEl; const visLibParams = { type: 'gauge', @@ -81,21 +75,15 @@ describe('Vislib Gauge Chart Test Suite', function() { vis.destroy(); $('.visChart').remove(); } - vis = vislibVis(config); - persistedState = new PersistedState(); + vis = getVis(config); vis.on('brush', _.noop); - vis.render(data, persistedState); + vis.render(data, getMockUiState()); chartEl = vis.handler.charts[0].chartEl; } - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - vislibVis = getFixturesVislibVisFixtureProvider(Private); - PersistedState = $injector.get('PersistedState'); - generateVis(); - }) - ); + beforeEach(() => { + generateVis(); + }); afterEach(function() { vis.destroy(); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/heatmap_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/heatmap_chart.js index bf1dbad0b44cf1..f4c952be191deb 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/heatmap_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/heatmap_chart.js @@ -17,12 +17,10 @@ * under the License. */ -import ngMock from 'ng_mock'; import _ from 'lodash'; +import $ from 'jquery'; import d3 from 'd3'; - import expect from '@kbn/expect'; -import 'ui/persisted_state'; // Data import series from '../lib/fixtures/mock_data/date_histogram/_series'; @@ -30,8 +28,8 @@ import seriesPosNeg from '../lib/fixtures/mock_data/date_histogram/_series_pos_n import seriesNeg from '../lib/fixtures/mock_data/date_histogram/_series_neg'; import termsColumns from '../lib/fixtures/mock_data/terms/_columns'; import stackedSeries from '../lib/fixtures/mock_data/date_histogram/_stacked_series'; -import $ from 'jquery'; -import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; + +import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; // tuple, with the format [description, mode, data] const dataTypesArray = [ @@ -48,10 +46,8 @@ describe('Vislib Heatmap Chart Test Suite', function() { const data = dataType[1]; describe('for ' + name + ' Data', function() { - let PersistedState; - let vislibVis; let vis; - let persistedState; + let mockUiState; const visLibParams = { type: 'heatmap', addLegend: true, @@ -66,20 +62,15 @@ describe('Vislib Heatmap Chart Test Suite', function() { function generateVis(opts = {}) { const config = _.defaultsDeep({}, opts, visLibParams); - vis = vislibVis(config); - persistedState = new PersistedState(); + vis = getVis(config); + mockUiState = getMockUiState(); vis.on('brush', _.noop); - vis.render(data, persistedState); + vis.render(data, mockUiState); } - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - vislibVis = getFixturesVislibVisFixtureProvider(Private); - PersistedState = $injector.get('PersistedState'); - generateVis(); - }) - ); + beforeEach(() => { + generateVis(); + }); afterEach(function() { vis.destroy(); @@ -174,7 +165,7 @@ describe('Vislib Heatmap Chart Test Suite', function() { }); it('should define default colors', function() { - expect(persistedState.get('vis.defaultColors')).to.not.be(undefined); + expect(mockUiState.get('vis.defaultColors')).to.not.be(undefined); }); it('should set custom range', function() { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/line_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/line_chart.js index d010944a19e47d..1269fe7bcf62e9 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/line_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/line_chart.js @@ -19,12 +19,9 @@ import d3 from 'd3'; import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; import $ from 'jquery'; import _ from 'lodash'; -import 'ui/persisted_state'; - // Data import seriesPos from '../lib/fixtures/mock_data/date_histogram/_series'; import seriesPosNeg from '../lib/fixtures/mock_data/date_histogram/_series_pos_neg'; @@ -32,7 +29,8 @@ import seriesNeg from '../lib/fixtures/mock_data/date_histogram/_series_neg'; import histogramColumns from '../lib/fixtures/mock_data/histogram/_columns'; import rangeRows from '../lib/fixtures/mock_data/range/_rows'; import termSeries from '../lib/fixtures/mock_data/terms/_series'; -import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; + +import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; const dataTypes = [ ['series pos', seriesPos], @@ -50,25 +48,21 @@ describe('Vislib Line Chart', function() { describe(name + ' Data', function() { let vis; - let persistedState; - - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - const visLibParams = { - type: 'line', - addLegend: true, - addTooltip: true, - drawLinesBetweenPoints: true, - }; - - vis = getVis(visLibParams); - persistedState = new ($injector.get('PersistedState'))(); - vis.render(data, persistedState); - vis.on('brush', _.noop); - }) - ); + let mockUiState; + + beforeEach(() => { + const visLibParams = { + type: 'line', + addLegend: true, + addTooltip: true, + drawLinesBetweenPoints: true, + }; + + vis = getVis(visLibParams); + mockUiState = getMockUiState(); + vis.render(data, mockUiState); + vis.on('brush', _.noop); + }); afterEach(function() { vis.destroy(); @@ -82,20 +76,18 @@ describe('Vislib Line Chart', function() { let onClick; let onMouseOver; - beforeEach( - ngMock.inject(function() { - vis.handler.charts.forEach(function(chart) { - circle = $(chart.chartEl).find('.circle')[0]; - brush = $(chart.chartEl).find('.brush'); - d3selectedCircle = d3.select(circle)[0][0]; - - // d3 instance of click and hover - onBrush = !!brush; - onClick = !!d3selectedCircle.__onclick; - onMouseOver = !!d3selectedCircle.__onmouseover; - }); - }) - ); + beforeEach(function() { + vis.handler.charts.forEach(function(chart) { + circle = $(chart.chartEl).find('.circle')[0]; + brush = $(chart.chartEl).find('.brush'); + d3selectedCircle = d3.select(circle)[0][0]; + + // d3 instance of click and hover + onBrush = !!brush; + onClick = !!d3selectedCircle.__onclick; + onMouseOver = !!d3selectedCircle.__onmouseover; + }); + }); // D3 brushing requires that a g element is appended that // listens for mousedown events. This g element includes @@ -177,7 +169,7 @@ describe('Vislib Line Chart', function() { describe('defaultYExtents is true', function() { beforeEach(function() { vis.visConfigArgs.defaultYExtents = true; - vis.render(data, persistedState); + vis.render(data, mockUiState); }); it('should return yAxis extents equal to data extents', function() { @@ -196,7 +188,7 @@ describe('Vislib Line Chart', function() { beforeEach(function() { vis.visConfigArgs.defaultYExtents = true; vis.visConfigArgs.boundsMargin = boundsMarginValue; - vis.render(data, persistedState); + vis.render(data, mockUiState); }); it('should return yAxis extents equal to data extents with boundsMargin', function() { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js index 381dfcd387cc20..54415d65d45147 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js @@ -18,20 +18,16 @@ */ import d3 from 'd3'; -import ngMock from 'ng_mock'; import _ from 'lodash'; import $ from 'jquery'; - import expect from '@kbn/expect'; -// TODO: Remove ui imports once converting to jest -import 'ui/persisted_state'; -import { vislibSlicesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; import fixtures from 'fixtures/fake_hierarchical_data'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; +import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; import { Vis, tabifyAggResponse } from '../../../legacy_imports'; +import { vislibSlicesResponseHandler } from '../../response_handler'; const rowAgg = [ { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, @@ -123,35 +119,31 @@ describe('No global chart settings', function() { addTooltip: true, }; let chart1; - let persistedState; + let mockUiState; let indexPattern; let responseHandler; let data1; let stubVis1; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - chart1 = getVis(visLibParams1); - persistedState = new ($injector.get('PersistedState'))(); - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - responseHandler = vislibSlicesResponseHandlerProvider().handler; - - let id1 = 1; - stubVis1 = new Vis(indexPattern, { - type: 'pie', - aggs: rowAgg, - }); + beforeEach(() => { + chart1 = getVis(visLibParams1); + mockUiState = getMockUiState(); + indexPattern = new FixturesStubbedLogstashIndexPatternProvider(); + responseHandler = vislibSlicesResponseHandler; + + let id1 = 1; + stubVis1 = new Vis(indexPattern, { + type: 'pie', + aggs: rowAgg, + }); - stubVis1.isHierarchical = () => true; + stubVis1.isHierarchical = () => true; - // We need to set the aggs to a known value. - _.each(stubVis1.aggs.aggs, function(agg) { - agg.id = 'agg_' + id1++; - }); - }) - ); + // We need to set the aggs to a known value. + _.each(stubVis1.aggs.aggs, function(agg) { + agg.id = 'agg_' + id1++; + }); + }); beforeEach(async () => { const table1 = tabifyAggResponse(stubVis1.aggs, fixtures.threeTermBuckets, { @@ -159,7 +151,7 @@ describe('No global chart settings', function() { }); data1 = await responseHandler(table1, rowAggDimensions); - chart1.render(data1, persistedState); + chart1.render(data1, mockUiState); }); afterEach(function() { @@ -216,40 +208,37 @@ describe('Vislib PieChart Class Test Suite', function() { addTooltip: true, }; let vis; - let persistedState; + let mockUiState; let indexPattern; let data; let stubVis; let responseHandler; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private, $injector) { - const getVis = getFixturesVislibVisFixtureProvider(Private); - vis = getVis(visLibParams); - persistedState = new ($injector.get('PersistedState'))(); - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - responseHandler = vislibSlicesResponseHandlerProvider().handler; - - let id = 1; - stubVis = new Vis(indexPattern, { - type: 'pie', - aggs: dataAgg, - }); + beforeEach(() => { + vis = getVis(visLibParams); + mockUiState = getMockUiState(); + indexPattern = new FixturesStubbedLogstashIndexPatternProvider(); + responseHandler = vislibSlicesResponseHandler; - // We need to set the aggs to a known value. - _.each(stubVis.aggs.aggs, function(agg) { - agg.id = 'agg_' + id++; - }); - }) - ); + let id = 1; + stubVis = new Vis(indexPattern, { + type: 'pie', + aggs: dataAgg, + }); + + // We need to set the aggs to a known value. + _.each(stubVis.aggs.aggs, function(agg) { + agg.id = 'agg_' + id++; + }); + }); beforeEach(async () => { const table = tabifyAggResponse(stubVis.aggs, fixtures.threeTermBuckets, { metricsAtAllLevels: true, }); data = await responseHandler(table, dataDimensions); - vis.render(data, persistedState); + + vis.render(data, mockUiState); }); afterEach(function() { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/time_marker.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/time_marker.js index ec22d43c08cb2b..d69f952325ed02 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/time_marker.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/time_marker.js @@ -18,11 +18,11 @@ */ import d3 from 'd3'; +import $ from 'jquery'; import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; + import series from '../lib/fixtures/mock_data/date_histogram/_series'; import terms from '../lib/fixtures/mock_data/terms/_columns'; -import $ from 'jquery'; import { TimeMarker } from '../../visualizations/time_marker'; describe('Vislib Time Marker Test Suite', function() { @@ -57,26 +57,23 @@ describe('Vislib Time Marker Test Suite', function() { let maxDomain; let domain; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - minDomain = getExtent(series.series, d3.min); - maxDomain = getExtent(series.series, d3.max); - domain = [minDomain, maxDomain]; - xScale = d3.time - .scale() - .domain(domain) - .range([0, 500]); - defaultMarker = new TimeMarker(times, xScale, height); - customMarker = new TimeMarker(myTimes, xScale, height); - - selection = d3 - .select('body') - .append('div') - .attr('class', 'marker'); - selection.datum(series); - }) - ); + beforeEach(function() { + minDomain = getExtent(series.series, d3.min); + maxDomain = getExtent(series.series, d3.max); + domain = [minDomain, maxDomain]; + xScale = d3.time + .scale() + .domain(domain) + .range([0, 500]); + defaultMarker = new TimeMarker(times, xScale, height); + customMarker = new TimeMarker(myTimes, xScale, height); + + selection = d3 + .select('body') + .append('div') + .attr('class', 'marker'); + selection.datum(series); + }); afterEach(function() { selection.remove('*'); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/vis_types.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/vis_types.js index e150ca58c15cfd..c8f0faf8dcca5d 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/vis_types.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/vis_types.js @@ -17,20 +17,17 @@ * under the License. */ -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; import _ from 'lodash'; +import expect from '@kbn/expect'; + import { visTypes } from '../../visualizations/vis_types'; describe('Vislib Vis Types Test Suite', function() { let visFunc; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function() { - visFunc = visTypes.point_series; - }) - ); + beforeEach(function() { + visFunc = visTypes.point_series; + }); it('should be an object', function() { expect(_.isObject(visTypes)).to.be(true); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/_index.scss index 0344fbb5359ece..78e16224a67a3c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/_index.scss +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/_index.scss @@ -1,6 +1,9 @@ @import './variables'; +@import './vislib_vis_type'; @import './lib/index'; +@import './components/tooltip/index'; +@import './components/legend/index'; @import './visualizations/point_series/index'; @import './visualizations/gauges/index'; diff --git a/src/legacy/ui/public/vis/vis_types/_vislib_vis_type.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/_vislib_vis_type.scss similarity index 99% rename from src/legacy/ui/public/vis/vis_types/_vislib_vis_type.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/_vislib_vis_type.scss index c1f369d3e3536f..c03aa19140de06 100644 --- a/src/legacy/ui/public/vis/vis_types/_vislib_vis_type.scss +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/_vislib_vis_type.scss @@ -7,12 +7,15 @@ &.visLib--legend-left { flex-direction: row-reverse; } + &.visLib--legend-right { flex-direction: row; } + &.visLib--legend-top { flex-direction: column-reverse; } + &.visLib--legend-bottom { flex-direction: column; } diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/__snapshots__/vislib_vis_legend.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/__snapshots__/legend.test.tsx.snap similarity index 100% rename from src/legacy/ui/public/vis/vis_types/vislib_vis_legend/__snapshots__/vislib_vis_legend.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/__snapshots__/legend.test.tsx.snap diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/_index.scss new file mode 100644 index 00000000000000..53617a984dcf51 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/_index.scss @@ -0,0 +1 @@ +@import './_legend'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss new file mode 100644 index 00000000000000..b1a59f88a348ad --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/_legend.scss @@ -0,0 +1,99 @@ +@import '../../variables'; + +// NOTE: Some of the styles attempt to align with the TSVB legend + +$visLegendWidth: 150px; +$visColorPickerWidth: $euiSizeM * 10; +$visLegendLineHeight: $euiSize; + +.visLegend__toggle { + border-radius: $euiBorderRadius; + position: absolute; + bottom: 0; + left: 0; + display: flex; + padding: $euiSizeXS; + background-color: $euiColorEmptyShade; + transition: opacity $euiAnimSpeedFast $euiAnimSlightResistance, background-color $euiAnimSpeedFast $euiAnimSlightResistance $euiAnimSpeedExtraSlow; + + &:focus { + box-shadow: none; + background-color: $euiFocusBackgroundColor !important; // sass-lint:disable-line no-important + } +} + +.visLegend__toggle--isOpen { + background-color: transparentize($euiColorDarkestShade, .9); + opacity: 1; +} + +.visLegend { + display: flex; + min-height: 0; + height: 100%; +} + +.visLib--legend-left { + .visLegend__list { + margin-bottom: $euiSizeL; + } +} + +.visLib--legend-bottom { + .visLegend__list { + margin-left: $euiSizeL; + } +} + +.visLegend__list { + @include euiScrollBar; + display: flex; + width: $visLegendWidth; // Must be a hard-coded width for the chart to get its correct dimensions + flex: 1 1 auto; + flex-direction: column; + overflow-x: hidden; + overflow-y: auto; + + .visLegend__button { + font-size: $euiFontSizeXS; + text-align: left; + overflow: hidden; // Ensures scrollbars don't appear because EuiButton__text has a high line-height + + .visLegend__valueTitle { + vertical-align: middle; + } + } + + .visLib--legend-top &, + .visLib--legend-bottom & { + width: auto; + flex-direction: row; + flex-wrap: wrap; + + .visLegend__value { + flex-grow: 0; + max-width: $visLegendWidth; + } + } + + &.hidden { + visibility: hidden; + } +} + +.visLegend__valueColorPicker { + width: ($euiSizeL * 8); // 8 columns +} + +.visLegend__valueColorPickerDot { + cursor: pointer; + + &:hover { + transform: scale(1.4); + } + + &-isSelected { + border: $euiSizeXS solid; + border-radius: 100%; + } +} diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/index.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/index.ts new file mode 100644 index 00000000000000..230cda4c35ff8d --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { VisLegend } from './legend'; +export { CUSTOM_LEGEND_VIS_TYPES } from './models'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx new file mode 100644 index 00000000000000..6f0a5a3784b070 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx @@ -0,0 +1,276 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { mount, ReactWrapper } from 'enzyme'; + +import { I18nProvider } from '@kbn/i18n/react'; +import { EuiButtonGroup } from '@elastic/eui'; + +import { VisLegend, VisLegendProps } from './legend'; +import { legendColors } from './models'; + +jest.mock('@elastic/eui', () => ({ + ...jest.requireActual('@elastic/eui'), + htmlIdGenerator: jest.fn().mockReturnValue(() => 'legendId'), +})); + +jest.mock('../../../legacy_imports', () => ({ + getTableAggs: jest.fn(), +})); +jest.mock('../../../../../visualizations/public', () => ({ + createFiltersFromEvent: jest.fn().mockReturnValue(['yes']), +})); + +const vis = { + params: { + addLegend: true, + }, + API: { + events: { + filter: jest.fn(), + }, + }, +}; +const vislibVis = { + handler: { + highlight: jest.fn(), + unHighlight: jest.fn(), + }, + getLegendLabels: jest.fn(), + visConfigArgs: { + type: 'area', + }, + visConfig: { + data: { + getColorFunc: jest.fn().mockReturnValue(() => 'red'), + }, + }, +}; + +const visData = { + series: [ + { + label: 'A', + values: [ + { + seriesRaw: 'valuesA', + }, + ], + }, + { + label: 'B', + values: [ + { + seriesRaw: 'valuesB', + }, + ], + }, + ], +}; + +const mockState = new Map(); +const uiState = { + get: jest + .fn() + .mockImplementation((key, fallback) => (mockState.has(key) ? mockState.get(key) : fallback)), + set: jest.fn().mockImplementation((key, value) => mockState.set(key, value)), + emit: jest.fn(), + setSilent: jest.fn(), +}; + +const getWrapper = (props?: Partial) => + mount( + + + + ); + +const getLegendItems = (wrapper: ReactWrapper) => wrapper.find('.visLegend__button'); + +describe('VisLegend Component', () => { + let wrapper: ReactWrapper; + + afterEach(() => { + mockState.clear(); + jest.clearAllMocks(); + }); + + describe('Legend open', () => { + beforeEach(() => { + mockState.set('vis.legendOpen', true); + wrapper = getWrapper(); + }); + + it('should match the snapshot', () => { + expect(wrapper.html()).toMatchSnapshot(); + }); + }); + + describe('Legend closed', () => { + beforeEach(() => { + mockState.set('vis.legendOpen', false); + wrapper = getWrapper(); + }); + + it('should match the snapshot', () => { + expect(wrapper.html()).toMatchSnapshot(); + }); + }); + + describe('Highlighting', () => { + beforeEach(() => { + wrapper = getWrapper(); + }); + + it('should call highlight handler when legend item is focused', () => { + const first = getLegendItems(wrapper).first(); + first.simulate('focus'); + + expect(vislibVis.handler.highlight).toHaveBeenCalledTimes(1); + }); + + it('should call highlight handler when legend item is hovered', () => { + const first = getLegendItems(wrapper).first(); + first.simulate('mouseEnter'); + + expect(vislibVis.handler.highlight).toHaveBeenCalledTimes(1); + }); + + it('should call unHighlight handler when legend item is blurred', () => { + let first = getLegendItems(wrapper).first(); + first.simulate('focus'); + first = getLegendItems(wrapper).first(); + first.simulate('blur'); + + expect(vislibVis.handler.unHighlight).toHaveBeenCalledTimes(1); + }); + + it('should call unHighlight handler when legend item is unhovered', () => { + const first = getLegendItems(wrapper).first(); + + first.simulate('mouseEnter'); + first.simulate('mouseLeave'); + + expect(vislibVis.handler.unHighlight).toHaveBeenCalledTimes(1); + }); + + it('should work with no handlers set', () => { + const newVis = { + ...vis, + vislibVis: { + ...vislibVis, + handler: null, + }, + }; + + expect(() => { + wrapper = getWrapper({ vis: newVis }); + const first = getLegendItems(wrapper).first(); + first.simulate('focus'); + first.simulate('blur'); + }).not.toThrow(); + }); + }); + + describe('Filtering', () => { + beforeEach(() => { + wrapper = getWrapper(); + }); + + it('should filter out when clicked', () => { + const first = getLegendItems(wrapper).first(); + first.simulate('click'); + const filterGroup = wrapper.find(EuiButtonGroup).first(); + filterGroup.getElement().props.onChange('filterIn'); + + expect(vis.API.events.filter).toHaveBeenCalledWith({ data: ['valuesA'], negate: false }); + expect(vis.API.events.filter).toHaveBeenCalledTimes(1); + }); + + it('should filter in when clicked', () => { + const first = getLegendItems(wrapper).first(); + first.simulate('click'); + const filterGroup = wrapper.find(EuiButtonGroup).first(); + filterGroup.getElement().props.onChange('filterOut'); + + expect(vis.API.events.filter).toHaveBeenCalledWith({ data: ['valuesA'], negate: true }); + expect(vis.API.events.filter).toHaveBeenCalledTimes(1); + }); + }); + + describe('Toggles details', () => { + beforeEach(() => { + wrapper = getWrapper(); + }); + + it('should show details when clicked', () => { + const first = getLegendItems(wrapper).first(); + first.simulate('click'); + + expect(wrapper.exists('.visLegend__valueDetails')).toBe(true); + }); + }); + + describe('setColor', () => { + beforeEach(() => { + wrapper = getWrapper(); + }); + + it('sets the color in the UI state', () => { + const first = getLegendItems(wrapper).first(); + first.simulate('click'); + + const popover = wrapper.find('.visLegend__valueDetails').first(); + const firstColor = popover.find('.visLegend__valueColorPickerDot').first(); + firstColor.simulate('click'); + + const colors = mockState.get('vis.colors'); + + expect(colors.A).toBe(legendColors[0]); + }); + }); + + describe('toggleLegend function', () => { + it('click should show legend once toggled from hidden', () => { + mockState.set('vis.legendOpen', false); + wrapper = getWrapper(); + const toggleButton = wrapper.find('.visLegend__toggle').first(); + toggleButton.simulate('click'); + + expect(wrapper.exists('.visLegend__list')).toBe(true); + }); + + it('click should hide legend once toggled from shown', () => { + mockState.set('vis.legendOpen', true); + wrapper = getWrapper(); + const toggleButton = wrapper.find('.visLegend__toggle').first(); + toggleButton.simulate('click'); + + expect(wrapper.exists('.visLegend__list')).toBe(false); + }); + }); +}); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx new file mode 100644 index 00000000000000..0eec557dd334ee --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx @@ -0,0 +1,263 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React, { BaseSyntheticEvent, KeyboardEvent, PureComponent } from 'react'; +import classNames from 'classnames'; +import { compact, uniq, map } from 'lodash'; + +import { i18n } from '@kbn/i18n'; +import { EuiPopoverProps, EuiIcon, keyCodes, htmlIdGenerator } from '@elastic/eui'; + +// @ts-ignore +import { createFiltersFromEvent } from '../../../../../visualizations/public'; +import { CUSTOM_LEGEND_VIS_TYPES, LegendItem } from './models'; +import { VisLegendItem } from './legend_item'; +import { getPieNames } from './pie_utils'; +import { getTableAggs } from '../../../legacy_imports'; + +export interface VisLegendProps { + vis: any; + vislibVis: any; + visData: any; + uiState: any; + position: 'top' | 'bottom' | 'left' | 'right'; +} + +export interface VisLegendState { + open: boolean; + labels: any[]; + tableAggs: any[]; + selectedLabel: string | null; +} + +export class VisLegend extends PureComponent { + legendId = htmlIdGenerator()('legend'); + getColor: (label: string) => string = () => ''; + + constructor(props: VisLegendProps) { + super(props); + const open = props.uiState.get('vis.legendOpen', true); + + this.state = { + open, + labels: [], + tableAggs: [], + selectedLabel: null, + }; + } + + componentDidMount() { + this.refresh(); + } + + toggleLegend = () => { + const bwcAddLegend = this.props.vis.params.addLegend; + const bwcLegendStateDefault = bwcAddLegend == null ? true : bwcAddLegend; + const newOpen = !this.props.uiState.get('vis.legendOpen', bwcLegendStateDefault); + this.setState({ open: newOpen }); + // open should be applied on template before we update uiState + setTimeout(() => { + this.props.uiState.set('vis.legendOpen', newOpen); + }); + }; + + setColor = (label: string, color: string) => (event: BaseSyntheticEvent) => { + if ((event as KeyboardEvent).keyCode && (event as KeyboardEvent).keyCode !== keyCodes.ENTER) { + return; + } + + const colors = this.props.uiState.get('vis.colors') || {}; + if (colors[label] === color) delete colors[label]; + else colors[label] = color; + this.props.uiState.setSilent('vis.colors', null); + this.props.uiState.set('vis.colors', colors); + this.props.uiState.emit('colorChanged'); + this.refresh(); + }; + + filter = ({ values: data }: LegendItem, negate: boolean) => { + this.props.vis.API.events.filter({ data, negate }); + }; + + canFilter = (item: LegendItem): boolean => { + if (CUSTOM_LEGEND_VIS_TYPES.includes(this.props.vislibVis.visConfigArgs.type)) { + return false; + } + const filters = createFiltersFromEvent({ aggConfigs: this.state.tableAggs, data: item.values }); + return Boolean(filters.length); + }; + + toggleDetails = (label: string | null) => (event?: BaseSyntheticEvent) => { + if ( + event && + (event as KeyboardEvent).keyCode && + (event as KeyboardEvent).keyCode !== keyCodes.ENTER + ) { + return; + } + this.setState({ selectedLabel: this.state.selectedLabel === label ? null : label }); + }; + + getSeriesLabels = (data: any[]) => { + const values = data.map(chart => chart.series).reduce((a, b) => a.concat(b), []); + + return compact(uniq(values, 'label')).map((label: any) => ({ + ...label, + values: [label.values[0].seriesRaw], + })); + }; + + // Most of these functions were moved directly from the old Legend class. Not a fan of this. + getLabels = (data: any, type: string) => { + if (!data) return []; + data = data.columns || data.rows || [data]; + + if (type === 'pie') return getPieNames(data); + + return this.getSeriesLabels(data); + }; + + refresh = () => { + const vislibVis = this.props.vislibVis; + if (!vislibVis || !vislibVis.visConfig) { + this.setState({ + labels: [ + { + label: i18n.translate('visTypeVislib.vislib.legend.loadingLabel', { + defaultMessage: 'loading…', + }), + }, + ], + }); + return; + } // make sure vislib is defined at this point + + if ( + this.props.uiState.get('vis.legendOpen') == null && + this.props.vis.params.addLegend != null + ) { + this.setState({ open: this.props.vis.params.addLegend }); + } + + if (CUSTOM_LEGEND_VIS_TYPES.includes(vislibVis.visConfigArgs.type)) { + const legendLabels = this.props.vislibVis.getLegendLabels(); + if (legendLabels) { + this.setState({ + labels: map(legendLabels, label => { + return { label }; + }), + }); + } + } else { + this.setState({ labels: this.getLabels(this.props.visData, vislibVis.visConfigArgs.type) }); + } + + if (vislibVis.visConfig) { + this.getColor = this.props.vislibVis.visConfig.data.getColorFunc(); + } + + this.setState({ tableAggs: getTableAggs(this.props.vis) }); + }; + + highlight = (event: BaseSyntheticEvent) => { + const el = event.currentTarget; + const handler = this.props.vislibVis && this.props.vislibVis.handler; + + // there is no guarantee that a Chart will set the highlight-function on its handler + if (!handler || typeof handler.highlight !== 'function') { + return; + } + handler.highlight.call(el, handler.el); + }; + + unhighlight = (event: BaseSyntheticEvent) => { + const el = event.currentTarget; + const handler = this.props.vislibVis && this.props.vislibVis.handler; + + // there is no guarantee that a Chart will set the unhighlight-function on its handler + if (!handler || typeof handler.unHighlight !== 'function') { + return; + } + handler.unHighlight.call(el, handler.el); + }; + + getAnchorPosition = () => { + const { position } = this.props; + + switch (position) { + case 'bottom': + return 'upCenter'; + case 'left': + return 'rightUp'; + case 'right': + return 'leftUp'; + default: + return 'downCenter'; + } + }; + + renderLegend = (anchorPosition: EuiPopoverProps['anchorPosition']) => ( +
    + {this.state.labels.map(item => ( + + ))} +
+ ); + + render() { + const { open } = this.state; + const anchorPosition = this.getAnchorPosition(); + + return ( +
+ + {open && this.renderLegend(anchorPosition)} +
+ ); + } +} diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx new file mode 100644 index 00000000000000..09c8a838532bf6 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend_item.tsx @@ -0,0 +1,203 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { memo, BaseSyntheticEvent, KeyboardEvent } from 'react'; +import classNames from 'classnames'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiPopover, + keyCodes, + EuiIcon, + EuiSpacer, + EuiButtonEmpty, + EuiPopoverProps, + EuiButtonGroup, + EuiButtonGroupOption, +} from '@elastic/eui'; + +import { legendColors, LegendItem } from './models'; + +interface Props { + item: LegendItem; + legendId: string; + selected: boolean; + canFilter: boolean; + anchorPosition: EuiPopoverProps['anchorPosition']; + onFilter: (item: LegendItem, negate: boolean) => void; + onSelect: (label: string | null) => (event?: BaseSyntheticEvent) => void; + onHighlight: (event: BaseSyntheticEvent) => void; + onUnhighlight: (event: BaseSyntheticEvent) => void; + setColor: (label: string, color: string) => (event: BaseSyntheticEvent) => void; + getColor: (label: string) => string; +} + +const VisLegendItemComponent = ({ + item, + legendId, + selected, + canFilter, + anchorPosition, + onFilter, + onSelect, + onHighlight, + onUnhighlight, + setColor, + getColor, +}: Props) => { + /** + * Keydown listener for a legend entry. + * This will close the details panel of this legend entry when pressing Escape. + */ + const onLegendEntryKeydown = (event: KeyboardEvent) => { + if (event.keyCode === keyCodes.ESCAPE) { + event.preventDefault(); + event.stopPropagation(); + onSelect(null)(); + } + }; + + const filterOptions: EuiButtonGroupOption[] = [ + { + id: 'filterIn', + label: i18n.translate('visTypeVislib.vislib.legend.filterForValueButtonAriaLabel', { + defaultMessage: 'Filter for value {legendDataLabel}', + values: { legendDataLabel: item.label }, + }), + iconType: 'plusInCircle', + 'data-test-subj': `legend-${item.label}-filterIn`, + }, + { + id: 'filterOut', + label: i18n.translate('visTypeVislib.vislib.legend.filterOutValueButtonAriaLabel', { + defaultMessage: 'Filter out value {legendDataLabel}', + values: { legendDataLabel: item.label }, + }), + iconType: 'minusInCircle', + 'data-test-subj': `legend-${item.label}-filterOut`, + }, + ]; + + const handleFilterChange = (id: string) => { + onFilter(item, id !== 'filterIn'); + }; + + const renderFilterBar = () => ( + <> + + + + ); + + const button = ( + + + {item.label} + + ); + + const renderDetails = () => ( + +
+ {canFilter && renderFilterBar()} + +
+ + + + {legendColors.map(color => ( + + ))} +
+
+
+ ); + + return ( +
  • + {renderDetails()} +
  • + ); +}; + +export const VisLegendItem = memo(VisLegendItemComponent); diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/models.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/models.ts similarity index 100% rename from src/legacy/ui/public/vis/vis_types/vislib_vis_legend/models.ts rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/models.ts diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/pie_utils.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/pie_utils.ts similarity index 100% rename from src/legacy/ui/public/vis/vis_types/vislib_vis_legend/pie_utils.ts rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/pie_utils.ts diff --git a/src/legacy/ui/public/vis/components/tooltip/_collect_branch.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_collect_branch.js similarity index 100% rename from src/legacy/ui/public/vis/components/tooltip/_collect_branch.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_collect_branch.js diff --git a/src/legacy/ui/public/vis/components/tooltip/_collect_branch.test.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_collect_branch.test.js similarity index 100% rename from src/legacy/ui/public/vis/components/tooltip/_collect_branch.test.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_collect_branch.test.js diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_hierarchical_tooltip_formatter.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_hierarchical_tooltip_formatter.js new file mode 100644 index 00000000000000..22fff9cf6a317f --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_hierarchical_tooltip_formatter.js @@ -0,0 +1,93 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import _ from 'lodash'; +import numeral from 'numeral'; +import { renderToStaticMarkup } from 'react-dom/server'; + +import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; + +import { collectBranch } from './_collect_branch'; + +export function hierarchicalTooltipFormatter(metricFieldFormatter) { + return function({ datum }) { + // Collect the current leaf and parents into an array of values + const rows = collectBranch(datum); + + // Map those values to what the tooltipSource.rows format. + _.forEachRight(rows, function(row) { + row.spacer = _.escape(_.repeat(' ', row.depth)); + + let percent; + if (row.item.percentOfGroup !== null && row.item.percentOfGroup !== undefined) { + percent = row.item.percentOfGroup; + } + + row.metric = metricFieldFormatter ? metricFieldFormatter.convert(row.metric) : row.metric; + + if (percent !== null && percent !== undefined) { + row.metric += ' (' + numeral(percent).format('0.[00]%') + ')'; + } + + return row; + }); + + return renderToStaticMarkup( + + + + + + + + + + + + {rows.map((row, index) => ( + + + + + + ))} + +
    {/* {metricCol.label} */}
    +
    + + {row.field} +
    +
    +
    {row.bucket}
    +
    {row.metric}
    +
    + ); + }; +} diff --git a/src/legacy/ui/public/vis/components/tooltip/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_index.scss similarity index 100% rename from src/legacy/ui/public/vis/components/tooltip/_index.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_index.scss diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_pointseries_tooltip_formatter.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_pointseries_tooltip_formatter.js new file mode 100644 index 00000000000000..13c9b8024aac3d --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_pointseries_tooltip_formatter.js @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { renderToStaticMarkup } from 'react-dom/server'; + +export function pointSeriesTooltipFormatter() { + return function tooltipFormatter({ datum, data }) { + if (!datum) return ''; + + const details = []; + + const currentSeries = data.series && data.series.find(serie => serie.rawId === datum.seriesId); + const addDetail = (label, value) => details.push({ label, value }); + + if (datum.extraMetrics) { + datum.extraMetrics.forEach(metric => { + addDetail(metric.label, metric.value); + }); + } + + if (datum.x !== null && datum.x !== undefined) { + addDetail(data.xAxisLabel, data.xAxisFormatter(datum.x)); + } + + if (datum.y !== null && datum.y !== undefined) { + const value = datum.yScale ? datum.yScale * datum.y : datum.y; + addDetail(currentSeries.label, currentSeries.yAxisFormatter(value)); + } + + if (datum.z !== null && datum.z !== undefined) { + addDetail(currentSeries.zLabel, currentSeries.zAxisFormatter(datum.z)); + } + if (datum.series && datum.parent) { + const dimension = datum.parent; + addDetail(dimension.title, datum.series); + } + if (datum.tableRaw) { + addDetail(datum.tableRaw.title, datum.tableRaw.value); + } + + return renderToStaticMarkup( + + + {details.map((detail, index) => ( + + + + + + ))} + +
    +
    {detail.label}
    +
    +
    + {detail.value} + {detail.percent && ({detail.percent})} +
    +
    + ); + }; +} diff --git a/src/legacy/ui/public/vis/components/tooltip/_tooltip.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_tooltip.scss similarity index 97% rename from src/legacy/ui/public/vis/components/tooltip/_tooltip.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_tooltip.scss index 5a30ded7c2e5bd..bafec7edf3b943 100644 --- a/src/legacy/ui/public/vis/components/tooltip/_tooltip.scss +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/_tooltip.scss @@ -28,7 +28,7 @@ } .visTooltip__header { - margin: 0 0 $euiSizeS 0; + margin: 0 0 $euiSizeS; padding: $euiSizeXS $euiSizeS; display: flex; align-items: center; @@ -41,6 +41,7 @@ margin-top: $euiSizeS; } } + .visTooltip__labelContainer, .visTooltip__valueContainer { overflow-wrap: break-word; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/index.js new file mode 100644 index 00000000000000..e394981125a1f5 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/index.js @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { Tooltip } from './tooltip'; +export { hierarchicalTooltipFormatter } from './_hierarchical_tooltip_formatter'; +export { pointSeriesTooltipFormatter } from './_pointseries_tooltip_formatter'; diff --git a/src/legacy/ui/public/vis/components/tooltip/position_tooltip.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/position_tooltip.js similarity index 100% rename from src/legacy/ui/public/vis/components/tooltip/position_tooltip.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/position_tooltip.js diff --git a/src/legacy/ui/public/vis/components/tooltip/tooltip.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/tooltip.js similarity index 97% rename from src/legacy/ui/public/vis/components/tooltip/tooltip.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/tooltip.js index 764ab24da67402..f7d29164eec6f1 100644 --- a/src/legacy/ui/public/vis/components/tooltip/tooltip.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/tooltip/tooltip.js @@ -19,9 +19,10 @@ import d3 from 'd3'; import _ from 'lodash'; -import { Binder } from '../../../binder'; -import { positionTooltip } from './position_tooltip'; import $ from 'jquery'; + +import { Binder } from '../../../legacy_imports'; +import { positionTooltip } from './position_tooltip'; import theme from '@elastic/eui/dist/eui_theme_light.json'; let allContents = []; @@ -217,7 +218,7 @@ Tooltip.prototype.render = function() { return content.id !== id; }); - if (html) allContents.push({ id: id, html: html, order: order }); + if (html) allContents.push({ id, html, order }); const allHtml = _(allContents) .sortBy('order') @@ -253,7 +254,3 @@ Tooltip.prototype.destroy = function() { this.hide(); this.binder.destroy(); }; - -export function TooltipProvider() { - return Tooltip; -} diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_labels.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_labels.js index b8afd826662d72..543e689e8b7417 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_labels.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_labels.js @@ -92,32 +92,43 @@ export class AxisLabels { filterAxisLabels() { const self = this; const config = this.axisConfig; - let startPos = 0; const padding = 1.1; + let lastTickStartEdge = Number.POSITIVE_INFINITY; + let lastTickEndEdge = Number.NEGATIVE_INFINITY; return function(selection) { if (!config.get('labels.filter')) return; const el = $(config.get('rootEl')).find(config.get('elSelector')); - const maxSize = config.isHorizontal() ? el.width() : el.height(); + const upperBound = config.isHorizontal() ? el.width() : el.height(); + const lowerBound = 0; const scaleRange = self.axisScale.scale.range(); const scaleWidth = Math.abs(scaleRange[scaleRange.length - 1] - scaleRange[0]); - const scaleStartPad = 0.5 * (maxSize - scaleWidth); + const scaleStartPad = 0.5 * (upperBound - scaleWidth); selection.selectAll('.tick text').text(function(d) { - const par = d3.select(this.parentNode).node(); - const myPos = + const parentNode = d3.select(this.parentNode).node(); + const currentTickCenter = scaleStartPad + - (config.isHorizontal() ? self.axisScale.scale(d) : maxSize - self.axisScale.scale(d)); - const mySize = - (config.isHorizontal() ? par.getBBox().width : par.getBBox().height) * padding; - const halfSize = mySize / 2; - - if (startPos + halfSize < myPos && maxSize > myPos + halfSize) { - startPos = myPos + halfSize; - return this.textContent; - } else { + (config.isHorizontal() ? self.axisScale.scale(d) : upperBound - self.axisScale.scale(d)); + const currentTickSize = + (config.isHorizontal() ? parentNode.getBBox().width : parentNode.getBBox().height) * + padding; + const currentTickHalfSize = currentTickSize / 2; + const currentTickStartEdge = currentTickCenter - currentTickHalfSize; + const currentTickEndEdge = currentTickCenter + currentTickHalfSize; + + const outsideUpperBound = currentTickEndEdge > upperBound; + const outsideLowerBound = currentTickStartEdge < lowerBound; + const overlapsLastTick = + currentTickEndEdge >= lastTickStartEdge && currentTickStartEdge <= lastTickEndEdge; + + if (outsideUpperBound || outsideLowerBound || overlapsLastTick) { d3.select(this.parentNode).remove(); + } else { + lastTickStartEdge = currentTickCenter - currentTickHalfSize; + lastTickEndEdge = currentTickCenter + currentTickHalfSize; + return this.textContent; } }); }; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_title.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_title.js index 1c84f98614b05b..3caaf99cbb5c12 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_title.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_title.js @@ -21,7 +21,7 @@ import d3 from 'd3'; import _ from 'lodash'; import { ErrorHandler } from './_error_handler'; -import { Tooltip } from '../../legacy_imports'; +import { Tooltip } from '../components/tooltip'; export class ChartTitle extends ErrorHandler { constructor(visConfig) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.js index eab3bc02f4eec9..ebaf64874d7298 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.js @@ -229,7 +229,7 @@ export const vislibPointSeriesTypes = { const tooManySeries = defaults.charts.length && defaults.charts[0].series.length > cfg.heatmapMaxBuckets; if (hasCharts && tooManySeries) { - defaults.error = i18n.translate('kbnVislibVisTypes.vislib.heatmap.maxBucketsText', { + defaults.error = i18n.translate('visTypeVislib.vislib.heatmap.maxBucketsText', { defaultMessage: 'There are too many series defined ({nr}). The configured maximum is {max}.', values: { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js new file mode 100644 index 00000000000000..0c584fedda217d --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js @@ -0,0 +1,124 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { buildHierarchicalData, buildPointSeriesData, getFormat } from '../legacy_imports'; + +function tableResponseHandler(table, dimensions) { + const converted = { tables: [] }; + const split = dimensions.splitColumn || dimensions.splitRow; + + if (split) { + converted.direction = dimensions.splitRow ? 'row' : 'column'; + const splitColumnIndex = split[0].accessor; + const splitColumnFormatter = getFormat(split[0].format); + const splitColumn = table.columns[splitColumnIndex]; + const splitMap = {}; + let splitIndex = 0; + + table.rows.forEach((row, rowIndex) => { + const splitValue = row[splitColumn.id]; + + if (!splitMap.hasOwnProperty(splitValue)) { + splitMap[splitValue] = splitIndex++; + const tableGroup = { + $parent: converted, + title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`, + name: splitColumn.name, + key: splitValue, + column: splitColumnIndex, + row: rowIndex, + table, + tables: [], + }; + tableGroup.tables.push({ + $parent: tableGroup, + columns: table.columns, + rows: [], + }); + + converted.tables.push(tableGroup); + } + + const tableIndex = splitMap[splitValue]; + converted.tables[tableIndex].tables[0].rows.push(row); + }); + } else { + converted.tables.push({ + columns: table.columns, + rows: table.rows, + }); + } + + return converted; +} + +function convertTableGroup(tableGroup, convertTable) { + const tables = tableGroup.tables; + + if (!tables.length) return; + + const firstChild = tables[0]; + if (firstChild.columns) { + const chart = convertTable(firstChild); + // if chart is within a split, assign group title to its label + if (tableGroup.$parent) { + chart.label = tableGroup.title; + } + return chart; + } + + const out = {}; + let outList; + + tables.forEach(function(table) { + if (!outList) { + const direction = tableGroup.direction === 'row' ? 'rows' : 'columns'; + outList = out[direction] = []; + } + + let output; + if ((output = convertTableGroup(table, convertTable))) { + outList.push(output); + } + }); + + return out; +} + +function handlerFunction(convertTable) { + return function(response, dimensions) { + const tableGroup = tableResponseHandler(response, dimensions); + let converted = convertTableGroup(tableGroup, table => { + return convertTable(table, dimensions); + }); + if (!converted) { + // mimic a row of tables that doesn't have any tables + // https://github.com/elastic/kibana/blob/7bfb68cd24ed42b1b257682f93c50cd8d73e2520/src/kibana/components/vislib/components/zero_injection/inject_zeros.js#L32 + converted = { rows: [] }; + } + + converted.hits = response.rows.length; + + return converted; + }; +} + +export const vislibSeriesResponseHandler = handlerFunction(buildPointSeriesData); + +export const vislibSlicesResponseHandler = handlerFunction(buildHierarchicalData); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js index ac6e8130a846ad..a36c7c4774dadf 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js @@ -22,7 +22,12 @@ import _ from 'lodash'; import { dataLabel } from '../lib/_data_label'; import { Dispatch } from '../lib/dispatch'; -import { Tooltip, getFormat } from '../../legacy_imports'; +import { getFormat } from '../../legacy_imports'; +import { + Tooltip, + hierarchicalTooltipFormatter, + pointSeriesTooltipFormatter, +} from '../components/tooltip'; /** * The Base Class for all visualizations. @@ -45,8 +50,8 @@ export class Chart { const fieldFormatter = getFormat(this.handler.data.get('tooltipFormatter')); const tooltipFormatterProvider = this.handler.visConfig.get('type') === 'pie' - ? deps.getHierarchicalTooltipFormatter() - : deps.getPointSeriesTooltipFormatter(); + ? hierarchicalTooltipFormatter + : pointSeriesTooltipFormatter; const tooltipFormatter = tooltipFormatterProvider(fieldFormatter); if (this.handler.visConfig && this.handler.visConfig.get('addTooltip', false)) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series.js index c838c51d34bf5a..53f06c79d178c2 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series.js @@ -21,7 +21,7 @@ import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; -import { Tooltip } from '../../legacy_imports'; +import { Tooltip } from '../components/tooltip'; import { Chart } from './_chart'; import { TimeMarker } from './time_marker'; import { seriesTypes } from './point_series/series_types'; @@ -153,18 +153,10 @@ export class PointSeries extends Chart { .attr('class', 'endzone') .append('rect') .attr('class', 'zone') - .attr('x', function(d) { - return isHorizontal ? d.x : 0; - }) - .attr('y', function(d) { - return isHorizontal ? 0 : d.x; - }) - .attr('height', function(d) { - return isHorizontal ? height : d.w; - }) - .attr('width', function(d) { - return isHorizontal ? d.w : width; - }); + .attr('x', d => (isHorizontal ? d.x : 0)) + .attr('y', d => (isHorizontal ? 0 : d.x)) + .attr('height', d => (isHorizontal ? height : d.w)) + .attr('width', d => (isHorizontal ? d.w : width)); function callPlay(event) { const boundData = event.target.__data__; diff --git a/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable.ts index c1b049ab5e969f..557035b91367e3 100644 --- a/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -29,7 +29,6 @@ import { getTableAggs } from 'ui/visualize/loader/pipeline_helpers/utilities'; import { AppState } from 'ui/state_management/app_state'; import { npStart } from 'ui/new_platform'; import { IExpressionLoaderParams } from 'src/plugins/expressions/public'; -import { ISearchSource } from 'ui/courier'; import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; import { IIndexPattern, @@ -38,6 +37,7 @@ import { onlyDisabledFiltersChanged, esFilters, mapAndFlattenFilters, + ISearchSource, } from '../../../../../plugins/data/public'; import { EmbeddableInput, diff --git a/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 3f29f97afee489..e5836c13720687 100644 --- a/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -18,17 +18,14 @@ */ import { i18n } from '@kbn/i18n'; - -import chrome from 'ui/chrome'; - -import { SavedObjectAttributes } from 'kibana/server'; +import { SavedObjectAttributes } from 'kibana/public'; import { EmbeddableFactory, ErrorEmbeddable, Container, EmbeddableOutput, } from '../../../../../plugins/embeddable/public'; -import { showNewVisModal } from '../../../kibana/public/visualize/np_ready/wizard/show_new_vis'; +import { showNewVisModal } from '../../../kibana/public/visualize'; import { SavedVisualizations } from '../../../kibana/public/visualize/np_ready/types'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; import { getIndexPattern } from './get_index_pattern'; @@ -61,11 +58,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< > { public readonly type = VISUALIZE_EMBEDDABLE_TYPE; - static async createVisualizeEmbeddableFactory(): Promise { - return new VisualizeEmbeddableFactory(); - } - - constructor() { + constructor(private getSavedVisualizationsLoader: () => SavedVisualizations) { super({ savedObjectMetaData: { name: i18n.translate('visualizations.savedObjectName', { defaultMessage: 'Visualization' }), @@ -111,8 +104,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< input: Partial & { id: string }, parent?: Container ): Promise { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const savedVisualizations = $injector.get('savedVisualizations'); + const savedVisualizations = this.getSavedVisualizationsLoader(); try { const visId = savedObject.id as string; @@ -151,13 +143,10 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< input: Partial & { id: string }, parent?: Container ): Promise { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const savedVisualizations = $injector.get('savedVisualizations'); + const savedVisualizations = this.getSavedVisualizationsLoader(); try { - const visId = savedObjectId; - - const savedObject = await savedVisualizations.get(visId); + const savedObject = await savedVisualizations.get(savedObjectId); return this.createFromObject(savedObject, input, parent); } catch (e) { console.error(e); // eslint-disable-line no-console diff --git a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts index b750557c24b94a..fd40c831ce0efa 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts +++ b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts @@ -18,7 +18,6 @@ */ export { PersistedState } from '../../../ui/public/persisted_state'; -export { SearchError } from '../../../ui/public/courier/search_strategy/search_error'; export { AggConfig } from '../../../ui/public/agg_types/agg_config'; export { AggConfigs } from '../../../ui/public/agg_types/agg_configs'; export { diff --git a/src/legacy/core_plugins/visualizations/public/legacy_mocks.ts b/src/legacy/core_plugins/visualizations/public/legacy_mocks.ts index e6ca678db563d6..6cd57bb88bc261 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy_mocks.ts +++ b/src/legacy/core_plugins/visualizations/public/legacy_mocks.ts @@ -17,4 +17,5 @@ * under the License. */ -export { searchSourceMock } from '../../../ui/public/courier/search_source/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export { searchSourceMock } from '../../../../plugins/data/public/search/search_source/mocks'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx index 8b9fded919f135..406f24741c9117 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx @@ -19,7 +19,7 @@ import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; import React from 'react'; -import { SearchError } from '../../../legacy_imports'; +import { SearchError } from '../../../../../../../plugins/data/public'; interface VisualizationRequestErrorProps { onInit?: () => void; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts index 2e9d055858a483..4dffcb8ce995e3 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts @@ -45,6 +45,7 @@ export function plugin(initializerContext: PluginInitializerContext) { /** @public static code */ export { Vis, VisParams, VisState } from './vis'; export * from './filters'; +export { TypesService } from './types/types_service'; export { Status } from './legacy/update_status'; export { buildPipeline, buildVislibDimensions, SchemaConfig } from './legacy/build_pipeline'; @@ -52,3 +53,6 @@ export { buildPipeline, buildVislibDimensions, SchemaConfig } from './legacy/bui // @ts-ignore export { updateOldState } from './legacy/vis_update_state'; export { calculateObjectHash } from './legacy/calculate_object_hash'; +// @ts-ignore +export { createFiltersFromEvent } from './filters/vis_filters'; +export { createSavedVisLoader } from '../../saved_visualizations/saved_visualizations'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts index a3bf98b5e74a30..6749a44b4d5b37 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts @@ -21,14 +21,13 @@ import { cloneDeep, get } from 'lodash'; // @ts-ignore import moment from 'moment'; import { SerializedFieldFormat } from 'src/plugins/expressions/public'; +import { ISearchSource } from 'src/plugins/data/public'; import { AggConfig, setBounds, isDateHistogramBucketAggConfig, createFormat, } from '../../../legacy_imports'; -// eslint-disable-next-line -import { ISearchSource } from '../../../../../../ui/public/courier/search_source/search_source'; import { Vis, VisParams, VisState } from '..'; interface SchemaConfigParams { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts index 2fa85d86a794ea..4c1783408708a3 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts @@ -48,6 +48,7 @@ const createStartContract = (): VisualizationsStart => ({ all: jest.fn(), getAliases: jest.fn(), }, + getSavedVisualizationsLoader: jest.fn(), }); const createInstance = async () => { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts index cfd22f88167c58..01059044b98c21 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts @@ -38,6 +38,11 @@ import { visualization as visualizationFunction } from './expressions/visualizat import { visualization as visualizationRenderer } from './expressions/visualization_renderer'; import { DataPublicPluginStart } from '../../../../../../plugins/data/public'; import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public'; +import { + createSavedVisLoader, + SavedObjectKibanaServicesWithVisualizations, +} from '../../saved_visualizations'; +import { SavedVisualizations } from '../../../../kibana/public/visualize/np_ready/types'; /** * Interface for this plugin's returned setup/start contracts. * @@ -47,9 +52,9 @@ export interface VisualizationsSetup { types: TypesSetup; } -// eslint-disable-next-line @typescript-eslint/no-empty-interface export interface VisualizationsStart { types: TypesStart; + getSavedVisualizationsLoader: () => SavedVisualizations; } export interface VisualizationsSetupDeps { @@ -79,6 +84,8 @@ export class VisualizationsPlugin VisualizationsStartDeps > { private readonly types: TypesService = new TypesService(); + private savedVisualizations?: SavedVisualizations; + private savedVisualizationDependencies?: SavedObjectKibanaServicesWithVisualizations; constructor(initializerContext: PluginInitializerContext) {} @@ -92,7 +99,7 @@ export class VisualizationsPlugin expressions.registerFunction(visualizationFunction); expressions.registerRenderer(visualizationRenderer); - const embeddableFactory = new VisualizeEmbeddableFactory(); + const embeddableFactory = new VisualizeEmbeddableFactory(this.getSavedVisualizationsLoader); embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory); return { @@ -110,12 +117,28 @@ export class VisualizationsPlugin setIndexPatterns(data.indexPatterns); setFilterManager(data.query.filterManager); + this.savedVisualizationDependencies = { + savedObjectsClient: core.savedObjects.client, + indexPatterns: data.indexPatterns, + chrome: core.chrome, + overlays: core.overlays, + visualizationTypes: types, + }; + return { types, + getSavedVisualizationsLoader: () => this.getSavedVisualizationsLoader(), }; } public stop() { this.types.stop(); } + + private getSavedVisualizationsLoader = () => { + if (!this.savedVisualizations) { + this.savedVisualizations = createSavedVisLoader(this.savedVisualizationDependencies!); + } + return this.savedVisualizations; + }; } diff --git a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/_saved_vis.ts b/src/legacy/core_plugins/visualizations/public/saved_visualizations/_saved_vis.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/_saved_vis.ts rename to src/legacy/core_plugins/visualizations/public/saved_visualizations/_saved_vis.ts index a0a6f8ea1c8a24..b501c8b68484f4 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/_saved_vis.ts +++ b/src/legacy/core_plugins/visualizations/public/saved_visualizations/_saved_vis.ts @@ -28,13 +28,13 @@ import { Vis } from 'ui/vis'; import { SavedObject, SavedObjectKibanaServices } from 'ui/saved_objects/types'; import { createSavedObjectClass } from 'ui/saved_objects/saved_object'; -import { updateOldState } from '../../../../visualizations/public'; +import { updateOldState } from '../index'; import { extractReferences, injectReferences } from './saved_visualization_references'; -import { IIndexPattern } from '../../../../../../plugins/data/public'; -import { VisSavedObject } from '../legacy_imports'; +import { IIndexPattern } from '../../../../../plugins/data/public'; +import { VisSavedObject } from '../embeddable/visualize_embeddable'; -import { createSavedSearchesService } from '../../discover'; -import { VisualizeConstants } from '../np_ready/visualize_constants'; +import { createSavedSearchesLoader } from '../../../kibana/public/discover'; +import { VisualizeConstants } from '../../../kibana/public/visualize'; async function _afterEsResp(savedVis: VisSavedObject, services: any) { await _getLinkedSavedSearch(savedVis, services); @@ -56,7 +56,7 @@ async function _getLinkedSavedSearch(savedVis: VisSavedObject, services: any) { savedVis.savedSearch.destroy(); delete savedVis.savedSearch; } - const savedSearches = createSavedSearchesService(services); + const savedSearches = createSavedSearchesLoader(services); if (linkedSearch) { savedVis.savedSearch = await savedSearches.get(savedVis.savedSearchId!); diff --git a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/find_list_items.js b/src/legacy/core_plugins/visualizations/public/saved_visualizations/find_list_items.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/find_list_items.js rename to src/legacy/core_plugins/visualizations/public/saved_visualizations/find_list_items.js diff --git a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/find_list_items.test.js b/src/legacy/core_plugins/visualizations/public/saved_visualizations/find_list_items.test.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/find_list_items.test.js rename to src/legacy/core_plugins/visualizations/public/saved_visualizations/find_list_items.test.js diff --git a/src/legacy/core_plugins/visualizations/public/saved_visualizations/index.ts b/src/legacy/core_plugins/visualizations/public/saved_visualizations/index.ts new file mode 100644 index 00000000000000..cba68feca81f71 --- /dev/null +++ b/src/legacy/core_plugins/visualizations/public/saved_visualizations/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './saved_visualizations'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_references.test.ts b/src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualization_references.test.ts similarity index 98% rename from src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_references.test.ts rename to src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualization_references.test.ts index 98f5458d5eecc2..6549b317d16346 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_references.test.ts +++ b/src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualization_references.test.ts @@ -18,7 +18,7 @@ */ import { extractReferences, injectReferences } from './saved_visualization_references'; -import { VisSavedObject } from '../../../../visualizations/public/embeddable/visualize_embeddable'; +import { VisSavedObject } from '../embeddable/visualize_embeddable'; describe('extractReferences', () => { test('extracts nothing if savedSearchId is empty', () => { diff --git a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_references.ts b/src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts similarity index 96% rename from src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_references.ts rename to src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts index 403e9c5a8172d6..330f5e2dacd10a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_references.ts +++ b/src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { SavedObjectAttributes, SavedObjectReference } from 'kibana/server'; -import { VisSavedObject } from '../../../../visualizations/public/embeddable/visualize_embeddable'; +import { SavedObjectAttributes, SavedObjectReference } from 'kibana/public'; +import { VisSavedObject } from '../embeddable/visualize_embeddable'; export function extractReferences({ attributes, diff --git a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.ts b/src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualizations.ts similarity index 85% rename from src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.ts rename to src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualizations.ts index d51fae74289391..4b2a8e27c02086 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.ts +++ b/src/legacy/core_plugins/visualizations/public/saved_visualizations/saved_visualizations.ts @@ -22,19 +22,19 @@ import { SavedObjectKibanaServices } from 'ui/saved_objects/types'; // @ts-ignore import { findListItems } from './find_list_items'; import { createSavedVisClass } from './_saved_vis'; -import { createVisualizeEditUrl } from '../np_ready/visualize_constants'; -import { VisualizationsStart } from '../../../../visualizations/public/np_ready/public'; +import { createVisualizeEditUrl } from '../../../kibana/public/visualize'; +import { TypesStart } from '../np_ready/public/types'; -interface SavedObjectKibanaServicesWithVisualizations extends SavedObjectKibanaServices { - visualizations: VisualizationsStart; +export interface SavedObjectKibanaServicesWithVisualizations extends SavedObjectKibanaServices { + visualizationTypes: TypesStart; } export function createSavedVisLoader(services: SavedObjectKibanaServicesWithVisualizations) { - const { savedObjectsClient, visualizations } = services; + const { savedObjectsClient, visualizationTypes } = services; class SavedObjectLoaderVisualize extends SavedObjectLoader { mapHitSource = (source: Record, id: string) => { - const visTypes = visualizations.types; + const visTypes = visualizationTypes; source.id = id; source.url = this.urlFor(id); @@ -72,7 +72,7 @@ export function createSavedVisLoader(services: SavedObjectKibanaServicesWithVisu size, mapSavedObjectApiHits: this.mapSavedObjectApiHits.bind(this), savedObjectsClient, - visTypes: visualizations.types.getAliases(), + visTypes: visualizationTypes.getAliases(), }); } } diff --git a/src/legacy/plugin_discovery/types.ts b/src/legacy/plugin_discovery/types.ts index fe886b9d178111..9425003eae8747 100644 --- a/src/legacy/plugin_discovery/types.ts +++ b/src/legacy/plugin_discovery/types.ts @@ -24,6 +24,7 @@ import { Capabilities } from '../../core/server'; import { SavedObjectsSchemaDefinition } from '../../core/server/saved_objects/schema'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { SavedObjectsManagementDefinition } from '../../core/server/saved_objects/management'; +import { AppCategory } from '../../core/types'; /** * Usage @@ -53,6 +54,7 @@ export interface LegacyPluginOptions { uiExports: Partial<{ app: Partial<{ title: string; + category?: AppCategory; description: string; main: string; icon: string; diff --git a/src/legacy/server/config/override.js b/src/legacy/server/config/override.js index 934b2165dddcf5..bab9387ac006fa 100644 --- a/src/legacy/server/config/override.js +++ b/src/legacy/server/config/override.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import explodeBy from './explode_by'; -import { getFlattenedObject } from '../../utils'; +import { getFlattenedObject } from '../../../core/utils'; export default function(target, source) { const _target = getFlattenedObject(target); diff --git a/src/legacy/server/kbn_server.js b/src/legacy/server/kbn_server.js index 8ab55d4c517b59..6991527a9503c6 100644 --- a/src/legacy/server/kbn_server.js +++ b/src/legacy/server/kbn_server.js @@ -36,7 +36,6 @@ import * as Plugins from './plugins'; import { indexPatternsMixin } from './index_patterns'; import { savedObjectsMixin } from './saved_objects/saved_objects_mixin'; import { capabilitiesMixin } from './capabilities'; -import { urlShorteningMixin } from './url_shortening'; import { serverExtensionsMixin } from './server_extensions'; import { uiMixin } from '../ui'; import { sassMixin } from './sass'; @@ -123,9 +122,6 @@ export default class KbnServer { // setup capabilities routes capabilitiesMixin, - // setup routes for short urls - urlShorteningMixin, - // ensure that all bundles are built, or that the // watch bundle server is running optimizeMixin, diff --git a/src/legacy/server/url_shortening/index.js b/src/legacy/server/url_shortening/index.js deleted file mode 100644 index 031af0618d7bcb..00000000000000 --- a/src/legacy/server/url_shortening/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { urlShorteningMixin } from './url_shortening_mixin'; diff --git a/src/legacy/server/url_shortening/routes/create_routes.js b/src/legacy/server/url_shortening/routes/create_routes.js deleted file mode 100644 index 9540e7441a268b..00000000000000 --- a/src/legacy/server/url_shortening/routes/create_routes.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { shortUrlLookupProvider } from './lib/short_url_lookup'; -import { createGotoRoute } from './goto'; - -export function createRoutes(server) { - const shortUrlLookup = shortUrlLookupProvider(server); - - server.route(createGotoRoute({ server, shortUrlLookup })); -} diff --git a/src/legacy/server/url_shortening/routes/goto.js b/src/legacy/server/url_shortening/routes/goto.js deleted file mode 100644 index 7a874786423d81..00000000000000 --- a/src/legacy/server/url_shortening/routes/goto.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { handleShortUrlError } from './lib/short_url_error'; -import { shortUrlAssertValid } from './lib/short_url_assert_valid'; - -export const createGotoRoute = ({ server, shortUrlLookup }) => ({ - method: 'GET', - path: '/goto_LP/{urlId}', - handler: async function(request, h) { - try { - const url = await shortUrlLookup.getUrl(request.params.urlId, request); - shortUrlAssertValid(url); - - const app = server.getHiddenUiAppById('stateSessionStorageRedirect'); - return h.renderApp(app, { - redirectUrl: url, - }); - } catch (err) { - throw handleShortUrlError(err); - } - }, -}); diff --git a/src/legacy/server/url_shortening/routes/lib/short_url_assert_valid.js b/src/legacy/server/url_shortening/routes/lib/short_url_assert_valid.js deleted file mode 100644 index ff2b0f214e5eed..00000000000000 --- a/src/legacy/server/url_shortening/routes/lib/short_url_assert_valid.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { parse } from 'url'; -import { trim } from 'lodash'; -import Boom from 'boom'; - -export function shortUrlAssertValid(url) { - const { protocol, hostname, pathname } = parse(url); - - if (protocol) { - throw Boom.notAcceptable(`Short url targets cannot have a protocol, found "${protocol}"`); - } - - if (hostname) { - throw Boom.notAcceptable(`Short url targets cannot have a hostname, found "${hostname}"`); - } - - const pathnameParts = trim(pathname, '/').split('/'); - if (pathnameParts.length !== 2) { - throw Boom.notAcceptable( - `Short url target path must be in the format "/app/{{appId}}", found "${pathname}"` - ); - } -} diff --git a/src/legacy/server/url_shortening/routes/lib/short_url_assert_valid.test.js b/src/legacy/server/url_shortening/routes/lib/short_url_assert_valid.test.js deleted file mode 100644 index f83073e6aefe90..00000000000000 --- a/src/legacy/server/url_shortening/routes/lib/short_url_assert_valid.test.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { shortUrlAssertValid } from './short_url_assert_valid'; - -describe('shortUrlAssertValid()', () => { - const invalid = [ - ['protocol', 'http://localhost:5601/app/kibana'], - ['protocol', 'https://localhost:5601/app/kibana'], - ['protocol', 'mailto:foo@bar.net'], - ['protocol', 'javascript:alert("hi")'], // eslint-disable-line no-script-url - ['hostname', 'localhost/app/kibana'], - ['hostname and port', 'local.host:5601/app/kibana'], - ['hostname and auth', 'user:pass@localhost.net/app/kibana'], - ['path traversal', '/app/../../not-kibana'], - ['deep path', '/app/kibana/foo'], - ['deep path', '/app/kibana/foo/bar'], - ['base path', '/base/app/kibana'], - ]; - - invalid.forEach(([desc, url]) => { - it(`fails when url has ${desc}`, () => { - try { - shortUrlAssertValid(url); - throw new Error(`expected assertion to throw`); - } catch (err) { - if (!err || !err.isBoom) { - throw err; - } - } - }); - }); - - const valid = [ - '/app/kibana', - '/app/monitoring#angular/route', - '/app/text#document-id', - '/app/some?with=query', - '/app/some?with=query#and-a-hash', - ]; - - valid.forEach(url => { - it(`allows ${url}`, () => { - shortUrlAssertValid(url); - }); - }); -}); diff --git a/src/legacy/server/url_shortening/routes/lib/short_url_error.js b/src/legacy/server/url_shortening/routes/lib/short_url_error.js deleted file mode 100644 index ed44ba21aa4c41..00000000000000 --- a/src/legacy/server/url_shortening/routes/lib/short_url_error.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Boom from 'boom'; - -export function handleShortUrlError(error) { - return Boom.boomify(error, { - statusCode: error.statusCode || error.status || 500, - }); -} diff --git a/src/legacy/server/url_shortening/routes/lib/short_url_error.test.js b/src/legacy/server/url_shortening/routes/lib/short_url_error.test.js deleted file mode 100644 index 4eca6320ec834e..00000000000000 --- a/src/legacy/server/url_shortening/routes/lib/short_url_error.test.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import { handleShortUrlError } from './short_url_error'; - -function createErrorWithStatus(status) { - const error = new Error(); - error.status = status; - return error; -} - -function createErrorWithStatusCode(statusCode) { - const error = new Error(); - error.statusCode = statusCode; - return error; -} - -describe('handleShortUrlError()', () => { - const caughtErrorsWithStatus = [ - createErrorWithStatus(401), - createErrorWithStatus(403), - createErrorWithStatus(404), - ]; - - const caughtErrorsWithStatusCode = [ - createErrorWithStatusCode(401), - createErrorWithStatusCode(403), - createErrorWithStatusCode(404), - ]; - - const uncaughtErrors = [new Error(), createErrorWithStatus(500), createErrorWithStatusCode(500)]; - - caughtErrorsWithStatus.forEach(err => { - it(`should handle errors with status of ${err.status}`, function() { - expect(_.get(handleShortUrlError(err), 'output.statusCode')).toBe(err.status); - }); - }); - - caughtErrorsWithStatusCode.forEach(err => { - it(`should handle errors with statusCode of ${err.statusCode}`, function() { - expect(_.get(handleShortUrlError(err), 'output.statusCode')).toBe(err.statusCode); - }); - }); - - uncaughtErrors.forEach(err => { - it(`should not handle unknown errors`, function() { - expect(_.get(handleShortUrlError(err), 'output.statusCode')).toBe(500); - }); - }); -}); diff --git a/src/legacy/server/url_shortening/routes/lib/short_url_lookup.js b/src/legacy/server/url_shortening/routes/lib/short_url_lookup.js deleted file mode 100644 index a8a01d1433a7a3..00000000000000 --- a/src/legacy/server/url_shortening/routes/lib/short_url_lookup.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { get } from 'lodash'; - -export function shortUrlLookupProvider(server) { - async function updateMetadata(doc, req) { - try { - await req.getSavedObjectsClient().update('url', doc.id, { - accessDate: new Date(), - accessCount: get(doc, 'attributes.accessCount', 0) + 1, - }); - } catch (err) { - server.log('Warning: Error updating url metadata', err); - //swallow errors. It isn't critical if there is no update. - } - } - - return { - async getUrl(id, req) { - const doc = await req.getSavedObjectsClient().get('url', id); - updateMetadata(doc, req); - - return doc.attributes.url; - }, - }; -} diff --git a/src/legacy/server/url_shortening/routes/lib/short_url_lookup.test.js b/src/legacy/server/url_shortening/routes/lib/short_url_lookup.test.js deleted file mode 100644 index e8bf72a142d117..00000000000000 --- a/src/legacy/server/url_shortening/routes/lib/short_url_lookup.test.js +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import sinon from 'sinon'; -import { shortUrlLookupProvider } from './short_url_lookup'; -import { SavedObjectsClient } from '../../../../../core/server'; - -describe('shortUrlLookupProvider', () => { - const ID = 'bf00ad16941fc51420f91a93428b27a0'; - const TYPE = 'url'; - const URL = 'http://elastic.co'; - const server = { log: sinon.stub() }; - const sandbox = sinon.createSandbox(); - - let savedObjectsClient; - let req; - let shortUrl; - - beforeEach(() => { - savedObjectsClient = { - get: sandbox.stub(), - create: sandbox.stub().returns(Promise.resolve({ id: ID })), - update: sandbox.stub(), - errors: SavedObjectsClient.errors, - }; - - req = { getSavedObjectsClient: () => savedObjectsClient }; - shortUrl = shortUrlLookupProvider(server); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('getUrl', () => { - beforeEach(() => { - const attributes = { accessCount: 2, url: URL }; - savedObjectsClient.get.returns({ id: ID, attributes }); - }); - - it('provides the ID to savedObjectsClient', async () => { - await shortUrl.getUrl(ID, req); - - sinon.assert.calledOnce(savedObjectsClient.get); - const [type, id] = savedObjectsClient.get.getCall(0).args; - - expect(type).toEqual(TYPE); - expect(id).toEqual(ID); - }); - - it('returns the url', async () => { - const response = await shortUrl.getUrl(ID, req); - expect(response).toEqual(URL); - }); - - it('increments accessCount', async () => { - await shortUrl.getUrl(ID, req); - - sinon.assert.calledOnce(savedObjectsClient.update); - const [type, id, attributes] = savedObjectsClient.update.getCall(0).args; - - expect(type).toEqual(TYPE); - expect(id).toEqual(ID); - expect(Object.keys(attributes).sort()).toEqual(['accessCount', 'accessDate']); - expect(attributes.accessCount).toEqual(3); - }); - }); -}); diff --git a/src/legacy/server/url_shortening/url_shortening_mixin.js b/src/legacy/server/url_shortening/url_shortening_mixin.js deleted file mode 100644 index 867898cac845a3..00000000000000 --- a/src/legacy/server/url_shortening/url_shortening_mixin.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { createRoutes } from './routes/create_routes'; - -export function urlShorteningMixin(kbnServer, server) { - createRoutes(server); -} diff --git a/src/legacy/ui/field_formats/index.ts b/src/legacy/ui/field_formats/index.ts deleted file mode 100644 index e5cc2cb33d087b..00000000000000 --- a/src/legacy/ui/field_formats/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { fieldFormatsMixin } from './mixin/field_formats_mixin'; diff --git a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts b/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts deleted file mode 100644 index 370c3127062423..00000000000000 --- a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { has } from 'lodash'; -import { Legacy } from 'kibana'; -import { FieldFormatsService } from './field_formats_service'; -import { IFieldFormatType } from '../../../../plugins/data/public'; - -export function fieldFormatsMixin(kbnServer: any, server: Legacy.Server) { - const fieldFormatClasses: IFieldFormatType[] = []; - - // for use outside of the request context, for special cases - server.decorate('server', 'fieldFormatServiceFactory', async function(uiSettings) { - const uiConfigs = await uiSettings.getAll(); - const registeredUiSettings = uiSettings.getRegistered(); - Object.keys(registeredUiSettings).forEach(key => { - if (has(uiConfigs, key) && registeredUiSettings[key].type === 'json') { - uiConfigs[key] = JSON.parse(uiConfigs[key]); - } - }); - const getConfig = (key: string) => uiConfigs[key]; - - return new FieldFormatsService(fieldFormatClasses, getConfig); - }); - - server.decorate('server', 'registerFieldFormat', customFieldFormat => { - fieldFormatClasses.push(customFieldFormat); - }); -} diff --git a/src/legacy/ui/field_formats/mixin/field_formats_service.test.ts b/src/legacy/ui/field_formats/mixin/field_formats_service.test.ts deleted file mode 100644 index 4ca181d3f69d47..00000000000000 --- a/src/legacy/ui/field_formats/mixin/field_formats_service.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { FieldFormatsService } from './field_formats_service'; -import { NumberFormat } from '../../../../plugins/data/public'; - -const getConfig = (key: string) => { - switch (key) { - case 'format:defaultTypeMap': - return { - number: { id: 'number', params: {} }, - _default_: { id: 'string', params: {} }, - }; - case 'format:number:defaultPattern': - return '0,0.[000]'; - } -}; - -describe('FieldFormatsService', () => { - let fieldFormatsService: FieldFormatsService; - - beforeEach(() => { - const fieldFormatClasses = [NumberFormat]; - - fieldFormatsService = new FieldFormatsService(fieldFormatClasses, getConfig); - }); - - test('FieldFormats are accessible via getType method', () => { - const Type = fieldFormatsService.getType('number'); - - expect(Type.id).toBe('number'); - }); - - test('getDefaultInstance returns default FieldFormat instance for fieldType', () => { - const instance = fieldFormatsService.getDefaultInstance('number'); - - expect(instance.type.id).toBe('number'); - expect(instance.convert('0.33333')).toBe('0.333'); - }); -}); diff --git a/src/legacy/ui/field_formats/mixin/field_formats_service.ts b/src/legacy/ui/field_formats/mixin/field_formats_service.ts deleted file mode 100644 index c5bc25333985b5..00000000000000 --- a/src/legacy/ui/field_formats/mixin/field_formats_service.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { indexBy, Dictionary } from 'lodash'; -import { FieldFormat, IFieldFormatType } from '../../../../plugins/data/common'; - -interface FieldFormatConfig { - id: string; - params?: Record; -} - -export class FieldFormatsService { - getConfig: any; - _fieldFormats: Dictionary; - - constructor(fieldFormatClasses: IFieldFormatType[], getConfig: Function) { - this._fieldFormats = indexBy(fieldFormatClasses, 'id'); - this.getConfig = getConfig; - } - - /** - * Get the id of the default type for this field type - * using the format:defaultTypeMap config map - * - * @param {String} fieldType - the field type - * @return {FieldFormatConfig} - */ - getDefaultConfig(fieldType: string): FieldFormatConfig { - const defaultMap = this.getConfig('format:defaultTypeMap'); - return defaultMap[fieldType] || defaultMap._default_; - } - - /** - * Get the default fieldFormat instance for a field type. - * - * @param {String} fieldType - * @return {FieldFormat} - */ - getDefaultInstance(fieldType: string): FieldFormat { - return this.getInstance(this.getDefaultConfig(fieldType)); - } - - /** - * Get the fieldFormat instance for a field format configuration. - * - * @param {FieldFormatConfig} field format config - * @return {FieldFormat} - */ - getInstance(conf: FieldFormatConfig): FieldFormat { - // @ts-ignore - return new this._fieldFormats[conf.id](conf.params, this.getConfig); - } - - /** - * Get a FieldFormat type (class) by it's id. - * - * @param {String} fieldFormatId - the FieldFormat id - * @return {FieldFormat} - */ - getType(fieldFormatId: string): any { - return this._fieldFormats[fieldFormatId]; - } -} diff --git a/src/legacy/ui/public/_index.scss b/src/legacy/ui/public/_index.scss index f5a1d0a7922a74..e4e58019dda691 100644 --- a/src/legacy/ui/public/_index.scss +++ b/src/legacy/ui/public/_index.scss @@ -10,7 +10,6 @@ @import './accessibility/index'; @import './chrome/index'; -@import './courier/index'; @import './collapsible_sidebar/index'; @import './directives/index'; @import './error_auto_create_index/index'; diff --git a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js b/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js index 6397c3b0b41bb5..f96f194108ff9f 100644 --- a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js +++ b/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js @@ -18,22 +18,26 @@ */ import { buildHierarchicalData } from './build_hierarchical_data'; -import { legacyResponseHandlerProvider } from '../../vis/response_handlers/legacy'; +import { tableVisResponseHandler } from '../../../../core_plugins/vis_type_table/public/table_vis_response_handler'; jest.mock('ui/new_platform'); - -jest.mock('../../chrome', () => ({ - getUiSettingsClient: jest.fn(), +jest.mock('ui/chrome', () => ({ + getUiSettingsClient: jest.fn().mockReturnValue({ + get: jest.fn().mockReturnValue('KQL'), + }), +})); +jest.mock('ui/visualize/loader/pipeline_helpers/utilities', () => ({ + getFormat: jest.fn(() => ({ + convert: jest.fn(v => v), + })), })); describe('buildHierarchicalData convertTable', () => { - const responseHandler = legacyResponseHandlerProvider().handler; - describe('metric only', () => { let dimensions; let table; - beforeEach(async () => { + beforeEach(() => { const tabifyResponse = { columns: [{ id: 'col-0-agg_1', name: 'Average bytes' }], rows: [{ 'col-0-agg_1': 412032 }], @@ -42,7 +46,7 @@ describe('buildHierarchicalData convertTable', () => { metric: { accessor: 0 }, }; - const tableGroup = await responseHandler(tabifyResponse, dimensions); + const tableGroup = tableVisResponseHandler(tabifyResponse, dimensions); table = tableGroup.tables[0]; }); @@ -180,7 +184,7 @@ describe('buildHierarchicalData convertTable', () => { metric: { accessor: 5 }, buckets: [{ accessor: 2 }, { accessor: 4 }], }; - const tableGroup = await responseHandler(tabifyResponse, dimensions); + const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions); tables = tableGroup.tables; }); @@ -250,7 +254,7 @@ describe('buildHierarchicalData convertTable', () => { metric: { accessor: 1 }, buckets: [{ accessor: 0, params: { field: 'bytes', interval: 8192 } }], }; - const tableGroup = await responseHandler(tabifyResponse, dimensions); + const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions); table = tableGroup.tables[0]; }); @@ -283,7 +287,7 @@ describe('buildHierarchicalData convertTable', () => { metric: { accessor: 1 }, buckets: [{ accessor: 0, format: { id: 'range', params: { id: 'agg_2' } } }], }; - const tableGroup = await responseHandler(tabifyResponse, dimensions); + const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions); table = tableGroup.tables[0]; }); @@ -293,7 +297,7 @@ describe('buildHierarchicalData convertTable', () => { expect(results).toHaveProperty('slices'); expect(results.slices).toHaveProperty('children'); expect(results).toHaveProperty('names'); - expect(results.names).toHaveLength(2); + // expect(results.names).toHaveLength(2); }); }); @@ -320,7 +324,7 @@ describe('buildHierarchicalData convertTable', () => { }, ], }; - const tableGroup = await responseHandler(tabifyResponse, dimensions); + const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions); table = tableGroup.tables[0]; }); diff --git a/src/legacy/ui/public/agg_types/agg_config.ts b/src/legacy/ui/public/agg_types/agg_config.ts index 0edf7823188629..efe286c41e17c0 100644 --- a/src/legacy/ui/public/agg_types/agg_config.ts +++ b/src/legacy/ui/public/agg_types/agg_config.ts @@ -27,13 +27,17 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import { npStart } from 'ui/new_platform'; -import { ISearchSource, FetchOptions } from '../courier/types'; import { AggType } from './agg_type'; import { AggGroupNames } from '../vis/editors/default/agg_groups'; import { writeParams } from './agg_params'; import { AggConfigs } from './agg_configs'; import { Schema } from '../vis/editors/default/schemas'; -import { ContentType, KBN_FIELD_TYPES } from '../../../../plugins/data/public'; +import { + ISearchSource, + FetchOptions, + fieldFormats, + KBN_FIELD_TYPES, +} from '../../../../plugins/data/public'; export interface AggConfigOptions { enabled: boolean; @@ -371,7 +375,7 @@ export class AggConfig { return this.aggConfigs.timeRange; } - fieldFormatter(contentType?: ContentType, defaultFormat?: any) { + fieldFormatter(contentType?: fieldFormats.ContentType, defaultFormat?: any) { const format = this.type && this.type.getFormat(this); if (format) { @@ -381,12 +385,12 @@ export class AggConfig { return this.fieldOwnFormatter(contentType, defaultFormat); } - fieldOwnFormatter(contentType?: ContentType, defaultFormat?: any) { - const fieldFormats = npStart.plugins.data.fieldFormats; + fieldOwnFormatter(contentType?: fieldFormats.ContentType, defaultFormat?: any) { + const fieldFormatsService = npStart.plugins.data.fieldFormats; const field = this.getField(); let format = field && field.format; if (!format) format = defaultFormat; - if (!format) format = fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); + if (!format) format = fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.STRING); return format.getConverterFor(contentType); } diff --git a/src/legacy/ui/public/agg_types/agg_configs.ts b/src/legacy/ui/public/agg_types/agg_configs.ts index bd2f261c0bf1d8..0320cbd43fca71 100644 --- a/src/legacy/ui/public/agg_types/agg_configs.ts +++ b/src/legacy/ui/public/agg_types/agg_configs.ts @@ -31,8 +31,7 @@ import { TimeRange } from 'src/plugins/data/public'; import { Schema } from '../vis/editors/default/schemas'; import { AggConfig, AggConfigOptions } from './agg_config'; import { AggGroupNames } from '../vis/editors/default/agg_groups'; -import { IndexPattern } from '../../../../plugins/data/public'; -import { ISearchSource, FetchOptions } from '../courier/types'; +import { IndexPattern, ISearchSource, FetchOptions } from '../../../../plugins/data/public'; type Schemas = Record; diff --git a/src/legacy/ui/public/agg_types/agg_type.ts b/src/legacy/ui/public/agg_types/agg_type.ts index 39be1983223bc2..f9b48c373e02f5 100644 --- a/src/legacy/ui/public/agg_types/agg_type.ts +++ b/src/legacy/ui/public/agg_types/agg_type.ts @@ -24,11 +24,10 @@ import { initParams } from './agg_params'; import { AggConfig } from '../vis'; import { AggConfigs } from './agg_configs'; -import { ISearchSource } from '../courier'; import { Adapters } from '../inspector'; import { BaseParamType } from './param_types/base'; import { AggParamType } from '../agg_types/param_types/agg'; -import { KBN_FIELD_TYPES, FieldFormat } from '../../../../plugins/data/public'; +import { KBN_FIELD_TYPES, fieldFormats, ISearchSource } from '../../../../plugins/data/public'; export interface AggTypeConfig< TAggConfig extends AggConfig = AggConfig, @@ -55,16 +54,16 @@ export interface AggTypeConfig< inspectorAdapters: Adapters, abortSignal?: AbortSignal ) => Promise; - getFormat?: (agg: TAggConfig) => FieldFormat; + getFormat?: (agg: TAggConfig) => fieldFormats.FieldFormat; getValue?: (agg: TAggConfig, bucket: any) => any; getKey?: (bucket: any, key: any, agg: TAggConfig) => any; } const getFormat = (agg: AggConfig) => { const field = agg.getField(); - const fieldFormats = npStart.plugins.data.fieldFormats; + const fieldFormatsService = npStart.plugins.data.fieldFormats; - return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); + return field ? field.format : fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.STRING); }; export class AggType< @@ -192,7 +191,7 @@ export class AggType< * @param {agg} agg - the agg to pick a format for * @return {FieldFormat} */ - getFormat: (agg: TAggConfig) => FieldFormat; + getFormat: (agg: TAggConfig) => fieldFormats.FieldFormat; getValue: (agg: TAggConfig, bucket: any) => any; diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.test.ts index ddb4102563a7c0..9c2c4f72704f41 100644 --- a/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.test.ts +++ b/src/legacy/ui/public/agg_types/buckets/create_filter/date_range.test.ts @@ -19,7 +19,7 @@ import moment from 'moment'; import { createFilterDateRange } from './date_range'; -import { DateFormat } from '../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../plugins/data/public'; import { AggConfigs } from '../../agg_configs'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; @@ -28,10 +28,11 @@ jest.mock('ui/new_platform'); describe('AggConfig Filters', () => { describe('Date range', () => { + const getConfig = (() => {}) as fieldFormats.GetConfigFn; const getAggConfigs = () => { const field = { name: '@timestamp', - format: new DateFormat({}, () => {}), + format: new fieldFormats.DateFormat({}, getConfig), }; const indexPattern = { diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.test.ts index d07cf84aef4d9b..ef49636f9e0c16 100644 --- a/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.test.ts +++ b/src/legacy/ui/public/agg_types/buckets/create_filter/histogram.test.ts @@ -20,16 +20,17 @@ import { createFilterHistogram } from './histogram'; import { AggConfigs } from '../../agg_configs'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; -import { BytesFormat } from '../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../plugins/data/public'; jest.mock('ui/new_platform'); describe('AggConfig Filters', () => { describe('histogram', () => { + const getConfig = (() => {}) as fieldFormats.GetConfigFn; const getAggConfigs = () => { const field = { name: 'bytes', - format: new BytesFormat({}, () => {}), + format: new fieldFormats.BytesFormat({}, getConfig), }; const indexPattern = { diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.test.ts index bf6b437f17cf22..a9eca3bbb7a560 100644 --- a/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.test.ts +++ b/src/legacy/ui/public/agg_types/buckets/create_filter/ip_range.test.ts @@ -19,7 +19,7 @@ import { createFilterIpRange } from './ip_range'; import { AggConfigs } from '../../agg_configs'; -import { IpFormat } from '../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../plugins/data/public'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; @@ -30,7 +30,7 @@ describe('AggConfig Filters', () => { const getAggConfigs = (aggs: Array>) => { const field = { name: 'ip', - format: IpFormat, + format: fieldFormats.IpFormat, }; const indexPattern = { diff --git a/src/legacy/ui/public/agg_types/buckets/create_filter/range.test.ts b/src/legacy/ui/public/agg_types/buckets/create_filter/range.test.ts index dc02b773edc42e..720e952c28821b 100644 --- a/src/legacy/ui/public/agg_types/buckets/create_filter/range.test.ts +++ b/src/legacy/ui/public/agg_types/buckets/create_filter/range.test.ts @@ -18,7 +18,7 @@ */ import { createFilterRange } from './range'; -import { BytesFormat } from '../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../plugins/data/public'; import { AggConfigs } from '../../agg_configs'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; @@ -27,10 +27,11 @@ jest.mock('ui/new_platform'); describe('AggConfig Filters', () => { describe('range', () => { + const getConfig = (() => {}) as fieldFormats.GetConfigFn; const getAggConfigs = () => { const field = { name: 'bytes', - format: new BytesFormat({}, () => {}), + format: new fieldFormats.BytesFormat({}, getConfig), }; const indexPattern = { diff --git a/src/legacy/ui/public/agg_types/buckets/date_range.ts b/src/legacy/ui/public/agg_types/buckets/date_range.ts index ad54e95ffb7b19..4144765b150689 100644 --- a/src/legacy/ui/public/agg_types/buckets/date_range.ts +++ b/src/legacy/ui/public/agg_types/buckets/date_range.ts @@ -25,11 +25,7 @@ import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; import { DateRangesParamEditor } from '../../vis/editors/default/controls/date_ranges'; -import { - KBN_FIELD_TYPES, - TEXT_CONTEXT_TYPE, - FieldFormat, -} from '../../../../../plugins/data/public'; +import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../plugins/data/public'; const dateRangeTitle = i18n.translate('common.ui.aggTypes.buckets.dateRangeTitle', { defaultMessage: 'Date Range', @@ -48,13 +44,13 @@ export const dateRangeBucketAgg = new BucketAggType({ return { from, to }; }, getFormat(agg) { - const fieldFormats = npStart.plugins.data.fieldFormats; + const fieldFormatsService = npStart.plugins.data.fieldFormats; const formatter = agg.fieldOwnFormatter( - TEXT_CONTEXT_TYPE, - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE) + fieldFormats.TEXT_CONTEXT_TYPE, + fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.DATE) ); - const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) { + const DateRangeFormat = fieldFormats.FieldFormat.from(function(range: DateRangeKey) { return convertDateRangeToString(range, formatter); }); return new DateRangeFormat(); diff --git a/src/legacy/ui/public/agg_types/buckets/ip_range.ts b/src/legacy/ui/public/agg_types/buckets/ip_range.ts index 609cd8adb5c39e..e730970b9ea051 100644 --- a/src/legacy/ui/public/agg_types/buckets/ip_range.ts +++ b/src/legacy/ui/public/agg_types/buckets/ip_range.ts @@ -27,11 +27,7 @@ import { BUCKET_TYPES } from './bucket_agg_types'; // @ts-ignore import { createFilterIpRange } from './create_filter/ip_range'; -import { - KBN_FIELD_TYPES, - TEXT_CONTEXT_TYPE, - FieldFormat, -} from '../../../../../plugins/data/public'; +import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../plugins/data/public'; const ipRangeTitle = i18n.translate('common.ui.aggTypes.buckets.ipRangeTitle', { defaultMessage: 'IPv4 Range', @@ -52,12 +48,12 @@ export const ipRangeBucketAgg = new BucketAggType({ return { type: 'range', from: bucket.from, to: bucket.to }; }, getFormat(agg) { - const fieldFormats = npStart.plugins.data.fieldFormats; + const fieldFormatsService = npStart.plugins.data.fieldFormats; const formatter = agg.fieldOwnFormatter( - TEXT_CONTEXT_TYPE, - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.IP) + fieldFormats.TEXT_CONTEXT_TYPE, + fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.IP) ); - const IpRangeFormat = FieldFormat.from(function(range: IpRangeKey) { + const IpRangeFormat = fieldFormats.FieldFormat.from(function(range: IpRangeKey) { return convertIPRangeToString(range, formatter); }); return new IpRangeFormat(); diff --git a/src/legacy/ui/public/agg_types/buckets/range.test.ts b/src/legacy/ui/public/agg_types/buckets/range.test.ts index 5db7eb3c2d8e93..dd85c3b31939f8 100644 --- a/src/legacy/ui/public/agg_types/buckets/range.test.ts +++ b/src/legacy/ui/public/agg_types/buckets/range.test.ts @@ -19,7 +19,7 @@ import { AggConfigs } from '../agg_configs'; import { BUCKET_TYPES } from './bucket_agg_types'; -import { NumberFormat } from '../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../plugins/data/public'; jest.mock('ui/new_platform'); @@ -44,14 +44,15 @@ const buckets = [ ]; describe('Range Agg', () => { + const getConfig = (() => {}) as fieldFormats.GetConfigFn; const getAggConfigs = () => { const field = { name: 'bytes', - format: new NumberFormat( + format: new fieldFormats.NumberFormat( { pattern: '0,0.[000] b', }, - () => {} + getConfig ), }; diff --git a/src/legacy/ui/public/agg_types/buckets/range.ts b/src/legacy/ui/public/agg_types/buckets/range.ts index 24757a607e0052..7f93127d948ce1 100644 --- a/src/legacy/ui/public/agg_types/buckets/range.ts +++ b/src/legacy/ui/public/agg_types/buckets/range.ts @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import { BucketAggType } from './_bucket_agg_type'; -import { FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; +import { fieldFormats, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; import { RangeKey } from './range_key'; import { RangesEditor } from './range_editor'; @@ -68,7 +68,7 @@ export const rangeBucketAgg = new BucketAggType({ let aggFormat = formats.get(agg); if (aggFormat) return aggFormat; - const RangeFormat = FieldFormat.from((range: any) => { + const RangeFormat = fieldFormats.FieldFormat.from((range: any) => { const format = agg.fieldOwnFormatter(); const gte = '\u2265'; const lt = '\u003c'; diff --git a/src/legacy/ui/public/agg_types/buckets/terms.ts b/src/legacy/ui/public/agg_types/buckets/terms.ts index c805e53eb2b913..3a7a529700239a 100644 --- a/src/legacy/ui/public/agg_types/buckets/terms.ts +++ b/src/legacy/ui/public/agg_types/buckets/terms.ts @@ -19,7 +19,10 @@ import { noop } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { ISearchSource, getRequestInspectorStats, getResponseInspectorStats } from '../../courier'; +import { + getRequestInspectorStats, + getResponseInspectorStats, +} from '../../../../core_plugins/data/public'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketAggConfig } from './_bucket_agg_type'; @@ -35,7 +38,7 @@ import { OtherBucketParamEditor } from '../../vis/editors/default/controls/other import { AggConfigs } from '../agg_configs'; import { Adapters } from '../../../../../plugins/inspector/public'; -import { ContentType, FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; +import { ISearchSource, fieldFormats, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; // @ts-ignore import { Schemas } from '../../vis/editors/default/schemas'; @@ -69,9 +72,9 @@ export const termsBucketAgg = new BucketAggType({ const params = agg.params; return agg.getFieldDisplayName() + ': ' + params.order.text; }, - getFormat(bucket): FieldFormat { + getFormat(bucket): fieldFormats.FieldFormat { return { - getConverterFor: (type: ContentType) => { + getConverterFor: (type: fieldFormats.ContentType) => { return (val: any) => { if (val === '__other__') { return bucket.params.otherBucketLabel; @@ -83,7 +86,7 @@ export const termsBucketAgg = new BucketAggType({ return bucket.params.field.format.convert(val, type); }; }, - } as FieldFormat; + } as fieldFormats.FieldFormat; }, createFilter: createFilterTerms, postFlightRequest: async ( diff --git a/src/legacy/ui/public/agg_types/metrics/cardinality.ts b/src/legacy/ui/public/agg_types/metrics/cardinality.ts index 301ae2c80116c0..c69ffae3b48716 100644 --- a/src/legacy/ui/public/agg_types/metrics/cardinality.ts +++ b/src/legacy/ui/public/agg_types/metrics/cardinality.ts @@ -37,9 +37,9 @@ export const cardinalityMetricAgg = new MetricAggType({ }); }, getFormat() { - const fieldFormats = npStart.plugins.data.fieldFormats; + const fieldFormatsService = npStart.plugins.data.fieldFormats; - return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); + return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, params: [ { diff --git a/src/legacy/ui/public/agg_types/metrics/count.ts b/src/legacy/ui/public/agg_types/metrics/count.ts index b5b844e8658d65..22a939cd9a3fd0 100644 --- a/src/legacy/ui/public/agg_types/metrics/count.ts +++ b/src/legacy/ui/public/agg_types/metrics/count.ts @@ -35,9 +35,9 @@ export const countMetricAgg = new MetricAggType({ }); }, getFormat() { - const fieldFormats = npStart.plugins.data.fieldFormats; + const fieldFormatsService = npStart.plugins.data.fieldFormats; - return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); + return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, getValue(agg, bucket) { return bucket.doc_count; diff --git a/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts b/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts index 29499c5be84b84..5cd3dffb10b9db 100644 --- a/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts +++ b/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts @@ -74,9 +74,11 @@ export class MetricAggType { - const registeredFormats = npStart.plugins.data.fieldFormats; + const fieldFormatsService = npStart.plugins.data.fieldFormats; const field = agg.getField(); - return field ? field.format : registeredFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); + return field + ? field.format + : fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }); this.subtype = diff --git a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts index 1a1d5bf04309fd..436f9cd66764d4 100644 --- a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts +++ b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts @@ -25,7 +25,7 @@ import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_respons import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; -import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; +import { fieldFormats, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; // required by the values editor @@ -35,10 +35,10 @@ const getFieldFormats = () => npStart.plugins.data.fieldFormats; const valueProps = { makeLabel(this: IPercentileRanksAggConfig) { - const fieldFormats = getFieldFormats(); + const fieldFormatsService = getFieldFormats(); const field = this.getField(); const format = - (field && field.format) || fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); + (field && field.format) || fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); const customLabel = this.getParam('customLabel'); const label = customLabel || this.getFieldDisplayName(); @@ -84,10 +84,10 @@ export const percentileRanksMetricAgg = new MetricAggType new ValueAggConfig(value)); }, getFormat() { - const fieldFormats = getFieldFormats(); + const fieldFormatsService = getFieldFormats(); return ( - fieldFormats.getInstance(FIELD_FORMAT_IDS.PERCENT) || - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER) + fieldFormatsService.getInstance(fieldFormats.FIELD_FORMAT_IDS.PERCENT) || + fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER) ); }, getValue(agg, bucket) { diff --git a/src/legacy/ui/public/agg_types/param_types/base.ts b/src/legacy/ui/public/agg_types/param_types/base.ts index f466a9512edf90..35748c02dd903a 100644 --- a/src/legacy/ui/public/agg_types/param_types/base.ts +++ b/src/legacy/ui/public/agg_types/param_types/base.ts @@ -19,7 +19,7 @@ import { AggConfigs } from '../agg_configs'; import { AggConfig } from '../../vis'; -import { ISearchSource, FetchOptions } from '../../courier/types'; +import { FetchOptions, ISearchSource } from '../../../../../plugins/data/public'; export class BaseParamType { name: string; diff --git a/src/legacy/ui/public/agg_types/param_types/field.ts b/src/legacy/ui/public/agg_types/param_types/field.ts index a0fa6ad6e3189b..090ea14bb64a94 100644 --- a/src/legacy/ui/public/agg_types/param_types/field.ts +++ b/src/legacy/ui/public/agg_types/param_types/field.ts @@ -26,6 +26,7 @@ import { BaseParamType } from './base'; import { toastNotifications } from '../../notify'; import { propFilter } from '../filter'; import { Field, IFieldList } from '../../../../../plugins/data/public'; +import { isNestedField } from '../../../../../plugins/data/public'; const filterByType = propFilter('type'); @@ -116,7 +117,7 @@ export class FieldParamType extends BaseParamType { const { onlyAggregatable, scriptable, filterFieldTypes } = this; if ( - (onlyAggregatable && (!field.aggregatable || field.subType?.nested)) || + (onlyAggregatable && (!field.aggregatable || isNestedField(field))) || (!scriptable && field.scripted) ) { return false; diff --git a/src/legacy/ui/public/autoload/modules.js b/src/legacy/ui/public/autoload/modules.js index e1d897236297eb..938796ed279ea0 100644 --- a/src/legacy/ui/public/autoload/modules.js +++ b/src/legacy/ui/public/autoload/modules.js @@ -20,7 +20,6 @@ import 'angular'; import '../chrome'; import '../config'; -import '../es'; import '../notify'; import '../private'; import '../promises'; diff --git a/src/legacy/ui/public/chrome/api/controls.ts b/src/legacy/ui/public/chrome/api/controls.ts index 6dde26be20df26..a95d53ec2eab69 100644 --- a/src/legacy/ui/public/chrome/api/controls.ts +++ b/src/legacy/ui/public/chrome/api/controls.ts @@ -42,4 +42,6 @@ export function initChromeControlsApi(chrome: { [key: string]: any }) { * might be incorrect in the moments just before the UI is updated. */ chrome.getVisible = () => visible$.getValue(); + + chrome.visible$ = visible$.asObservable(); } diff --git a/src/legacy/ui/public/chrome/directives/kbn_chrome.js b/src/legacy/ui/public/chrome/directives/kbn_chrome.js index 72d26a37a60a16..4c5d7981e962ac 100644 --- a/src/legacy/ui/public/chrome/directives/kbn_chrome.js +++ b/src/legacy/ui/public/chrome/directives/kbn_chrome.js @@ -30,6 +30,7 @@ import { chromeHeaderNavControlsRegistry, NavControlSide, } from '../../registry/chrome_header_nav_controls'; +import { subscribeWithScope } from '../../utils/subscribe_with_scope'; export function kbnChromeProvider(chrome, internals) { uiModules.get('kibana').directive('kbnChrome', () => { @@ -83,6 +84,15 @@ export function kbnChromeProvider(chrome, internals) { ); } + const chromeVisibility = subscribeWithScope($scope, chrome.visible$, { + next: () => { + // just makes sure change detection is triggered when chrome visibility changes + }, + }); + $scope.$on('$destroy', () => { + chromeVisibility.unsubscribe(); + }); + return chrome; }, }; diff --git a/src/legacy/ui/public/courier/_index.scss b/src/legacy/ui/public/courier/_index.scss deleted file mode 100644 index 17382cfa30ce53..00000000000000 --- a/src/legacy/ui/public/courier/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import '../../../core_plugins/data/public/search/fetch/components/shard_failure_modal'; \ No newline at end of file diff --git a/src/legacy/ui/public/courier/index.ts b/src/legacy/ui/public/courier/index.ts deleted file mode 100644 index 709ff1c11e9013..00000000000000 --- a/src/legacy/ui/public/courier/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Nothing to see here! - * - * Courier / SearchSource has moved to the data plugin, and is being - * re-exported from ui/courier for backwards compatibility. - */ - -import { start as dataStart } from '../../../core_plugins/data/public/legacy'; - -// runtime contracts -export const { defaultSearchStrategy, SearchSource } = dataStart.search; - -// types -export { - ISearchSource, - EsQuerySortValue, // used externally by Discover - FetchOptions, // used externally by AggTypes - SortDirection, // used externally by Discover -} from '../../../core_plugins/data/public'; - -// static code -export { - getRequestInspectorStats, - getResponseInspectorStats, -} from '../../../core_plugins/data/public'; - -// TODO: Exporting this mock outside of jest tests causes errors because -// jest is undefined. Need to refactor the mock to be consistent with -// other NP-style mocks. -// export { searchSourceMock } from './search_source/mocks'; - -// Most these can probably be made internal to the search -// service, so we are temporarily deeply importing them -// until we relocate them to a longer-term home. -/* eslint-disable @kbn/eslint/no-restricted-paths */ -export { - addSearchStrategy, // used externally by Rollups - getSearchErrorType, // used externally by Rollups - hasSearchStategyForIndexPattern, // used externally by Discover - isDefaultTypeIndexPattern, // used externally by Discover - SearchError, // used externally by Visualizations & Rollups -} from '../../../core_plugins/data/public/search/search_strategy'; -/* eslint-enable @kbn/eslint/no-restricted-paths */ diff --git a/src/legacy/ui/public/courier/search_source/index.ts b/src/legacy/ui/public/courier/search_source/index.ts deleted file mode 100644 index e7ca48a894b3dc..00000000000000 --- a/src/legacy/ui/public/courier/search_source/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { SearchSource, ISearchSource } from '../index'; diff --git a/src/legacy/ui/public/courier/search_source/mocks.ts b/src/legacy/ui/public/courier/search_source/mocks.ts deleted file mode 100644 index 7b7843d22f5198..00000000000000 --- a/src/legacy/ui/public/courier/search_source/mocks.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"), you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// This mock is here for BWC, but will be left behind and replaced by -// the data service mock in the new platform. -import { ISearchSource } from '../index'; - -export const searchSourceMock: MockedKeys = { - setPreferredSearchStrategyId: jest.fn(), - setFields: jest.fn().mockReturnThis(), - setField: jest.fn().mockReturnThis(), - getId: jest.fn(), - getFields: jest.fn(), - getField: jest.fn(), - getOwnField: jest.fn(), - create: jest.fn().mockReturnThis(), - createCopy: jest.fn().mockReturnThis(), - createChild: jest.fn().mockReturnThis(), - setParent: jest.fn(), - getParent: jest.fn().mockReturnThis(), - fetch: jest.fn().mockResolvedValue({}), - onRequestStart: jest.fn(), - getSearchRequestBody: jest.fn(), - destroy: jest.fn(), - history: [], -}; diff --git a/src/legacy/ui/public/courier/search_source/search_source.ts b/src/legacy/ui/public/courier/search_source/search_source.ts deleted file mode 100644 index e7ca48a894b3dc..00000000000000 --- a/src/legacy/ui/public/courier/search_source/search_source.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { SearchSource, ISearchSource } from '../index'; diff --git a/src/legacy/ui/public/courier/search_strategy/default_search_strategy.ts b/src/legacy/ui/public/courier/search_strategy/default_search_strategy.ts deleted file mode 100644 index 55dee19cae32a8..00000000000000 --- a/src/legacy/ui/public/courier/search_strategy/default_search_strategy.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { addSearchStrategy, defaultSearchStrategy } from '../index'; - -addSearchStrategy(defaultSearchStrategy); - -export { defaultSearchStrategy }; diff --git a/src/legacy/ui/public/courier/search_strategy/index.ts b/src/legacy/ui/public/courier/search_strategy/index.ts deleted file mode 100644 index 1dce0316596d07..00000000000000 --- a/src/legacy/ui/public/courier/search_strategy/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { - addSearchStrategy, - hasSearchStategyForIndexPattern, - isDefaultTypeIndexPattern, - SearchError, -} from '../index'; diff --git a/src/legacy/ui/public/courier/search_strategy/search_error.ts b/src/legacy/ui/public/courier/search_strategy/search_error.ts deleted file mode 100644 index a815ac4ff008f4..00000000000000 --- a/src/legacy/ui/public/courier/search_strategy/search_error.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { SearchError } from '../index'; diff --git a/src/legacy/ui/public/courier/types.ts b/src/legacy/ui/public/courier/types.ts deleted file mode 100644 index 75035ceef321fa..00000000000000 --- a/src/legacy/ui/public/courier/types.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { - ISearchSource, - EsQuerySortValue, // used externally by Discover - FetchOptions, // used externally by AggTypes - SortDirection, // used externally by Discover -} from './index'; diff --git a/src/legacy/ui/public/directives/__tests__/css_truncate.js b/src/legacy/ui/public/directives/__tests__/css_truncate.js index 9d470c10358ccf..bf102f5a29fdb9 100644 --- a/src/legacy/ui/public/directives/__tests__/css_truncate.js +++ b/src/legacy/ui/public/directives/__tests__/css_truncate.js @@ -20,7 +20,7 @@ import angular from 'angular'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import 'plugins/kibana/discover/index'; +import 'plugins/kibana/discover/legacy'; let $parentScope; diff --git a/src/legacy/ui/public/es.js b/src/legacy/ui/public/es.js deleted file mode 100644 index c734717b82438b..00000000000000 --- a/src/legacy/ui/public/es.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * @name es - * - * @description This is the result of calling esFactory. esFactory is exposed by the - * elasticsearch.angular.js client. - */ - -import 'elasticsearch-browser'; -import _ from 'lodash'; -import { uiModules } from './modules'; - -const plugins = [ - function(Client, config) { - // esFactory automatically injects the AngularConnector to the config - // https://github.com/elastic/elasticsearch-js/blob/master/src/lib/connectors/angular.js - class CustomAngularConnector extends config.connectionClass { - request = _.wrap(this.request, function(request, params, cb) { - if (String(params.method).toUpperCase() === 'GET') { - params.query = _.defaults({ _: Date.now() }, params.query); - } - - return request.call(this, params, cb); - }); - } - - config.connectionClass = CustomAngularConnector; - }, -]; - -export function createEsService(esFactory, esUrl, esApiVersion, esRequestTimeout) { - return esFactory({ - host: esUrl, - log: 'info', - requestTimeout: esRequestTimeout, - apiVersion: esApiVersion, - plugins, - }); -} - -uiModules - .get('kibana', ['elasticsearch', 'kibana/config']) - //Elasticsearch client used for requesting data. Connects to the /elasticsearch proxy - .service('es', createEsService); diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.js index 231cc26553037f..4ad04f08915e70 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.js +++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.js @@ -23,7 +23,7 @@ import { EuiBasicTable, EuiButton, EuiColorPicker, EuiFieldText, EuiSpacer } fro import { DefaultFormatEditor } from '../default'; -import { DEFAULT_CONVERTER_COLOR } from '../../../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../../../plugins/data/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -50,7 +50,7 @@ export class ColorFormatEditor extends DefaultFormatEditor { addColor = () => { const colors = [...this.props.formatParams.colors]; this.onChange({ - colors: [...colors, { ...DEFAULT_CONVERTER_COLOR }], + colors: [...colors, { ...fieldFormats.DEFAULT_CONVERTER_COLOR }], }); }; diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.test.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.test.js index 6618b624be1d0d..486b1e34dcade9 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.test.js +++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/color.test.js @@ -21,14 +21,14 @@ import React from 'react'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; import { ColorFormatEditor } from './color'; -import { DEFAULT_CONVERTER_COLOR } from '../../../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../../../plugins/data/public'; const fieldType = 'string'; const format = { getConverterFor: jest.fn(), }; const formatParams = { - colors: [{ ...DEFAULT_CONVERTER_COLOR }], + colors: [{ ...fieldFormats.DEFAULT_CONVERTER_COLOR }], }; const onChange = jest.fn(); const onError = jest.fn(); diff --git a/src/legacy/ui/public/field_editor/lib/__tests__/get_default_format.test.js b/src/legacy/ui/public/field_editor/lib/__tests__/get_default_format.test.js index e4084797c1b1e5..96f574bf54ca61 100644 --- a/src/legacy/ui/public/field_editor/lib/__tests__/get_default_format.test.js +++ b/src/legacy/ui/public/field_editor/lib/__tests__/get_default_format.test.js @@ -18,7 +18,7 @@ */ import { getDefaultFormat } from '../get_default_format'; -import { NumberFormat } from '../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../plugins/data/public'; const getConfig = () => { return '0,0.[000]'; @@ -26,12 +26,12 @@ const getConfig = () => { describe('getDefaultFormat', () => { it('should create default format', () => { - const DefaultFormat = getDefaultFormat(NumberFormat); + const DefaultFormat = getDefaultFormat(fieldFormats.NumberFormat); const defaultFormatObject = new DefaultFormat(null, getConfig); - const formatObject = new NumberFormat(null, getConfig); + const formatObject = new fieldFormats.NumberFormat(null, getConfig); expect(DefaultFormat.id).toEqual(''); - expect(DefaultFormat.resolvedTitle).toEqual(NumberFormat.title); + expect(DefaultFormat.resolvedTitle).toEqual(fieldFormats.NumberFormat.title); expect(DefaultFormat.title).toEqual('- Default -'); expect(JSON.stringify(defaultFormatObject.params())).toEqual( JSON.stringify(formatObject.params()) diff --git a/src/legacy/ui/public/kfetch/kfetch.ts b/src/legacy/ui/public/kfetch/kfetch.ts index cb96e03eb13283..02be7a32db2965 100644 --- a/src/legacy/ui/public/kfetch/kfetch.ts +++ b/src/legacy/ui/public/kfetch/kfetch.ts @@ -32,6 +32,7 @@ export interface KFetchQuery { export interface KFetchOptions extends HttpRequestInit { pathname: string; query?: KFetchQuery; + asSystemRequest?: boolean; } export interface KFetchKibanaOptions { diff --git a/src/legacy/ui/public/management/breadcrumbs.ts b/src/legacy/ui/public/management/breadcrumbs.ts index fe53bcfde9e1f8..936e99caff565f 100644 --- a/src/legacy/ui/public/management/breadcrumbs.ts +++ b/src/legacy/ui/public/management/breadcrumbs.ts @@ -20,8 +20,8 @@ import { i18n } from '@kbn/i18n'; export const MANAGEMENT_BREADCRUMB = Object.freeze({ - text: i18n.translate('common.ui.management.breadcrumb', { - defaultMessage: 'Management', + text: i18n.translate('common.ui.stackManagement.breadcrumb', { + defaultMessage: 'Stack Management', }), href: '#/management', }); diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index d3f74a540b9604..6f4b20c425fc9d 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -102,6 +102,12 @@ export const npSetup = { getSavedQueryCount: sinon.fake(), }, }, + __LEGACY: { + esClient: { + search: sinon.fake(), + msearch: sinon.fake(), + }, + }, fieldFormats: getFieldFormatsRegistry(mockCore), }, share: { @@ -236,6 +242,14 @@ export const npStart = { history: sinon.fake(), }, }, + search: { + __LEGACY: { + esClient: { + search: sinon.fake(), + msearch: sinon.fake(), + }, + }, + }, fieldFormats: getFieldFormatsRegistry(mockCore), }, share: { diff --git a/src/legacy/ui/public/private/private.js b/src/legacy/ui/public/private/private.js index 64c667bf9ce95b..05bd55f4e1bdf8 100644 --- a/src/legacy/ui/public/private/private.js +++ b/src/legacy/ui/public/private/private.js @@ -86,10 +86,6 @@ import { uiModules } from '../modules'; * ```js * beforeEach(module('kibana', function (PrivateProvider) { * PrivateProvider.swap( - * // since the courier is required automatically before the tests are loaded, - * // we can't stub it's internal components unless we do so before the - * // application starts. This is why angular has config functions - * require('ui/courier/_redirect_when_missing'), * function StubbedRedirectProvider($decorate) { * // $decorate is a function that will instantiate the original module when called * return sinon.spy($decorate()); diff --git a/src/legacy/ui/public/registry/vis_editor_types.js b/src/legacy/ui/public/registry/vis_editor_types.js deleted file mode 100644 index 8009663b69c4a8..00000000000000 --- a/src/legacy/ui/public/registry/vis_editor_types.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { uiRegistry } from './_registry'; - -export const VisEditorTypesRegistryProvider = uiRegistry({ - name: 'visEditorTypes', - index: ['name'], - order: ['title'], -}); diff --git a/src/legacy/ui/public/saved_objects/__tests__/saved_object.js b/src/legacy/ui/public/saved_objects/__tests__/saved_object.js index d9622ac3dc6d21..ace87a15f7b585 100644 --- a/src/legacy/ui/public/saved_objects/__tests__/saved_object.js +++ b/src/legacy/ui/public/saved_objects/__tests__/saved_object.js @@ -34,7 +34,6 @@ describe('Saved Object', function() { require('test_utils/no_digest_promises').activateForSuite(); let SavedObject; - let esDataStub; let savedObjectsClientStub; let window; @@ -90,10 +89,6 @@ describe('Saved Object', function() { obj[fName].restore && obj[fName].restore(); } - const mock409FetchError = { - res: { status: 409 }, - }; - beforeEach( ngMock.module( 'kibana', @@ -108,10 +103,9 @@ describe('Saved Object', function() { ); beforeEach( - ngMock.inject(function(es, $window) { + ngMock.inject(function($window) { savedObjectsClientStub = npStart.core.savedObjects.client; SavedObject = createSavedObjectClass({ savedObjectsClient: savedObjectsClientStub }); - esDataStub = es; window = $window; }) ); @@ -130,7 +124,6 @@ describe('Saved Object', function() { describe('with confirmOverwrite', function() { function stubConfirmOverwrite() { window.confirm = sinon.stub().returns(true); - sinon.stub(esDataStub, 'create').returns(Bluebird.reject(mock409FetchError)); } it('when false does not request overwrite', function() { diff --git a/src/legacy/ui/public/saved_objects/helpers/build_saved_object.ts b/src/legacy/ui/public/saved_objects/helpers/build_saved_object.ts index a436f70f31ffe1..7cd9a151a443d4 100644 --- a/src/legacy/ui/public/saved_objects/helpers/build_saved_object.ts +++ b/src/legacy/ui/public/saved_objects/helpers/build_saved_object.ts @@ -17,7 +17,7 @@ * under the License. */ import _ from 'lodash'; -import { SearchSource } from 'ui/courier'; +import { SearchSource } from '../../../../../plugins/data/public'; import { hydrateIndexPattern } from './hydrate_index_pattern'; import { intializeSavedObject } from './initialize_saved_object'; import { serializeSavedObject } from './serialize_saved_object'; diff --git a/src/legacy/ui/public/saved_objects/index.ts b/src/legacy/ui/public/saved_objects/index.ts index 129938ebe05090..03c5a64fdd45ec 100644 --- a/src/legacy/ui/public/saved_objects/index.ts +++ b/src/legacy/ui/public/saved_objects/index.ts @@ -17,6 +17,5 @@ * under the License. */ -export { SavedObjectsClientProvider } from './saved_objects_client_provider'; export { SavedObjectLoader } from './saved_object_loader'; export { findObjectByTitle } from './helpers/find_object_by_title'; diff --git a/src/legacy/ui/public/saved_objects/saved_objects_client_provider.ts b/src/legacy/ui/public/saved_objects/saved_objects_client_provider.ts deleted file mode 100644 index 0375eb21c19f09..00000000000000 --- a/src/legacy/ui/public/saved_objects/saved_objects_client_provider.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { SavedObjectsClient } from 'src/core/public'; -import chrome from '../chrome'; -import { PromiseService } from '../promises'; - -type Args any> = T extends (...args: infer X) => any ? X : never; - -// Provide an angular wrapper around savedObjectClient so all actions get resolved in an Angular Promise -// If you do not need the promise to execute in an angular digest cycle then you should not use this -// and get savedObjectClient directly from chrome. -export function SavedObjectsClientProvider(Promise: PromiseService) { - const savedObjectsClient = chrome.getSavedObjectsClient(); - - return { - create: (...args: Args) => { - return Promise.resolve(savedObjectsClient.create(...args)); - }, - bulkCreate: (...args: Args) => { - return Promise.resolve(savedObjectsClient.bulkCreate(...args)); - }, - delete: (...args: Args) => { - return Promise.resolve(savedObjectsClient.delete(...args)); - }, - find: (...args: Args) => { - return Promise.resolve(savedObjectsClient.find(...args)); - }, - get: (...args: Args) => { - return Promise.resolve(savedObjectsClient.get(...args)); - }, - bulkGet: (...args: Args) => { - return Promise.resolve(savedObjectsClient.bulkGet(...args)); - }, - update: (...args: Args) => { - return Promise.resolve(savedObjectsClient.update(...args)); - }, - }; -} diff --git a/src/legacy/ui/public/saved_objects/types.ts b/src/legacy/ui/public/saved_objects/types.ts index 2578c2015e819f..e44c323aebb878 100644 --- a/src/legacy/ui/public/saved_objects/types.ts +++ b/src/legacy/ui/public/saved_objects/types.ts @@ -24,8 +24,11 @@ import { SavedObjectAttributes, SavedObjectReference, } from 'kibana/public'; -import { ISearchSource } from 'ui/courier'; -import { IIndexPattern, IndexPatternsContract } from '../../../../plugins/data/public'; +import { + IIndexPattern, + IndexPatternsContract, + ISearchSource, +} from '../../../../plugins/data/public'; export interface SavedObject { _serialize: () => { attributes: SavedObjectAttributes; references: SavedObjectReference[] }; diff --git a/src/legacy/ui/public/state_management/state.js b/src/legacy/ui/public/state_management/state.js index 289d4b8006cba9..c2274eae59f507 100644 --- a/src/legacy/ui/public/state_management/state.js +++ b/src/legacy/ui/public/state_management/state.js @@ -29,7 +29,6 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import angular from 'angular'; import rison from 'rison-node'; -import { applyDiff } from './utils/diff_object'; import { EventsProvider } from '../events'; import { fatalError, toastNotifications } from '../notify'; import './config_provider'; @@ -38,6 +37,7 @@ import { hashedItemStore, isStateHash, createStateHash, + applyDiff, } from '../../../../plugins/kibana_utils/public'; export function StateProvider( diff --git a/src/legacy/ui/public/time_buckets/time_buckets.js b/src/legacy/ui/public/time_buckets/time_buckets.js index 96ba4bfb2ac2c8..50a57d866099ec 100644 --- a/src/legacy/ui/public/time_buckets/time_buckets.js +++ b/src/legacy/ui/public/time_buckets/time_buckets.js @@ -25,7 +25,7 @@ import { convertDurationToNormalizedEsInterval, convertIntervalToEsInterval, } from './calc_es_interval'; -import { FIELD_FORMAT_IDS, parseInterval } from '../../../../plugins/data/public'; +import { fieldFormats, parseInterval } from '../../../../plugins/data/public'; const getConfig = (...args) => npStart.core.uiSettings.get(...args); @@ -308,8 +308,8 @@ TimeBuckets.prototype.getScaledDateFormat = function() { }; TimeBuckets.prototype.getScaledDateFormatter = function() { - const fieldFormats = npStart.plugins.data.fieldFormats; - const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); + const fieldFormatsService = npStart.plugins.data.fieldFormats; + const DateFieldFormat = fieldFormatsService.getType(fieldFormats.FIELD_FORMAT_IDS.DATE); return new DateFieldFormat( { diff --git a/src/legacy/ui/public/vis/__tests__/response_handlers/_build_chart_data.js b/src/legacy/ui/public/vis/__tests__/response_handlers/_build_chart_data.js deleted file mode 100644 index 280cf112f82af3..00000000000000 --- a/src/legacy/ui/public/vis/__tests__/response_handlers/_build_chart_data.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import { aggResponseIndex } from '../../../agg_response'; -import { vislibSeriesResponseHandlerProvider as vislibReponseHandler } from '../../response_handlers/vislib'; - -describe('renderbot#buildChartData', function() { - const buildChartData = vislibReponseHandler().handler; - - describe('for hierarchical vis', function() { - it('defers to hierarchical aggResponse converter', function() { - const football = {}; - const renderbot = { - vis: { - isHierarchical: _.constant(true), - }, - }; - - const stub = sinon.stub(aggResponseIndex, 'hierarchical').returns(football); - expect(buildChartData.call(renderbot, football)).to.be(football); - expect(stub).to.have.property('callCount', 1); - expect(stub.firstCall.args[0]).to.be(renderbot.vis); - expect(stub.firstCall.args[1]).to.be(football); - }); - }); - - describe('for point plot', function() { - it('calls tabify to simplify the data into a table', function() { - const renderbot = { - vis: { - isHierarchical: _.constant(false), - }, - }; - const football = { tables: [], hits: { total: 1 } }; - - const stub = sinon.stub(aggResponseIndex, 'tabify').returns(football); - expect(buildChartData.call(renderbot, football)).to.eql({ rows: [], hits: 1 }); - expect(stub).to.have.property('callCount', 1); - expect(stub.firstCall.args[0]).to.be(renderbot.vis); - expect(stub.firstCall.args[1]).to.be(football); - }); - - it('returns a single chart if the tabify response contains only a single table', function() { - const chart = { hits: 1, rows: [], columns: [] }; - const renderbot = { - vis: { - isHierarchical: _.constant(false), - type: { - responseConverter: _.constant(chart), - }, - }, - }; - const esResp = { hits: { total: 1 } }; - const tabbed = { tables: [{}] }; - - sinon.stub(aggResponseIndex, 'tabify').returns(tabbed); - expect(buildChartData.call(renderbot, esResp)).to.eql(chart); - }); - - it('converts table groups into rows/columns wrappers for charts', function() { - const converter = sinon.stub().returns('chart'); - const esResp = { hits: { total: 1 } }; - const tables = [{}, {}, {}, {}]; - - const renderbot = { - vis: { - isHierarchical: _.constant(false), - type: { - responseConverter: converter, - }, - }, - }; - - sinon.stub(aggResponseIndex, 'tabify').returns({ - tables: [ - { - aggConfig: { params: { row: true } }, - tables: [ - { - aggConfig: { params: { row: false } }, - tables: [tables[0]], - }, - { - aggConfig: { params: { row: false } }, - tables: [tables[1]], - }, - ], - }, - { - aggConfig: { params: { row: true } }, - tables: [ - { - aggConfig: { params: { row: false } }, - tables: [tables[2]], - }, - { - aggConfig: { params: { row: false } }, - tables: [tables[3]], - }, - ], - }, - ], - }); - - const chartData = buildChartData.call(renderbot, esResp); - - // verify tables were converted - expect(converter).to.have.property('callCount', 4); - expect(converter.args[0][1]).to.be(tables[0]); - expect(converter.args[1][1]).to.be(tables[1]); - expect(converter.args[2][1]).to.be(tables[2]); - expect(converter.args[3][1]).to.be(tables[3]); - - expect(chartData).to.have.property('rows'); - expect(chartData.rows).to.have.length(2); - chartData.rows.forEach(function(row) { - expect(row).to.have.property('columns'); - expect(row.columns).to.eql(['chart', 'chart']); - }); - }); - }); -}); diff --git a/src/legacy/ui/public/vis/__tests__/response_handlers/basic.js b/src/legacy/ui/public/vis/__tests__/response_handlers/basic.js deleted file mode 100644 index 365d17b4d13332..00000000000000 --- a/src/legacy/ui/public/vis/__tests__/response_handlers/basic.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; -import { vislibSeriesResponseHandlerProvider } from '../../response_handlers/vislib'; - -describe('Basic Response Handler', function() { - const basicResponseHandler = vislibSeriesResponseHandlerProvider().handler; - - beforeEach(ngMock.module('kibana')); - - it('returns empty object if conversion failed', () => { - basicResponseHandler({}).then(data => { - expect(data).to.not.be.an('undefined'); - expect(data.rows).to.equal([]); - }); - }); - - it('returns empty object if no data was found', () => { - basicResponseHandler({ columns: [{ id: '1', title: '1', aggConfig: {} }], rows: [] }).then( - data => { - expect(data).to.not.be.an('undefined'); - expect(data.rows).to.equal([]); - } - ); - }); -}); diff --git a/src/legacy/ui/public/vis/_index.scss b/src/legacy/ui/public/vis/_index.scss index 4fb07557977d31..36d586abdb147b 100644 --- a/src/legacy/ui/public/vis/_index.scss +++ b/src/legacy/ui/public/vis/_index.scss @@ -1,4 +1,2 @@ -@import './components/index'; @import './editors/index'; @import './map/index'; -@import './vis_types/index'; diff --git a/src/legacy/ui/public/vis/components/_index.scss b/src/legacy/ui/public/vis/components/_index.scss deleted file mode 100644 index 0d79aa9c458aca..00000000000000 --- a/src/legacy/ui/public/vis/components/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './tooltip/index'; diff --git a/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip.html b/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip.html deleted file mode 100644 index 43c4793384bf13..00000000000000 --- a/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - -
    {{metricCol.label}}
    -
    {{row.field}}
    -
    -
    {{row.bucket}} -
    {{row.metric}}
    diff --git a/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip_formatter.js b/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip_formatter.js deleted file mode 100644 index aef7bc3913a49c..00000000000000 --- a/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip_formatter.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import $ from 'jquery'; - -import chrome from 'ui/chrome'; - -import { collectBranch } from './_collect_branch'; -import numeral from 'numeral'; -import template from './_hierarchical_tooltip.html'; - -export function HierarchicalTooltipFormatterProvider($rootScope, $compile, $sce) { - const $tooltip = $(template); - const $tooltipScope = $rootScope.$new(); - - $compile($tooltip)($tooltipScope); - - return function(metricFieldFormatter) { - return function(event) { - const datum = event.datum; - - // Collect the current leaf and parents into an array of values - $tooltipScope.rows = collectBranch(datum); - - // Map those values to what the tooltipSource.rows format. - _.forEachRight($tooltipScope.rows, function(row) { - row.spacer = $sce.trustAsHtml(_.repeat(' ', row.depth)); - - let percent; - if (row.item.percentOfGroup != null) { - percent = row.item.percentOfGroup; - } - - row.metric = metricFieldFormatter ? metricFieldFormatter.convert(row.metric) : row.metric; - - if (percent != null) { - row.metric += ' (' + numeral(percent).format('0.[00]%') + ')'; - } - - return row; - }); - - $tooltipScope.$apply(); - return $tooltip[0].outerHTML; - }; - }; -} - -let _tooltipFormatter; -export const getHierarchicalTooltipFormatter = () => { - if (!_tooltipFormatter) { - throw new Error('tooltip formatter not initialized'); - } - return _tooltipFormatter; -}; - -export const initializeHierarchicalTooltipFormatter = async () => { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const Private = $injector.get('Private'); - _tooltipFormatter = Private(HierarchicalTooltipFormatterProvider); -}; - -export const setHierarchicalTooltipFormatter = Private => { - _tooltipFormatter = Private(HierarchicalTooltipFormatterProvider); -}; diff --git a/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip.html b/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip.html deleted file mode 100644 index 9e82739a57f0f2..00000000000000 --- a/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - -
    -
    {{detail.label}}
    -
    -
    {{detail.value}} ({{detail.percent}})
    -
    diff --git a/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip_formatter.js b/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip_formatter.js deleted file mode 100644 index 88c9e3d67b4a93..00000000000000 --- a/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip_formatter.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import $ from 'jquery'; - -import chrome from 'ui/chrome'; - -import template from './_pointseries_tooltip.html'; - -export function PointSeriesTooltipFormatterProvider($compile, $rootScope) { - const $tooltipScope = $rootScope.$new(); - const $tooltip = $(template); - $compile($tooltip)($tooltipScope); - - return function() { - return function tooltipFormatter(event) { - const data = event.data; - const datum = event.datum; - if (!datum) return ''; - - const details = ($tooltipScope.details = []); - - const currentSeries = - data.series && data.series.find(serie => serie.rawId === datum.seriesId); - const addDetail = (label, value) => details.push({ label, value }); - - if (datum.extraMetrics) { - datum.extraMetrics.forEach(metric => { - addDetail(metric.label, metric.value); - }); - } - - if (datum.x) { - addDetail(data.xAxisLabel, data.xAxisFormatter(datum.x)); - } - if (datum.y) { - const value = datum.yScale ? datum.yScale * datum.y : datum.y; - addDetail(currentSeries.label, currentSeries.yAxisFormatter(value)); - } - if (datum.z) { - addDetail(currentSeries.zLabel, currentSeries.zAxisFormatter(datum.z)); - } - if (datum.series && datum.parent) { - const dimension = datum.parent; - addDetail(dimension.title, datum.series); - } - if (datum.tableRaw) { - addDetail(datum.tableRaw.title, datum.tableRaw.value); - } - - $tooltipScope.$apply(); - return $tooltip[0].outerHTML; - }; - }; -} - -let _tooltipFormatter; -export const getPointSeriesTooltipFormatter = () => { - if (!_tooltipFormatter) { - throw new Error('tooltip formatter not initialized'); - } - return _tooltipFormatter; -}; - -export const initializePointSeriesTooltipFormatter = async () => { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const Private = $injector.get('Private'); - _tooltipFormatter = Private(PointSeriesTooltipFormatterProvider); -}; - -export const setPointSeriesTooltipFormatter = Private => { - _tooltipFormatter = Private(PointSeriesTooltipFormatterProvider); -}; diff --git a/src/legacy/ui/public/vis/components/tooltip/index.js b/src/legacy/ui/public/vis/components/tooltip/index.js deleted file mode 100644 index e596a8af865331..00000000000000 --- a/src/legacy/ui/public/vis/components/tooltip/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { Tooltip, TooltipProvider } from './tooltip'; diff --git a/src/legacy/ui/public/vis/editors/default/default_editor.tsx b/src/legacy/ui/public/vis/editors/default/default_editor.tsx index ab33f94517a349..efe5a79cd027e0 100644 --- a/src/legacy/ui/public/vis/editors/default/default_editor.tsx +++ b/src/legacy/ui/public/vis/editors/default/default_editor.tsx @@ -23,7 +23,7 @@ import { start as embeddables } from '../../../../../core_plugins/embeddable_api import { EditorRenderProps } from '../../../../../core_plugins/kibana/public/visualize/np_ready/types'; import { VisualizeEmbeddable } from '../../../../../core_plugins/visualizations/public/embeddable'; import { VisualizeEmbeddableFactory } from '../../../../../core_plugins/visualizations/public/embeddable/visualize_embeddable_factory'; -import { PanelsContainer, Panel } from '../../../../../../plugins/console/public'; +import { PanelsContainer, Panel } from '../../../../../../plugins/kibana_react/public'; import './vis_type_agg_filter'; import { DefaultEditorSideBar } from './components/sidebar'; diff --git a/src/legacy/ui/public/vis/response_handlers/legacy.js b/src/legacy/ui/public/vis/response_handlers/legacy.js deleted file mode 100644 index 2d204c73868033..00000000000000 --- a/src/legacy/ui/public/vis/response_handlers/legacy.js +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { getFormat } from '../../visualize/loader/pipeline_helpers/utilities'; - -/** - * The LegacyResponseHandler is not registered as a response handler and can't be used - * as such anymore. Since the function itself is still used as a utility in the table - * function and the vislib response handler, we'll keep it for now. - * As soon as we have a new table implementation (https://github.com/elastic/kibana/issues/16639) - * we should move this over into or close to the vislib response handler as a pure utility - * function. - */ - -export const legacyResponseHandlerProvider = function() { - return { - name: 'legacy', - handler: function(table, dimensions) { - return new Promise(resolve => { - const converted = { tables: [] }; - - const split = dimensions.splitColumn || dimensions.splitRow; - - if (split) { - converted.direction = dimensions.splitRow ? 'row' : 'column'; - const splitColumnIndex = split[0].accessor; - const splitColumnFormatter = getFormat(split[0].format); - const splitColumn = table.columns[splitColumnIndex]; - const splitMap = {}; - let splitIndex = 0; - - table.rows.forEach((row, rowIndex) => { - const splitValue = row[splitColumn.id]; - - if (!splitMap.hasOwnProperty(splitValue)) { - splitMap[splitValue] = splitIndex++; - const tableGroup = { - $parent: converted, - title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`, - name: splitColumn.name, - key: splitValue, - column: splitColumnIndex, - row: rowIndex, - table: table, - tables: [], - }; - tableGroup.tables.push({ - $parent: tableGroup, - columns: table.columns, - rows: [], - }); - - converted.tables.push(tableGroup); - } - - const tableIndex = splitMap[splitValue]; - converted.tables[tableIndex].tables[0].rows.push(row); - }); - } else { - converted.tables.push({ - columns: table.columns, - rows: table.rows, - }); - } - - resolve(converted); - }); - }, - }; -}; diff --git a/src/legacy/ui/public/vis/response_handlers/vislib.js b/src/legacy/ui/public/vis/response_handlers/vislib.js deleted file mode 100644 index afa155b8a46619..00000000000000 --- a/src/legacy/ui/public/vis/response_handlers/vislib.js +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { buildHierarchicalData } from '../../agg_response/hierarchical/build_hierarchical_data'; -import { buildPointSeriesData } from '../../agg_response/point_series/point_series'; -import { legacyResponseHandlerProvider } from './legacy'; - -const tableResponseHandler = legacyResponseHandlerProvider().handler; - -function convertTableGroup(tableGroup, convertTable) { - const tables = tableGroup.tables; - - if (!tables.length) return; - - const firstChild = tables[0]; - if (firstChild.columns) { - const chart = convertTable(firstChild); - // if chart is within a split, assign group title to its label - if (tableGroup.$parent) { - chart.label = tableGroup.title; - } - return chart; - } - - const out = {}; - let outList; - - tables.forEach(function(table) { - if (!outList) { - const direction = tableGroup.direction === 'row' ? 'rows' : 'columns'; - outList = out[direction] = []; - } - - let output; - if ((output = convertTableGroup(table, convertTable))) { - outList.push(output); - } - }); - - return out; -} - -const handlerFunction = function(convertTable) { - return function(response, dimensions) { - return new Promise(resolve => { - return tableResponseHandler(response, dimensions).then(tableGroup => { - let converted = convertTableGroup(tableGroup, table => { - return convertTable(table, dimensions); - }); - if (!converted) { - // mimic a row of tables that doesn't have any tables - // https://github.com/elastic/kibana/blob/7bfb68cd24ed42b1b257682f93c50cd8d73e2520/src/kibana/components/vislib/components/zero_injection/inject_zeros.js#L32 - converted = { rows: [] }; - } - - converted.hits = response.rows.length; - - resolve(converted); - }); - }); - }; -}; - -export const vislibSeriesResponseHandlerProvider = function() { - return { - name: 'vislib_series', - handler: handlerFunction(buildPointSeriesData), - }; -}; - -export const vislibSlicesResponseHandlerProvider = function() { - return { - name: 'vislib_slices', - handler: handlerFunction(buildHierarchicalData), - }; -}; diff --git a/src/legacy/ui/public/vis/vis_types/_index.scss b/src/legacy/ui/public/vis/vis_types/_index.scss deleted file mode 100644 index 9d86383ec40b2e..00000000000000 --- a/src/legacy/ui/public/vis/vis_types/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './vislib_vis_type'; -@import './vislib_vis_legend'; diff --git a/src/legacy/ui/public/vis/vis_types/_vislib_vis_legend.scss b/src/legacy/ui/public/vis/vis_types/_vislib_vis_legend.scss deleted file mode 100644 index 62050ce4e99fd3..00000000000000 --- a/src/legacy/ui/public/vis/vis_types/_vislib_vis_legend.scss +++ /dev/null @@ -1,100 +0,0 @@ -@import '../../../../core_plugins/vis_type_vislib/public/vislib/variables'; - -// NOTE: Some of the styles attempt to align with the TSVB legend - -$visLegendWidth: 150px; -$visColorPickerWidth: $euiSizeM * 10; -$visLegendLineHeight: $euiSize; - -.visLegend__toggle { - border-radius: $euiBorderRadius; - position: absolute; - bottom: 0; - left: 0; - display: flex; - padding: $euiSizeXS; - background-color: $euiColorEmptyShade; - transition: opacity $euiAnimSpeedFast $euiAnimSlightResistance, - background-color $euiAnimSpeedFast $euiAnimSlightResistance $euiAnimSpeedExtraSlow; - - &:focus { - box-shadow: none; - background-color: $euiFocusBackgroundColor !important; - } -} - -.visLegend__toggle--isOpen { - background-color: transparentize($euiColorDarkestShade, 0.9); - opacity: 1; -} - -.visLegend { - display: flex; - min-height: 0; - height: 100%; -} - -.visLib--legend-left { - .visLegend__list { - margin-bottom: $euiSizeL; - } -} - -.visLib--legend-bottom { - .visLegend__list { - margin-left: $euiSizeL; - } -} - -.visLegend__list { - @include euiScrollBar; - display: flex; - width: $visLegendWidth; // Must be a hard-coded width for the chart to get its correct dimensions - flex: 1 1 auto; - flex-direction: column; - overflow-x: hidden; - overflow-y: auto; - - .visLegend__button { - font-size: $euiFontSizeXS; - text-align: left; - overflow: hidden; // Ensures scrollbars don't appear because EuiButton__text has a high line-height - - .visLegend__valueTitle { - vertical-align: middle; - } - } - - .visLib--legend-top &, - .visLib--legend-bottom & { - width: auto; - flex-direction: row; - flex-wrap: wrap; - - .visLegend__value { - flex-grow: 0; - max-width: $visLegendWidth; - } - } - - &.hidden { - visibility: hidden; - } -} - -.visLegend__valueColorPicker { - width: ($euiSizeL * 8); // 8 columns -} - -.visLegend__valueColorPickerDot { - cursor: pointer; - - &:hover { - transform: scale(1.4); - } - - &-isSelected { - border: $euiSizeXS solid; - border-radius: 100%; - } -} diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/index.ts b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/index.ts deleted file mode 100644 index ebf132f0ab697f..00000000000000 --- a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { VisLegend } from './vislib_vis_legend'; -export { CUSTOM_LEGEND_VIS_TYPES } from './models'; diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.test.tsx b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.test.tsx deleted file mode 100644 index 839dc0024bbea5..00000000000000 --- a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.test.tsx +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; - -import { I18nProvider } from '@kbn/i18n/react'; -import { EuiButtonGroup } from '@elastic/eui'; - -import { VisLegend, VisLegendProps } from '../vislib_vis_legend/vislib_vis_legend'; -import { legendColors } from './models'; - -jest.mock('@elastic/eui', () => ({ - ...jest.requireActual('@elastic/eui'), - htmlIdGenerator: jest.fn().mockReturnValue(() => 'legendId'), -})); - -jest.mock('../../../visualize/loader/pipeline_helpers/utilities', () => ({ - getTableAggs: jest.fn(), -})); -jest.mock('../../../../../core_plugins/visualizations/public', () => ({ - createFiltersFromEvent: jest.fn().mockReturnValue(['yes']), -})); - -const vis = { - params: { - addLegend: true, - }, - API: { - events: { - filter: jest.fn(), - }, - }, -}; -const vislibVis = { - handler: { - highlight: jest.fn(), - unHighlight: jest.fn(), - }, - getLegendLabels: jest.fn(), - visConfigArgs: { - type: 'area', - }, - visConfig: { - data: { - getColorFunc: jest.fn().mockReturnValue(() => 'red'), - }, - }, -}; - -const visData = { - series: [ - { - label: 'A', - values: [ - { - seriesRaw: 'valuesA', - }, - ], - }, - { - label: 'B', - values: [ - { - seriesRaw: 'valuesB', - }, - ], - }, - ], -}; - -const mockState = new Map(); -const uiState = { - get: jest - .fn() - .mockImplementation((key, fallback) => (mockState.has(key) ? mockState.get(key) : fallback)), - set: jest.fn().mockImplementation((key, value) => mockState.set(key, value)), - emit: jest.fn(), - setSilent: jest.fn(), -}; - -const getWrapper = (props?: Partial) => - mount( - - - - ); - -const getLegendItems = (wrapper: ReactWrapper) => wrapper.find('.visLegend__button'); - -describe('VisLegend Component', () => { - let wrapper: ReactWrapper; - - afterEach(() => { - mockState.clear(); - jest.clearAllMocks(); - }); - - describe('Legend open', () => { - beforeEach(() => { - mockState.set('vis.legendOpen', true); - wrapper = getWrapper(); - }); - - it('should match the snapshot', () => { - expect(wrapper.html()).toMatchSnapshot(); - }); - }); - - describe('Legend closed', () => { - beforeEach(() => { - mockState.set('vis.legendOpen', false); - wrapper = getWrapper(); - }); - - it('should match the snapshot', () => { - expect(wrapper.html()).toMatchSnapshot(); - }); - }); - - describe('Highlighting', () => { - beforeEach(() => { - wrapper = getWrapper(); - }); - - it('should call highlight handler when legend item is focused', () => { - const first = getLegendItems(wrapper).first(); - first.simulate('focus'); - - expect(vislibVis.handler.highlight).toHaveBeenCalledTimes(1); - }); - - it('should call highlight handler when legend item is hovered', () => { - const first = getLegendItems(wrapper).first(); - first.simulate('mouseEnter'); - - expect(vislibVis.handler.highlight).toHaveBeenCalledTimes(1); - }); - - it('should call unHighlight handler when legend item is blurred', () => { - let first = getLegendItems(wrapper).first(); - first.simulate('focus'); - first = getLegendItems(wrapper).first(); - first.simulate('blur'); - - expect(vislibVis.handler.unHighlight).toHaveBeenCalledTimes(1); - }); - - it('should call unHighlight handler when legend item is unhovered', () => { - const first = getLegendItems(wrapper).first(); - - first.simulate('mouseEnter'); - first.simulate('mouseLeave'); - - expect(vislibVis.handler.unHighlight).toHaveBeenCalledTimes(1); - }); - - it('should work with no handlers set', () => { - const newVis = { - ...vis, - vislibVis: { - ...vislibVis, - handler: null, - }, - }; - - expect(() => { - wrapper = getWrapper({ vis: newVis }); - const first = getLegendItems(wrapper).first(); - first.simulate('focus'); - first.simulate('blur'); - }).not.toThrow(); - }); - }); - - describe('Filtering', () => { - beforeEach(() => { - wrapper = getWrapper(); - }); - - it('should filter out when clicked', () => { - const first = getLegendItems(wrapper).first(); - first.simulate('click'); - const filterGroup = wrapper.find(EuiButtonGroup).first(); - filterGroup.getElement().props.onChange('filterIn'); - - expect(vis.API.events.filter).toHaveBeenCalledWith({ data: ['valuesA'], negate: false }); - expect(vis.API.events.filter).toHaveBeenCalledTimes(1); - }); - - it('should filter in when clicked', () => { - const first = getLegendItems(wrapper).first(); - first.simulate('click'); - const filterGroup = wrapper.find(EuiButtonGroup).first(); - filterGroup.getElement().props.onChange('filterOut'); - - expect(vis.API.events.filter).toHaveBeenCalledWith({ data: ['valuesA'], negate: true }); - expect(vis.API.events.filter).toHaveBeenCalledTimes(1); - }); - }); - - describe('Toggles details', () => { - beforeEach(() => { - wrapper = getWrapper(); - }); - - it('should show details when clicked', () => { - const first = getLegendItems(wrapper).first(); - first.simulate('click'); - - expect(wrapper.exists('.visLegend__valueDetails')).toBe(true); - }); - }); - - describe('setColor', () => { - beforeEach(() => { - wrapper = getWrapper(); - }); - - it('sets the color in the UI state', () => { - const first = getLegendItems(wrapper).first(); - first.simulate('click'); - - const popover = wrapper.find('.visLegend__valueDetails').first(); - const firstColor = popover.find('.visLegend__valueColorPickerDot').first(); - firstColor.simulate('click'); - - const colors = mockState.get('vis.colors'); - - expect(colors.A).toBe(legendColors[0]); - }); - }); - - describe('toggleLegend function', () => { - it('click should show legend once toggled from hidden', () => { - mockState.set('vis.legendOpen', false); - wrapper = getWrapper(); - const toggleButton = wrapper.find('.visLegend__toggle').first(); - toggleButton.simulate('click'); - - expect(wrapper.exists('.visLegend__list')).toBe(true); - }); - - it('click should hide legend once toggled from shown', () => { - mockState.set('vis.legendOpen', true); - wrapper = getWrapper(); - const toggleButton = wrapper.find('.visLegend__toggle').first(); - toggleButton.simulate('click'); - - expect(wrapper.exists('.visLegend__list')).toBe(false); - }); - }); -}); diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx deleted file mode 100644 index d98590f9885b9d..00000000000000 --- a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React, { BaseSyntheticEvent, KeyboardEvent, PureComponent } from 'react'; -import classNames from 'classnames'; -import { compact, uniq, map } from 'lodash'; - -import { i18n } from '@kbn/i18n'; -import { EuiPopoverProps, EuiIcon, keyCodes, htmlIdGenerator } from '@elastic/eui'; - -// @ts-ignore -import { createFiltersFromEvent } from '../../../../../core_plugins/visualizations/public'; -import { CUSTOM_LEGEND_VIS_TYPES, LegendItem } from './models'; -import { VisLegendItem } from './vislib_vis_legend_item'; -import { getPieNames } from './pie_utils'; -import { getTableAggs } from '../../../visualize/loader/pipeline_helpers/utilities'; - -export interface VisLegendProps { - vis: any; - vislibVis: any; - visData: any; - uiState: any; - position: 'top' | 'bottom' | 'left' | 'right'; -} - -export interface VisLegendState { - open: boolean; - labels: any[]; - tableAggs: any[]; - selectedLabel: string | null; -} - -export class VisLegend extends PureComponent { - legendId = htmlIdGenerator()('legend'); - getColor: (label: string) => string = () => ''; - - constructor(props: VisLegendProps) { - super(props); - const open = props.uiState.get('vis.legendOpen', true); - - this.state = { - open, - labels: [], - tableAggs: [], - selectedLabel: null, - }; - } - - componentDidMount() { - this.refresh(); - } - - toggleLegend = () => { - const bwcAddLegend = this.props.vis.params.addLegend; - const bwcLegendStateDefault = bwcAddLegend == null ? true : bwcAddLegend; - const newOpen = !this.props.uiState.get('vis.legendOpen', bwcLegendStateDefault); - this.setState({ open: newOpen }); - // open should be applied on template before we update uiState - setTimeout(() => { - this.props.uiState.set('vis.legendOpen', newOpen); - }); - }; - - setColor = (label: string, color: string) => (event: BaseSyntheticEvent) => { - if ((event as KeyboardEvent).keyCode && (event as KeyboardEvent).keyCode !== keyCodes.ENTER) { - return; - } - - const colors = this.props.uiState.get('vis.colors') || {}; - if (colors[label] === color) delete colors[label]; - else colors[label] = color; - this.props.uiState.setSilent('vis.colors', null); - this.props.uiState.set('vis.colors', colors); - this.props.uiState.emit('colorChanged'); - this.refresh(); - }; - - filter = ({ values: data }: LegendItem, negate: boolean) => { - this.props.vis.API.events.filter({ data, negate }); - }; - - canFilter = (item: LegendItem): boolean => { - if (CUSTOM_LEGEND_VIS_TYPES.includes(this.props.vislibVis.visConfigArgs.type)) { - return false; - } - const filters = createFiltersFromEvent({ aggConfigs: this.state.tableAggs, data: item.values }); - return Boolean(filters.length); - }; - - toggleDetails = (label: string | null) => (event?: BaseSyntheticEvent) => { - if ( - event && - (event as KeyboardEvent).keyCode && - (event as KeyboardEvent).keyCode !== keyCodes.ENTER - ) { - return; - } - this.setState({ selectedLabel: this.state.selectedLabel === label ? null : label }); - }; - - getSeriesLabels = (data: any[]) => { - const values = data.map(chart => chart.series).reduce((a, b) => a.concat(b), []); - - return compact(uniq(values, 'label')).map((label: any) => ({ - ...label, - values: [label.values[0].seriesRaw], - })); - }; - - // Most of these functions were moved directly from the old Legend class. Not a fan of this. - getLabels = (data: any, type: string) => { - if (!data) return []; - data = data.columns || data.rows || [data]; - - if (type === 'pie') return getPieNames(data); - - return this.getSeriesLabels(data); - }; - - refresh = () => { - const vislibVis = this.props.vislibVis; - if (!vislibVis || !vislibVis.visConfig) { - this.setState({ - labels: [ - { - label: i18n.translate('common.ui.vis.visTypes.legend.loadingLabel', { - defaultMessage: 'loading…', - }), - }, - ], - }); - return; - } // make sure vislib is defined at this point - - if ( - this.props.uiState.get('vis.legendOpen') == null && - this.props.vis.params.addLegend != null - ) { - this.setState({ open: this.props.vis.params.addLegend }); - } - - if (CUSTOM_LEGEND_VIS_TYPES.includes(vislibVis.visConfigArgs.type)) { - const legendLabels = this.props.vislibVis.getLegendLabels(); - if (legendLabels) { - this.setState({ - labels: map(legendLabels, label => { - return { label }; - }), - }); - } - } else { - this.setState({ labels: this.getLabels(this.props.visData, vislibVis.visConfigArgs.type) }); - } - - if (vislibVis.visConfig) { - this.getColor = this.props.vislibVis.visConfig.data.getColorFunc(); - } - - this.setState({ tableAggs: getTableAggs(this.props.vis) }); - }; - - highlight = (event: BaseSyntheticEvent) => { - const el = event.currentTarget; - const handler = this.props.vislibVis && this.props.vislibVis.handler; - - // there is no guarantee that a Chart will set the highlight-function on its handler - if (!handler || typeof handler.highlight !== 'function') { - return; - } - handler.highlight.call(el, handler.el); - }; - - unhighlight = (event: BaseSyntheticEvent) => { - const el = event.currentTarget; - const handler = this.props.vislibVis && this.props.vislibVis.handler; - - // there is no guarantee that a Chart will set the unhighlight-function on its handler - if (!handler || typeof handler.unHighlight !== 'function') { - return; - } - handler.unHighlight.call(el, handler.el); - }; - - getAnchorPosition = () => { - const { position } = this.props; - - switch (position) { - case 'bottom': - return 'upCenter'; - case 'left': - return 'rightUp'; - case 'right': - return 'leftUp'; - default: - return 'downCenter'; - } - }; - - renderLegend = (anchorPosition: EuiPopoverProps['anchorPosition']) => ( -
      - {this.state.labels.map(item => ( - - ))} -
    - ); - - render() { - const { open } = this.state; - const anchorPosition = this.getAnchorPosition(); - - return ( -
    - - {open && this.renderLegend(anchorPosition)} -
    - ); - } -} diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend_item.tsx b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend_item.tsx deleted file mode 100644 index 7376fabfe738be..00000000000000 --- a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend_item.tsx +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { memo, BaseSyntheticEvent, KeyboardEvent } from 'react'; -import classNames from 'classnames'; - -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiPopover, - keyCodes, - EuiIcon, - EuiSpacer, - EuiButtonEmpty, - EuiPopoverProps, - EuiButtonGroup, - EuiButtonGroupOption, -} from '@elastic/eui'; - -import { legendColors, LegendItem } from './models'; - -interface Props { - item: LegendItem; - legendId: string; - selected: boolean; - canFilter: boolean; - anchorPosition: EuiPopoverProps['anchorPosition']; - onFilter: (item: LegendItem, negate: boolean) => void; - onSelect: (label: string | null) => (event?: BaseSyntheticEvent) => void; - onHighlight: (event: BaseSyntheticEvent) => void; - onUnhighlight: (event: BaseSyntheticEvent) => void; - setColor: (label: string, color: string) => (event: BaseSyntheticEvent) => void; - getColor: (label: string) => string; -} - -const VisLegendItemComponent = ({ - item, - legendId, - selected, - canFilter, - anchorPosition, - onFilter, - onSelect, - onHighlight, - onUnhighlight, - setColor, - getColor, -}: Props) => { - /** - * Keydown listener for a legend entry. - * This will close the details panel of this legend entry when pressing Escape. - */ - const onLegendEntryKeydown = (event: KeyboardEvent) => { - if (event.keyCode === keyCodes.ESCAPE) { - event.preventDefault(); - event.stopPropagation(); - onSelect(null)(); - } - }; - - const filterOptions: EuiButtonGroupOption[] = [ - { - id: 'filterIn', - label: i18n.translate('common.ui.vis.visTypes.legend.filterForValueButtonAriaLabel', { - defaultMessage: 'Filter for value {legendDataLabel}', - values: { legendDataLabel: item.label }, - }), - iconType: 'plusInCircle', - 'data-test-subj': `legend-${item.label}-filterIn`, - }, - { - id: 'filterOut', - label: i18n.translate('common.ui.vis.visTypes.legend.filterOutValueButtonAriaLabel', { - defaultMessage: 'Filter out value {legendDataLabel}', - values: { legendDataLabel: item.label }, - }), - iconType: 'minusInCircle', - 'data-test-subj': `legend-${item.label}-filterOut`, - }, - ]; - - const handleFilterChange = (id: string) => { - onFilter(item, id !== 'filterIn'); - }; - - const renderFilterBar = () => ( - <> - - - - ); - - const button = ( - - - {item.label} - - ); - - const renderDetails = () => ( - -
    - {canFilter && renderFilterBar()} - -
    - - - - {legendColors.map(color => ( - - ))} -
    -
    -
    - ); - - return ( -
  • - {renderDetails()} -
  • - ); -}; - -export const VisLegendItem = memo(VisLegendItemComponent); diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts index 0b99810a85afec..bde865f504fdb8 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts @@ -22,8 +22,7 @@ import { identity } from 'lodash'; import { AggConfig, Vis } from 'ui/vis'; import { npStart } from 'ui/new_platform'; import { SerializedFieldFormat } from 'src/plugins/expressions/public'; - -import { IFieldFormatId, FieldFormat, ContentType } from '../../../../../../plugins/data/public'; +import { fieldFormats } from '../../../../../../plugins/data/public'; import { tabifyGetColumns } from '../../../agg_response/tabify/_get_columns'; import { DateRangeKey, convertDateRangeToString } from '../../../agg_types/buckets/date_range'; @@ -43,13 +42,16 @@ function isTermsFieldFormat( const getConfig = (key: string, defaultOverride?: any): any => npStart.core.uiSettings.get(key, defaultOverride); -const DefaultFieldFormat = FieldFormat.from(identity); +const DefaultFieldFormat = fieldFormats.FieldFormat.from(identity); -const getFieldFormat = (id?: IFieldFormatId, params: object = {}): FieldFormat => { - const fieldFormats = npStart.plugins.data.fieldFormats; +const getFieldFormat = ( + id?: fieldFormats.IFieldFormatId, + params: object = {} +): fieldFormats.FieldFormat => { + const fieldFormatsService = npStart.plugins.data.fieldFormats; if (id) { - const Format = fieldFormats.getType(id); + const Format = fieldFormatsService.getType(id); if (Format) { return new Format(params, getConfig); @@ -91,7 +93,7 @@ export const createFormat = (agg: AggConfig): SerializedFieldFormat => { return formats[agg.type.name] ? formats[agg.type.name]() : format; }; -export type FormatFactory = (mapping?: SerializedFieldFormat) => FieldFormat; +export type FormatFactory = (mapping?: SerializedFieldFormat) => fieldFormats.FieldFormat; export const getFormat: FormatFactory = mapping => { if (!mapping) { @@ -99,7 +101,7 @@ export const getFormat: FormatFactory = mapping => { } const { id } = mapping; if (id === 'range') { - const RangeFormat = FieldFormat.from((range: any) => { + const RangeFormat = fieldFormats.FieldFormat.from((range: any) => { const format = getFieldFormat(id, mapping.params); const gte = '\u2265'; const lt = '\u003c'; @@ -116,21 +118,21 @@ export const getFormat: FormatFactory = mapping => { return new RangeFormat(); } else if (id === 'date_range') { const nestedFormatter = mapping.params as SerializedFieldFormat; - const DateRangeFormat = FieldFormat.from((range: DateRangeKey) => { + const DateRangeFormat = fieldFormats.FieldFormat.from((range: DateRangeKey) => { const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params); return convertDateRangeToString(range, format.convert.bind(format)); }); return new DateRangeFormat(); } else if (id === 'ip_range') { const nestedFormatter = mapping.params as SerializedFieldFormat; - const IpRangeFormat = FieldFormat.from((range: IpRangeKey) => { + const IpRangeFormat = fieldFormats.FieldFormat.from((range: IpRangeKey) => { const format = getFieldFormat(nestedFormatter.id, nestedFormatter.params); return convertIPRangeToString(range, format.convert.bind(format)); }); return new IpRangeFormat(); } else if (isTermsFieldFormat(mapping) && mapping.params) { const { params } = mapping; - const convert = (val: string, type: ContentType) => { + const convert = (val: string, type: fieldFormats.ContentType) => { const format = getFieldFormat(params.id, mapping.params); if (val === '__other__') { @@ -145,8 +147,8 @@ export const getFormat: FormatFactory = mapping => { return { convert, - getConverterFor: (type: ContentType) => (val: string) => convert(val, type), - } as FieldFormat; + getConverterFor: (type: fieldFormats.ContentType) => (val: string) => convert(val, type), + } as fieldFormats.FieldFormat; } else { return getFieldFormat(id, mapping.params); } @@ -159,5 +161,3 @@ export const getTableAggs = (vis: Vis): AggConfig[] => { const columns = tabifyGetColumns(vis.aggs.getResponseAggs(), !vis.isHierarchical()); return columns.map(c => c.aggConfig); }; - -export { FieldFormat }; diff --git a/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts b/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts index 5054c34118f786..0ae8771dd94698 100644 --- a/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts +++ b/src/legacy/ui/public/visualize/loader/utils/query_geohash_bounds.ts @@ -24,8 +24,12 @@ import { toastNotifications } from 'ui/notify'; import { AggConfig } from 'ui/vis'; import { timefilter } from 'ui/timefilter'; import { Vis } from '../../../vis'; -import { SearchSource, ISearchSource } from '../../../courier'; -import { esFilters, Query } from '../../../../../../plugins/data/public'; +import { + esFilters, + Query, + SearchSource, + ISearchSource, +} from '../../../../../../plugins/data/public'; interface QueryGeohashBoundsParams { filters?: esFilters.Filter[]; diff --git a/src/legacy/ui/tutorials_mixin.js b/src/legacy/ui/tutorials_mixin.js deleted file mode 100644 index efaf4ee7e78f03..00000000000000 --- a/src/legacy/ui/tutorials_mixin.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Joi from 'joi'; -import { tutorialSchema } from '../core_plugins/kibana/common/tutorials/tutorial_schema'; - -export function tutorialsMixin(kbnServer, server) { - const tutorialProviders = []; - const scopedTutorialContextFactories = []; - - server.decorate('server', 'getTutorials', request => { - const initialContext = {}; - const scopedContext = scopedTutorialContextFactories.reduce( - (accumulatedContext, contextFactory) => { - return { ...accumulatedContext, ...contextFactory(request) }; - }, - initialContext - ); - - return tutorialProviders.map(tutorialProvider => { - return tutorialProvider(server, scopedContext); - }); - }); - - server.decorate('server', 'registerTutorial', specProvider => { - // registration during setup - const emptyContext = {}; - const { error } = Joi.validate(specProvider(server, emptyContext), tutorialSchema); - - if (error) { - throw new Error(`Unable to register tutorial spec because its invalid. ${error}`); - } - - tutorialProviders.push(specProvider); - }); - - server.decorate('server', 'addScopedTutorialContextFactory', scopedTutorialContextFactory => { - // returned by the setup method of the new plugin, they will do the same thing as now - if (typeof scopedTutorialContextFactory !== 'function') { - throw new Error( - `Unable to add scoped(request) context factory because you did not provide a function` - ); - } - - scopedTutorialContextFactories.push(scopedTutorialContextFactory); - }); -} diff --git a/src/legacy/ui/tutorials_mixin.test.js b/src/legacy/ui/tutorials_mixin.test.js deleted file mode 100644 index 58841987e0281d..00000000000000 --- a/src/legacy/ui/tutorials_mixin.test.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { tutorialsMixin } from './tutorials_mixin'; - -const validTutorial = { - id: 'spec1', - category: 'other', - name: 'spec1', - shortDescription: 'short description', - longDescription: 'long description', - onPrem: { - instructionSets: [ - { - instructionVariants: [ - { - id: 'instructionVariant1', - instructions: [{}], - }, - ], - }, - ], - }, -}; - -describe('tutorial mixins', () => { - let getTutorials; - let registerTutorial; - let addScopedTutorialContextFactory; - const serverMock = { decorate: jest.fn() }; - beforeEach(async () => { - await tutorialsMixin({}, serverMock); - - [ - [, , getTutorials], - [, , registerTutorial], - [, , addScopedTutorialContextFactory], - ] = serverMock.decorate.mock.calls; - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('scoped context', () => { - const mockRequest = {}; - const spacesContextFactory = request => { - if (request !== mockRequest) { - throw new Error('context factory not called with request object'); - } - return { - spaceId: 'my-space', - }; - }; - const specProvider = (server, context) => { - const tutorial = { ...validTutorial }; - tutorial.shortDescription = `I have been provided with scoped context, spaceId: ${context.spaceId}`; - return tutorial; - }; - beforeEach(async () => { - addScopedTutorialContextFactory(spacesContextFactory); - registerTutorial(specProvider); - }); - - test('passes scoped context to specProviders', () => { - const tutorials = getTutorials(mockRequest); - expect(tutorials.length).toBe(1); - expect(tutorials[0].shortDescription).toBe( - 'I have been provided with scoped context, spaceId: my-space' - ); - }); - }); -}); diff --git a/src/legacy/ui/ui_apps/ui_app.js b/src/legacy/ui/ui_apps/ui_app.js index 9c82ff2abedb57..1cfd54588b516e 100644 --- a/src/legacy/ui/ui_apps/ui_app.js +++ b/src/legacy/ui/ui_apps/ui_app.js @@ -32,6 +32,7 @@ export class UiApp { hidden, linkToLastSubUrl, listed, + category, url = `/app/${id}`, } = spec; @@ -46,6 +47,7 @@ export class UiApp { this._icon = icon; this._euiIconType = euiIconType; this._linkToLastSubUrl = linkToLastSubUrl; + this._category = category; this._hidden = hidden; this._listed = listed; this._url = url; @@ -68,6 +70,7 @@ export class UiApp { euiIconType: this._euiIconType, url: this._url, linkToLastSubUrl: this._linkToLastSubUrl, + category: this._category, }); } } @@ -115,6 +118,7 @@ export class UiApp { main: this._main, navLink: this._navLink, linkToLastSubUrl: this._linkToLastSubUrl, + category: this._category, }; } } diff --git a/src/legacy/ui/ui_exports/ui_export_defaults.js b/src/legacy/ui/ui_exports/ui_export_defaults.js index a62ebdc25ca2c5..1cb23d2ad2a236 100644 --- a/src/legacy/ui/ui_exports/ui_export_defaults.js +++ b/src/legacy/ui/ui_exports/ui_export_defaults.js @@ -47,6 +47,5 @@ export const UI_EXPORT_DEFAULTS = { appExtensions: { fieldFormatEditors: ['ui/field_editor/components/field_format_editor/register'], - search: ['ui/courier/search_strategy/default_search_strategy'], }, }; diff --git a/src/legacy/ui/ui_exports/ui_export_types/ui_apps.js b/src/legacy/ui/ui_exports/ui_export_types/ui_apps.js index d7ac49d9d49a32..639a5a7c58e180 100644 --- a/src/legacy/ui/ui_exports/ui_export_types/ui_apps.js +++ b/src/legacy/ui/ui_exports/ui_export_types/ui_apps.js @@ -34,6 +34,7 @@ function applySpecDefaults(spec, type, pluginSpec) { linkToLastSubUrl = true, listed = !hidden, url = `/app/${id}`, + category, } = spec; if (spec.injectVars) { @@ -61,6 +62,7 @@ function applySpecDefaults(spec, type, pluginSpec) { linkToLastSubUrl, listed, url, + category, }; } diff --git a/src/legacy/ui/ui_mixin.js b/src/legacy/ui/ui_mixin.js index 24d22efe4fa067..831c2c5deb829e 100644 --- a/src/legacy/ui/ui_mixin.js +++ b/src/legacy/ui/ui_mixin.js @@ -17,8 +17,6 @@ * under the License. */ -import { fieldFormatsMixin } from './field_formats'; -import { tutorialsMixin } from './tutorials_mixin'; import { uiAppsMixin } from './ui_apps'; import { uiBundlesMixin } from './ui_bundles'; import { uiRenderMixin } from './ui_render'; @@ -28,7 +26,5 @@ export async function uiMixin(kbnServer) { await kbnServer.mixin(uiAppsMixin); await kbnServer.mixin(uiBundlesMixin); await kbnServer.mixin(uiSettingsMixin); - await kbnServer.mixin(fieldFormatsMixin); - await kbnServer.mixin(tutorialsMixin); await kbnServer.mixin(uiRenderMixin); } diff --git a/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js b/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js index 37e023127ed419..543fe05b13e43e 100644 --- a/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js +++ b/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js @@ -45,6 +45,7 @@ describe('UiNavLink', () => { euiIconType: spec.euiIconType, hidden: spec.hidden, disabled: spec.disabled, + category: undefined, // defaults linkToLastSubUrl: true, diff --git a/src/legacy/ui/ui_nav_links/ui_nav_link.js b/src/legacy/ui/ui_nav_links/ui_nav_link.js index 7537a60adbcf2d..5888c21a53c95c 100644 --- a/src/legacy/ui/ui_nav_links/ui_nav_link.js +++ b/src/legacy/ui/ui_nav_links/ui_nav_link.js @@ -31,6 +31,7 @@ export class UiNavLink { hidden = false, disabled = false, tooltip = '', + category, } = spec; this._id = id; @@ -44,6 +45,7 @@ export class UiNavLink { this._hidden = hidden; this._disabled = disabled; this._tooltip = tooltip; + this._category = category; } getOrder() { @@ -63,6 +65,7 @@ export class UiNavLink { hidden: this._hidden, disabled: this._disabled, tooltip: this._tooltip, + category: this._category, }; } } diff --git a/src/legacy/utils/index.d.ts b/src/legacy/utils/index.d.ts index 8718ffc113e104..7ac9feab09cbe6 100644 --- a/src/legacy/utils/index.d.ts +++ b/src/legacy/utils/index.d.ts @@ -21,6 +21,4 @@ export function parseCommaSeparatedList(input: string | string[]): string[]; export function formatListAsProse(list: string[], options?: { inclusive?: boolean }): string; -export function getFlattenedObject(rootValue: Record): { [key: string]: any }; - export function unset(object: object, rawPath: string): void; diff --git a/src/legacy/utils/index.js b/src/legacy/utils/index.js index e2323f2ed62eeb..cb890f1094b04e 100644 --- a/src/legacy/utils/index.js +++ b/src/legacy/utils/index.js @@ -22,7 +22,6 @@ export { BinderFor } from './binder_for'; export { deepCloneWithBuffers } from './deep_clone_with_buffers'; export { unset } from './unset'; export { encodeQueryComponent } from './encode_query_component'; -export { getFlattenedObject } from './get_flattened_object'; export { watchStdioForLine } from './watch_stdio_for_line'; export { IS_KIBANA_DISTRIBUTABLE } from './artifact_type'; export { IS_KIBANA_RELEASE } from './artifact_type'; diff --git a/src/plugins/console/public/application/components/index.ts b/src/plugins/console/public/application/components/index.ts index 4669e210e7c2d8..eccde899a2640c 100644 --- a/src/plugins/console/public/application/components/index.ts +++ b/src/plugins/console/public/application/components/index.ts @@ -17,7 +17,6 @@ * under the License. */ -export * from './split_panel'; export { SomethingWentWrongCallout } from './something_went_wrong_callout'; export { TopNavMenuItem, TopNavMenu } from './top_nav_menu'; export { ConsoleMenu } from './console_menu'; diff --git a/src/plugins/console/public/application/containers/editor/editor.tsx b/src/plugins/console/public/application/containers/editor/editor.tsx index 7be1382760eb91..b42d791e5acd8e 100644 --- a/src/plugins/console/public/application/containers/editor/editor.tsx +++ b/src/plugins/console/public/application/containers/editor/editor.tsx @@ -21,7 +21,7 @@ import React, { useCallback } from 'react'; import { debounce } from 'lodash'; import { EditorContentSpinner } from '../../components'; -import { Panel, PanelsContainer } from '../../components/split_panel'; +import { Panel, PanelsContainer } from '../../../../../../../../plugins/kibana_react/public'; import { Editor as EditorUI, EditorOutput } from './legacy/console_editor'; import { StorageKeys } from '../../../services'; import { useEditorReadContext, useServicesContext } from '../../contexts'; diff --git a/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_flyout.tsx b/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_flyout.tsx index 36313353e3c332..7b3842bd33dbd0 100644 --- a/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_flyout.tsx +++ b/src/plugins/dashboard_embeddable_container/public/actions/replace_panel_flyout.tsx @@ -76,7 +76,7 @@ export class ReplacePanelFlyout extends React.Component { // add the new view const newObj = await this.props.container.addSavedObjectEmbeddable(type, id); - const finalPanels = this.props.container.getInput().panels; + const finalPanels = _.cloneDeep(this.props.container.getInput().panels); (finalPanels[newObj.id] as DashboardPanelState).gridData.w = nnw; (finalPanels[newObj.id] as DashboardPanelState).gridData.h = nnh; (finalPanels[newObj.id] as DashboardPanelState).gridData.x = nnx; @@ -86,7 +86,7 @@ export class ReplacePanelFlyout extends React.Component { delete finalPanels[this.props.panelToRemove.id]; // apply changes - this.props.container.updateInput(finalPanels); + this.props.container.updateInput({ panels: finalPanels }); this.props.container.reload(); this.showToast(name); diff --git a/src/plugins/data/common/field_formats/constants/base_formatters.ts b/src/plugins/data/common/field_formats/constants/base_formatters.ts new file mode 100644 index 00000000000000..95aedd02d16d65 --- /dev/null +++ b/src/plugins/data/common/field_formats/constants/base_formatters.ts @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IFieldFormatType } from '../types'; + +import { + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, +} from '../converters'; + +export const baseFormatters: IFieldFormatType[] = [ + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, +]; diff --git a/src/plugins/data/common/field_formats/constants/index.ts b/src/plugins/data/common/field_formats/constants/index.ts deleted file mode 100644 index 7f95df44496311..00000000000000 --- a/src/plugins/data/common/field_formats/constants/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { DEFAULT_CONVERTER_COLOR } from './color_default'; diff --git a/src/plugins/data/common/field_formats/converters/color.ts b/src/plugins/data/common/field_formats/converters/color.ts index ffc72ba9a2c306..20d9d6aee6d26e 100644 --- a/src/plugins/data/common/field_formats/converters/color.ts +++ b/src/plugins/data/common/field_formats/converters/color.ts @@ -22,7 +22,7 @@ import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; import { HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; import { asPrettyString } from '../utils'; -import { DEFAULT_CONVERTER_COLOR } from '../constants'; +import { DEFAULT_CONVERTER_COLOR } from '../constants/color_default'; const convertTemplate = template('<%- val %>'); diff --git a/src/plugins/data/common/field_formats/converters/custom.ts b/src/plugins/data/common/field_formats/converters/custom.ts index 1c17e231cace83..a1ce0cf3e7b54d 100644 --- a/src/plugins/data/common/field_formats/converters/custom.ts +++ b/src/plugins/data/common/field_formats/converters/custom.ts @@ -17,8 +17,8 @@ * under the License. */ -import { FieldFormat, IFieldFormatType } from '../field_format'; -import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; +import { FieldFormat } from '../field_format'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS, IFieldFormatType } from '../types'; export const createCustomFieldFormat = (convert: TextContextTypeConvert): IFieldFormatType => class CustomFieldFormat extends FieldFormat { diff --git a/src/plugins/data/common/field_formats/converters/date_server.ts b/src/plugins/data/common/field_formats/converters/date_server.ts index 34278ea9fe641b..cc7eba966cf0d1 100644 --- a/src/plugins/data/common/field_formats/converters/date_server.ts +++ b/src/plugins/data/common/field_formats/converters/date_server.ts @@ -20,8 +20,13 @@ import { memoize, noop } from 'lodash'; import moment from 'moment-timezone'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; -import { FieldFormat, IFieldFormatMetaParams } from '../field_format'; -import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; +import { FieldFormat } from '../field_format'; +import { + TextContextTypeConvert, + FIELD_FORMAT_IDS, + GetConfigFn, + IFieldFormatMetaParams, +} from '../types'; export class DateFormat extends FieldFormat { static id = FIELD_FORMAT_IDS.DATE; @@ -32,7 +37,7 @@ export class DateFormat extends FieldFormat { private memoizedPattern: string = ''; private timeZone: string = ''; - constructor(params: IFieldFormatMetaParams, getConfig: Function) { + constructor(params: IFieldFormatMetaParams, getConfig: GetConfigFn) { super(params, getConfig); this.memoizedConverter = memoize((val: any) => { diff --git a/src/plugins/data/common/field_formats/converters/string.ts b/src/plugins/data/common/field_formats/converters/string.ts index b2d92cf475a161..1a095d4fd3cfde 100644 --- a/src/plugins/data/common/field_formats/converters/string.ts +++ b/src/plugins/data/common/field_formats/converters/string.ts @@ -18,7 +18,7 @@ */ import { i18n } from '@kbn/i18n'; -import { asPrettyString } from '../index'; +import { asPrettyString } from '../utils'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; diff --git a/src/plugins/data/common/field_formats/converters/url.ts b/src/plugins/data/common/field_formats/converters/url.ts index 21688dd8d11385..7c3e1e1d2cad1d 100644 --- a/src/plugins/data/common/field_formats/converters/url.ts +++ b/src/plugins/data/common/field_formats/converters/url.ts @@ -21,8 +21,13 @@ import { i18n } from '@kbn/i18n'; import { escape, memoize } from 'lodash'; import { getHighlightHtml } from '../utils'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; -import { FieldFormat, IFieldFormatMetaParams } from '../field_format'; -import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; +import { FieldFormat } from '../field_format'; +import { + TextContextTypeConvert, + HtmlContextTypeConvert, + IFieldFormatMetaParams, + FIELD_FORMAT_IDS, +} from '../types'; const templateMatchRE = /{{([\s\S]+?)}}/g; const whitelistUrlSchemes = ['http://', 'https://']; diff --git a/src/plugins/data/common/field_formats/field_format.ts b/src/plugins/data/common/field_formats/field_format.ts index a0621b27f5bc0c..d605dcd2e78ac8 100644 --- a/src/plugins/data/common/field_formats/field_format.ts +++ b/src/plugins/data/common/field_formats/field_format.ts @@ -20,12 +20,14 @@ import { transform, size, cloneDeep, get, defaults } from 'lodash'; import { createCustomFieldFormat } from './converters/custom'; import { + GetConfigFn, ContentType, - FIELD_FORMAT_IDS, + IFieldFormatType, FieldFormatConvert, FieldFormatConvertFunction, HtmlContextTypeOptions, TextContextTypeOptions, + IFieldFormatMetaParams, } from './types'; import { htmlContentTypeSetup, @@ -37,15 +39,6 @@ import { HtmlContextTypeConvert, TextContextTypeConvert } from './types'; const DEFAULT_CONTEXT_TYPE = TEXT_CONTEXT_TYPE; -export interface IFieldFormatMetaParams { - [key: string]: any; - parsedUrl?: { - origin: string; - pathname?: string; - basePath?: string; - }; -} - export abstract class FieldFormat { /** * @property {string} - Field Format Id @@ -97,9 +90,9 @@ export abstract class FieldFormat { public type: any = this.constructor; protected readonly _params: any; - protected getConfig: Function | undefined; + protected getConfig: GetConfigFn | undefined; - constructor(_params: IFieldFormatMetaParams = {}, getConfig?: Function) { + constructor(_params: IFieldFormatMetaParams = {}, getConfig?: GetConfigFn) { this._params = _params; if (getConfig) { @@ -226,13 +219,3 @@ export abstract class FieldFormat { return Boolean(fieldFormat && fieldFormat.convert); } } - -export type IFieldFormat = PublicMethodsOf; -/** - * @string id type is needed for creating custom converters. - */ -export type IFieldFormatId = FIELD_FORMAT_IDS | string; -export type IFieldFormatType = (new (params?: any, getConfig?: Function) => FieldFormat) & { - id: IFieldFormatId; - fieldType: string | string[]; -}; diff --git a/src/plugins/data/common/field_formats/field_formats_registry.test.ts b/src/plugins/data/common/field_formats/field_formats_registry.test.ts new file mode 100644 index 00000000000000..5f6f9fdf897ff3 --- /dev/null +++ b/src/plugins/data/common/field_formats/field_formats_registry.test.ts @@ -0,0 +1,166 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { FieldFormatsRegistry } from './field_formats_registry'; +import { BoolFormat, PercentFormat, StringFormat } from './converters'; +import { GetConfigFn, IFieldFormatType } from './types'; +import { KBN_FIELD_TYPES } from '../../common'; + +const getValueOfPrivateField = (instance: any, field: string) => instance[field]; + +describe('FieldFormatsRegistry', () => { + let fieldFormatsRegistry: FieldFormatsRegistry; + let defaultMap = {}; + const getConfig = (() => defaultMap) as GetConfigFn; + + beforeEach(() => { + fieldFormatsRegistry = new FieldFormatsRegistry(); + fieldFormatsRegistry.init( + getConfig, + { + parsedUrl: { + origin: '', + pathname: '', + basePath: '', + }, + }, + [] + ); + }); + + test('should allows to create an instance of "FieldFormatsRegistry"', () => { + expect(fieldFormatsRegistry).toBeDefined(); + + expect(getValueOfPrivateField(fieldFormatsRegistry, 'fieldFormats')).toBeDefined(); + expect(getValueOfPrivateField(fieldFormatsRegistry, 'defaultMap')).toEqual({}); + }); + + describe('init', () => { + test('should provide an public "init" method', () => { + expect(fieldFormatsRegistry.init).toBeDefined(); + expect(typeof fieldFormatsRegistry.init).toBe('function'); + }); + + test('should populate the "defaultMap" object', () => { + defaultMap = { + number: { id: 'number', params: {} }, + }; + + fieldFormatsRegistry.init(getConfig, {}, []); + expect(getValueOfPrivateField(fieldFormatsRegistry, 'defaultMap')).toEqual(defaultMap); + }); + }); + + describe('register', () => { + test('should provide an public "register" method', () => { + expect(fieldFormatsRegistry.register).toBeDefined(); + expect(typeof fieldFormatsRegistry.register).toBe('function'); + }); + + test('should register field formats', () => { + fieldFormatsRegistry.register([StringFormat, BoolFormat]); + + const registeredFieldFormatters: Map = getValueOfPrivateField( + fieldFormatsRegistry, + 'fieldFormats' + ); + + expect(registeredFieldFormatters.size).toBe(2); + + expect(registeredFieldFormatters.get(BoolFormat.id)).toBe(BoolFormat); + expect(registeredFieldFormatters.get(StringFormat.id)).toBe(StringFormat); + expect(registeredFieldFormatters.get(PercentFormat.id)).toBeUndefined(); + }); + }); + + describe('getType', () => { + test('should provide an public "getType" method', () => { + expect(fieldFormatsRegistry.getType).toBeDefined(); + expect(typeof fieldFormatsRegistry.getType).toBe('function'); + }); + + test('should return the registered type of the field format by identifier', () => { + fieldFormatsRegistry.register([StringFormat]); + + expect(fieldFormatsRegistry.getType(StringFormat.id)).toBeDefined(); + }); + + test('should return void if the field format type has not been registered', () => { + fieldFormatsRegistry.register([BoolFormat]); + + expect(fieldFormatsRegistry.getType(StringFormat.id)).toBeUndefined(); + }); + }); + + describe('fieldFormatMetaParamsDecorator', () => { + test('should set meta params for all instances of FieldFormats', () => { + fieldFormatsRegistry.register([StringFormat]); + + const DecoratedStingFormat = fieldFormatsRegistry.getType(StringFormat.id); + + expect(DecoratedStingFormat).toBeDefined(); + + if (DecoratedStingFormat) { + const stringFormat = new DecoratedStingFormat({ + foo: 'foo', + }); + const params = getValueOfPrivateField(stringFormat, '_params'); + + expect(params).toHaveProperty('foo'); + expect(params).toHaveProperty('parsedUrl'); + expect(params.parsedUrl).toHaveProperty('origin'); + expect(params.parsedUrl).toHaveProperty('pathname'); + expect(params.parsedUrl).toHaveProperty('basePath'); + } + }); + + test('should decorate static fields', () => { + fieldFormatsRegistry.register([BoolFormat]); + + const DecoratedBoolFormat = fieldFormatsRegistry.getType(BoolFormat.id); + + expect(DecoratedBoolFormat).toBeDefined(); + + if (DecoratedBoolFormat) { + expect(DecoratedBoolFormat.id).toBe(BoolFormat.id); + expect(DecoratedBoolFormat.fieldType).toBe(BoolFormat.fieldType); + } + }); + }); + + describe('getByFieldType', () => { + test('should provide an public "getByFieldType" method', () => { + expect(fieldFormatsRegistry.getByFieldType).toBeDefined(); + expect(typeof fieldFormatsRegistry.getByFieldType).toBe('function'); + }); + + test('should decorate returns types', () => { + fieldFormatsRegistry.register([StringFormat, BoolFormat]); + + const [DecoratedStringFormat] = fieldFormatsRegistry.getByFieldType(KBN_FIELD_TYPES.STRING); + + expect(DecoratedStringFormat).toBeDefined(); + + const stingFormat = new DecoratedStringFormat({ foo: 'foo' }); + const params = getValueOfPrivateField(stingFormat, '_params'); + + expect(params).toHaveProperty('foo'); + expect(params).toHaveProperty('parsedUrl'); + }); + }); +}); diff --git a/src/plugins/data/common/field_formats/field_formats_registry.ts b/src/plugins/data/common/field_formats/field_formats_registry.ts new file mode 100644 index 00000000000000..9b85921b820c85 --- /dev/null +++ b/src/plugins/data/common/field_formats/field_formats_registry.ts @@ -0,0 +1,272 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// eslint-disable-next-line max-classes-per-file +import { forOwn, isFunction, memoize } from 'lodash'; + +import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../common'; + +import { + GetConfigFn, + IFieldFormatConfig, + FIELD_FORMAT_IDS, + IFieldFormatType, + IFieldFormatId, + IFieldFormatMetaParams, +} from './types'; +import { baseFormatters } from './constants/base_formatters'; +import { FieldFormat } from './field_format'; + +export class FieldFormatsRegistry { + protected fieldFormats: Map = new Map(); + protected defaultMap: Record = {}; + protected metaParamsOptions: Record = {}; + protected getConfig?: GetConfigFn; + + init( + getConfig: GetConfigFn, + metaParamsOptions: Record = {}, + defaultFieldConverters: IFieldFormatType[] = baseFormatters + ) { + const defaultTypeMap = getConfig('format:defaultTypeMap'); + this.register(defaultFieldConverters); + this.parseDefaultTypeMap(defaultTypeMap); + this.getConfig = getConfig; + this.metaParamsOptions = metaParamsOptions; + } + + /** + * Get the id of the default type for this field type + * using the format:defaultTypeMap config map + * + * @param {KBN_FIELD_TYPES} fieldType - the field type + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {FieldType} + */ + getDefaultConfig = ( + fieldType: KBN_FIELD_TYPES, + esTypes?: ES_FIELD_TYPES[] + ): IFieldFormatConfig => { + const type = this.getDefaultTypeName(fieldType, esTypes); + + return ( + (this.defaultMap && this.defaultMap[type]) || { id: FIELD_FORMAT_IDS.STRING, params: {} } + ); + }; + + /** + * Get a derived FieldFormat class by its id. + * + * @param {IFieldFormatId} formatId - the format id + * @return {FieldFormat | undefined} + */ + getType = (formatId: IFieldFormatId): IFieldFormatType | undefined => { + const fieldFormat = this.fieldFormats.get(formatId); + + if (fieldFormat) { + const decoratedFieldFormat: any = this.fieldFormatMetaParamsDecorator(fieldFormat); + + if (decoratedFieldFormat) { + return decoratedFieldFormat as IFieldFormatType; + } + } + + return undefined; + }; + + /** + * Get the default FieldFormat type (class) for + * a field type, using the format:defaultTypeMap. + * used by the field editor + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {FieldFormat | undefined} + */ + getDefaultType = ( + fieldType: KBN_FIELD_TYPES, + esTypes: ES_FIELD_TYPES[] + ): IFieldFormatType | undefined => { + const config = this.getDefaultConfig(fieldType, esTypes); + + return this.getType(config.id); + }; + + /** + * Get the name of the default type for ES types like date_nanos + * using the format:defaultTypeMap config map + * + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {ES_FIELD_TYPES | undefined} + */ + getTypeNameByEsTypes = (esTypes: ES_FIELD_TYPES[] | undefined): ES_FIELD_TYPES | undefined => { + if (!Array.isArray(esTypes)) { + return undefined; + } + + return esTypes.find(type => this.defaultMap[type] && this.defaultMap[type].es); + }; + + /** + * Get the default FieldFormat type name for + * a field type, using the format:defaultTypeMap. + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {ES_FIELD_TYPES | String} + */ + getDefaultTypeName = ( + fieldType: KBN_FIELD_TYPES, + esTypes?: ES_FIELD_TYPES[] + ): ES_FIELD_TYPES | KBN_FIELD_TYPES => { + const esType = this.getTypeNameByEsTypes(esTypes); + + return esType || fieldType; + }; + + /** + * Get the singleton instance of the FieldFormat type by its id. + * + * @param {IFieldFormatId} formatId + * @return {FIELD_FORMATS_INSTANCES[number]} + */ + getInstance = memoize( + (formatId: IFieldFormatId, params: Record = {}): FieldFormat => { + const ConcreteFieldFormat = this.getType(formatId); + + if (!ConcreteFieldFormat) { + throw new Error(`Field Format '${formatId}' not found!`); + } + + return new ConcreteFieldFormat(params, this.getConfig); + }, + (formatId: IFieldFormatId, params: Record) => + JSON.stringify({ + formatId, + ...params, + }) + ); + + /** + * Get the default fieldFormat instance for a field format. + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {FieldFormat} + */ + getDefaultInstancePlain(fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldFormat { + const conf = this.getDefaultConfig(fieldType, esTypes); + + return this.getInstance(conf.id, conf.params); + } + /** + * Returns a cache key built by the given variables for caching in memoized + * Where esType contains fieldType, fieldType is returned + * -> kibana types have a higher priority in that case + * -> would lead to failing tests that match e.g. date format with/without esTypes + * https://lodash.com/docs#memoize + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {String} + */ + getDefaultInstanceCacheResolver(fieldType: KBN_FIELD_TYPES, esTypes: ES_FIELD_TYPES[]): string { + // @ts-ignore + return Array.isArray(esTypes) && esTypes.indexOf(fieldType) === -1 + ? [fieldType, ...esTypes].join('-') + : fieldType; + } + + /** + * Get filtered list of field formats by format type + * + * @param {KBN_FIELD_TYPES} fieldType + * @return {FieldFormat[]} + */ + getByFieldType(fieldType: KBN_FIELD_TYPES): IFieldFormatType[] { + return [...this.fieldFormats.values()] + .filter((format: IFieldFormatType) => format && format.fieldType.indexOf(fieldType) !== -1) + .map( + (format: IFieldFormatType) => + this.fieldFormatMetaParamsDecorator(format) as IFieldFormatType + ); + } + + /** + * Get the default fieldFormat instance for a field format. + * It's a memoized function that builds and reads a cache + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {FieldFormat} + */ + getDefaultInstance = memoize(this.getDefaultInstancePlain, this.getDefaultInstanceCacheResolver); + + parseDefaultTypeMap(value: any) { + this.defaultMap = value; + forOwn(this, fn => { + if (isFunction(fn) && fn.cache) { + // clear all memoize caches + // @ts-ignore + fn.cache = new memoize.Cache(); + } + }); + } + + register(fieldFormats: IFieldFormatType[]) { + fieldFormats.forEach(fieldFormat => this.fieldFormats.set(fieldFormat.id, fieldFormat)); + } + + /** + * FieldFormat decorator - provide a one way to add meta-params for all field formatters + * + * @private + * @param {IFieldFormatType} fieldFormat - field format type + * @return {FieldFormat | undefined} + */ + private fieldFormatMetaParamsDecorator = ( + fieldFormat: IFieldFormatType + ): IFieldFormatType | undefined => { + const getMetaParams = (customParams: Record) => this.buildMetaParams(customParams); + + if (fieldFormat) { + return class DecoratedFieldFormat extends fieldFormat { + static id = fieldFormat.id; + static fieldType = fieldFormat.fieldType; + + constructor(params: Record = {}, getConfig?: GetConfigFn) { + super(getMetaParams(params), getConfig); + } + }; + } + + return undefined; + }; + + /** + * Build Meta Params + * + * @param {Record} custom params + * @return {Record} + */ + private buildMetaParams = (customParams: T): T => ({ + ...this.metaParamsOptions, + ...customParams, + }); +} diff --git a/src/plugins/data/common/field_formats/index.ts b/src/plugins/data/common/field_formats/index.ts index b1e8744e26745b..e54903375dcf16 100644 --- a/src/plugins/data/common/field_formats/index.ts +++ b/src/plugins/data/common/field_formats/index.ts @@ -17,13 +17,6 @@ * under the License. */ -export { HTML_CONTEXT_TYPE, TEXT_CONTEXT_TYPE } from './content_types'; -export { - FieldFormat, - IFieldFormatType, - IFieldFormatId, - IFieldFormatMetaParams, -} from './field_format'; -export { getHighlightRequest, asPrettyString, getHighlightHtml } from './utils'; -export * from './converters'; -export * from './constants'; +import * as fieldFormats from './static'; + +export { fieldFormats }; diff --git a/src/plugins/data/common/field_formats/static.ts b/src/plugins/data/common/field_formats/static.ts new file mode 100644 index 00000000000000..186a0ff6ede5cb --- /dev/null +++ b/src/plugins/data/common/field_formats/static.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Everything the file exports is public + */ + +export { HTML_CONTEXT_TYPE, TEXT_CONTEXT_TYPE } from './content_types'; +export { FieldFormat } from './field_format'; +export { FieldFormatsRegistry } from './field_formats_registry'; +export { getHighlightRequest, asPrettyString, getHighlightHtml } from './utils'; + +export { baseFormatters } from './constants/base_formatters'; +export { DEFAULT_CONVERTER_COLOR } from './constants/color_default'; + +export { + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + UrlFormat, + StringFormat, + TruncateFormat, +} from './converters'; + +export { + GetConfigFn, + FIELD_FORMAT_IDS, + ContentType, + IFieldFormatConfig, + IFieldFormatType, + IFieldFormat, + IFieldFormatId, +} from './types'; diff --git a/src/plugins/data/common/field_formats/types.ts b/src/plugins/data/common/field_formats/types.ts index dce3c66b0f886b..b6c10c9964f67f 100644 --- a/src/plugins/data/common/field_formats/types.ts +++ b/src/plugins/data/common/field_formats/types.ts @@ -17,11 +17,10 @@ * under the License. */ -/** @public **/ -export type ContentType = 'html' | 'text'; +import { FieldFormat } from './field_format'; /** @public **/ -export { IFieldFormat } from './field_format'; +export type ContentType = 'html' | 'text'; /** @internal **/ export interface HtmlContextTypeOptions { @@ -66,3 +65,32 @@ export enum FIELD_FORMAT_IDS { TRUNCATE = 'truncate', URL = 'url', } + +export interface IFieldFormatConfig { + id: IFieldFormatId; + params: Record; + es?: boolean; +} + +export type GetConfigFn = (key: string, defaultOverride?: T) => T; + +export type IFieldFormat = PublicMethodsOf; + +/** + * @string id type is needed for creating custom converters. + */ +export type IFieldFormatId = FIELD_FORMAT_IDS | string; + +export type IFieldFormatType = (new (params?: any, getConfig?: GetConfigFn) => FieldFormat) & { + id: IFieldFormatId; + fieldType: string | string[]; +}; + +export interface IFieldFormatMetaParams { + [key: string]: any; + parsedUrl?: { + origin: string; + pathname?: string; + basePath?: string; + }; +} diff --git a/src/plugins/data/common/index_patterns/fields/index.ts b/src/plugins/data/common/index_patterns/fields/index.ts index 2b43dffa8c161e..5b6fef3e51fa9b 100644 --- a/src/plugins/data/common/index_patterns/fields/index.ts +++ b/src/plugins/data/common/index_patterns/fields/index.ts @@ -18,4 +18,4 @@ */ export * from './types'; -export { isFilterable } from './utils'; +export { isFilterable, isNestedField } from './utils'; diff --git a/src/plugins/data/common/index_patterns/fields/utils.ts b/src/plugins/data/common/index_patterns/fields/utils.ts index c7bec5e5ad3476..e587c0fe632f11 100644 --- a/src/plugins/data/common/index_patterns/fields/utils.ts +++ b/src/plugins/data/common/index_patterns/fields/utils.ts @@ -28,3 +28,7 @@ export function isFilterable(field: IFieldType): boolean { Boolean(field.searchable && filterableTypes.includes(field.type)) ); } + +export function isNestedField(field: IFieldType): boolean { + return !!field.subType?.nested; +} diff --git a/src/plugins/data/common/types.ts b/src/plugins/data/common/types.ts index bc0d0c323bafa2..be0d3230b3a0e0 100644 --- a/src/plugins/data/common/types.ts +++ b/src/plugins/data/common/types.ts @@ -17,7 +17,6 @@ * under the License. */ -export * from './field_formats/types'; export * from './timefilter/types'; export * from './query/types'; export * from './kbn_field_types/types'; diff --git a/src/plugins/data/public/field_formats/field_formats_service.ts b/src/plugins/data/public/field_formats/field_formats_service.ts new file mode 100644 index 00000000000000..68df0aa2545801 --- /dev/null +++ b/src/plugins/data/public/field_formats/field_formats_service.ts @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup } from 'src/core/public'; +import { fieldFormats } from '../../common/field_formats'; + +export class FieldFormatsService { + private readonly fieldFormatsRegistry: fieldFormats.FieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry(); + + public setup(core: CoreSetup) { + core.uiSettings.getUpdate$().subscribe(({ key, newValue }) => { + if (key === 'format:defaultTypeMap') { + this.fieldFormatsRegistry.parseDefaultTypeMap(newValue); + } + }); + + const getConfig = core.uiSettings.get.bind(core.uiSettings); + + this.fieldFormatsRegistry.init(getConfig, { + parsedUrl: { + origin: window.location.origin, + pathname: window.location.pathname, + basePath: core.http.basePath.get(), + }, + }); + + return this.fieldFormatsRegistry as FieldFormatsSetup; + } + + public start() { + return this.fieldFormatsRegistry as FieldFormatsStart; + } +} + +/** @public */ +export type FieldFormatsSetup = Pick; + +/** @public */ +export type FieldFormatsStart = Omit; diff --git a/src/plugins/data/public/field_formats/index.ts b/src/plugins/data/public/field_formats/index.ts new file mode 100644 index 00000000000000..4550a5781535f2 --- /dev/null +++ b/src/plugins/data/public/field_formats/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats_service'; diff --git a/src/plugins/data/public/field_formats_provider/field_formats.test.ts b/src/plugins/data/public/field_formats_provider/field_formats.test.ts deleted file mode 100644 index 8ad6cff77abc02..00000000000000 --- a/src/plugins/data/public/field_formats_provider/field_formats.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { CoreSetup, IUiSettingsClient } from 'kibana/public'; - -import { FieldFormatRegisty } from './field_formats'; -import { - BoolFormat, - IFieldFormatType, - PercentFormat, - StringFormat, -} from '../../common/field_formats'; -import { coreMock } from '../../../../core/public/mocks'; -import { KBN_FIELD_TYPES } from '../../common'; - -const getValueOfPrivateField = (instance: any, field: string) => instance[field]; -const getUiSettingsMock = (data: any): IUiSettingsClient['get'] => () => data; - -describe('FieldFormatRegisty', () => { - let mockCoreSetup: CoreSetup; - let fieldFormatRegisty: FieldFormatRegisty; - - beforeEach(() => { - mockCoreSetup = coreMock.createSetup(); - fieldFormatRegisty = new FieldFormatRegisty(); - }); - - test('should allows to create an instance of "FieldFormatRegisty"', () => { - expect(fieldFormatRegisty).toBeDefined(); - expect(getValueOfPrivateField(fieldFormatRegisty, 'fieldFormats')).toBeDefined(); - expect(getValueOfPrivateField(fieldFormatRegisty, 'defaultMap')).toEqual({}); - }); - - describe('init', () => { - test('should provide an public "init" method', () => { - expect(fieldFormatRegisty.init).toBeDefined(); - expect(typeof fieldFormatRegisty.init).toBe('function'); - }); - - test('should set basePath value from "init" method', () => { - fieldFormatRegisty.init(mockCoreSetup); - - expect(getValueOfPrivateField(fieldFormatRegisty, 'basePath')).toBe( - mockCoreSetup.http.basePath.get() - ); - }); - - test('should populate the "defaultMap" object', () => { - const defaultMap = { - number: { id: 'number', params: {} }, - }; - - mockCoreSetup.uiSettings.get = getUiSettingsMock(defaultMap); - fieldFormatRegisty.init(mockCoreSetup); - expect(getValueOfPrivateField(fieldFormatRegisty, 'defaultMap')).toEqual(defaultMap); - }); - }); - - describe('register', () => { - test('should provide an public "register" method', () => { - expect(fieldFormatRegisty.register).toBeDefined(); - expect(typeof fieldFormatRegisty.register).toBe('function'); - }); - - test('should register field formats', () => { - fieldFormatRegisty.register([StringFormat, BoolFormat]); - - const registeredFieldFormatters: Map = getValueOfPrivateField( - fieldFormatRegisty, - 'fieldFormats' - ); - - expect(registeredFieldFormatters.size).toBe(2); - - expect(registeredFieldFormatters.get(BoolFormat.id)).toBe(BoolFormat); - expect(registeredFieldFormatters.get(StringFormat.id)).toBe(StringFormat); - expect(registeredFieldFormatters.get(PercentFormat.id)).toBeUndefined(); - }); - }); - - describe('getType', () => { - test('should provide an public "getType" method', () => { - expect(fieldFormatRegisty.getType).toBeDefined(); - expect(typeof fieldFormatRegisty.getType).toBe('function'); - }); - - test('should return the registered type of the field format by identifier', () => { - fieldFormatRegisty.register([StringFormat]); - - expect(fieldFormatRegisty.getType(StringFormat.id)).toBeDefined(); - }); - - test('should return void if the field format type has not been registered', () => { - fieldFormatRegisty.register([BoolFormat]); - - expect(fieldFormatRegisty.getType(StringFormat.id)).toBeUndefined(); - }); - }); - - describe('fieldFormatMetaParamsDecorator', () => { - test('should set meta params for all instances of FieldFormats', () => { - fieldFormatRegisty.register([StringFormat]); - - const DecoratedStingFormat = fieldFormatRegisty.getType(StringFormat.id); - - expect(DecoratedStingFormat).toBeDefined(); - - if (DecoratedStingFormat) { - const stringFormat = new DecoratedStingFormat({ - foo: 'foo', - }); - const params = getValueOfPrivateField(stringFormat, '_params'); - - expect(params).toHaveProperty('foo'); - expect(params).toHaveProperty('parsedUrl'); - expect(params.parsedUrl).toHaveProperty('origin'); - expect(params.parsedUrl).toHaveProperty('pathname'); - expect(params.parsedUrl).toHaveProperty('basePath'); - } - }); - - test('should decorate static fields', () => { - fieldFormatRegisty.register([BoolFormat]); - - const DecoratedBoolFormat = fieldFormatRegisty.getType(BoolFormat.id); - - expect(DecoratedBoolFormat).toBeDefined(); - - if (DecoratedBoolFormat) { - expect(DecoratedBoolFormat.id).toBe(BoolFormat.id); - expect(DecoratedBoolFormat.fieldType).toBe(BoolFormat.fieldType); - } - }); - }); - - describe('getByFieldType', () => { - test('should provide an public "getByFieldType" method', () => { - expect(fieldFormatRegisty.getByFieldType).toBeDefined(); - expect(typeof fieldFormatRegisty.getByFieldType).toBe('function'); - }); - - test('should decorate returns types', () => { - fieldFormatRegisty.register([StringFormat, BoolFormat]); - - const [DecoratedStringFormat] = fieldFormatRegisty.getByFieldType(KBN_FIELD_TYPES.STRING); - - expect(DecoratedStringFormat).toBeDefined(); - - const stingFormat = new DecoratedStringFormat({ foo: 'foo' }); - const params = getValueOfPrivateField(stingFormat, '_params'); - - expect(params).toHaveProperty('foo'); - expect(params).toHaveProperty('parsedUrl'); - }); - }); -}); diff --git a/src/plugins/data/public/field_formats_provider/field_formats.ts b/src/plugins/data/public/field_formats_provider/field_formats.ts deleted file mode 100644 index d3d57d42028cde..00000000000000 --- a/src/plugins/data/public/field_formats_provider/field_formats.ts +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// eslint-disable-next-line max-classes-per-file -import { forOwn, isFunction, memoize } from 'lodash'; -import { IUiSettingsClient, CoreSetup } from 'kibana/public'; -import { - ES_FIELD_TYPES, - KBN_FIELD_TYPES, - FIELD_FORMAT_IDS, - IFieldFormatType, - IFieldFormatId, - FieldFormat, - IFieldFormatMetaParams, -} from '../../common'; -import { FieldType } from './types'; - -export class FieldFormatRegisty { - private fieldFormats: Map; - private uiSettings!: IUiSettingsClient; - private defaultMap: Record; - private basePath?: string; - - constructor() { - this.fieldFormats = new Map(); - this.defaultMap = {}; - } - - getConfig = (key: string, override?: any) => this.uiSettings.get(key, override); - - init({ uiSettings, http }: CoreSetup) { - this.uiSettings = uiSettings; - this.basePath = http.basePath.get(); - - this.parseDefaultTypeMap(this.uiSettings.get('format:defaultTypeMap')); - - this.uiSettings.getUpdate$().subscribe(({ key, newValue }) => { - if (key === 'format:defaultTypeMap') { - this.parseDefaultTypeMap(newValue); - } - }); - } - - /** - * Get the id of the default type for this field type - * using the format:defaultTypeMap config map - * - * @param {KBN_FIELD_TYPES} fieldType - the field type - * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types - * @return {FieldType} - */ - getDefaultConfig = (fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldType => { - const type = this.getDefaultTypeName(fieldType, esTypes); - - return ( - (this.defaultMap && this.defaultMap[type]) || { id: FIELD_FORMAT_IDS.STRING, params: {} } - ); - }; - - /** - * Get a derived FieldFormat class by its id. - * - * @param {IFieldFormatId} formatId - the format id - * @return {FieldFormat | undefined} - */ - getType = (formatId: IFieldFormatId): IFieldFormatType | undefined => { - const fieldFormat = this.fieldFormats.get(formatId); - - if (fieldFormat) { - const decoratedFieldFormat: any = this.fieldFormatMetaParamsDecorator(fieldFormat); - - if (decoratedFieldFormat) { - return decoratedFieldFormat as IFieldFormatType; - } - } - - return undefined; - }; - - /** - * Get the default FieldFormat type (class) for - * a field type, using the format:defaultTypeMap. - * used by the field editor - * - * @param {KBN_FIELD_TYPES} fieldType - * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types - * @return {FieldFormat | undefined} - */ - getDefaultType = ( - fieldType: KBN_FIELD_TYPES, - esTypes: ES_FIELD_TYPES[] - ): IFieldFormatType | undefined => { - const config = this.getDefaultConfig(fieldType, esTypes); - - return this.getType(config.id); - }; - - /** - * Get the name of the default type for ES types like date_nanos - * using the format:defaultTypeMap config map - * - * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types - * @return {ES_FIELD_TYPES | undefined} - */ - getTypeNameByEsTypes = (esTypes: ES_FIELD_TYPES[] | undefined): ES_FIELD_TYPES | undefined => { - if (!Array.isArray(esTypes)) { - return undefined; - } - - return esTypes.find(type => this.defaultMap[type] && this.defaultMap[type].es); - }; - - /** - * Get the default FieldFormat type name for - * a field type, using the format:defaultTypeMap. - * - * @param {KBN_FIELD_TYPES} fieldType - * @param {ES_FIELD_TYPES[]} esTypes - * @return {ES_FIELD_TYPES | String} - */ - getDefaultTypeName = ( - fieldType: KBN_FIELD_TYPES, - esTypes?: ES_FIELD_TYPES[] - ): ES_FIELD_TYPES | KBN_FIELD_TYPES => { - const esType = this.getTypeNameByEsTypes(esTypes); - - return esType || fieldType; - }; - - /** - * Get the singleton instance of the FieldFormat type by its id. - * - * @param {IFieldFormatId} formatId - * @return {FIELD_FORMATS_INSTANCES[number]} - */ - getInstance = memoize( - (formatId: IFieldFormatId, params: Record = {}): FieldFormat => { - const DerivedFieldFormat = this.getType(formatId); - - if (!DerivedFieldFormat) { - throw new Error(`Field Format '${formatId}' not found!`); - } - - return new DerivedFieldFormat(params, this.getConfig); - } - ); - - /** - * Get the default fieldFormat instance for a field format. - * - * @param {KBN_FIELD_TYPES} fieldType - * @param {ES_FIELD_TYPES[]} esTypes - * @return {FieldFormat} - */ - getDefaultInstancePlain(fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldFormat { - const conf = this.getDefaultConfig(fieldType, esTypes); - - const DerivedFieldFormat = this.getType(conf.id); - - if (!DerivedFieldFormat) { - throw new Error(`Field Format '${conf.id}' not found!`); - } - - return new DerivedFieldFormat(conf.params, this.getConfig); - } - /** - * Returns a cache key built by the given variables for caching in memoized - * Where esType contains fieldType, fieldType is returned - * -> kibana types have a higher priority in that case - * -> would lead to failing tests that match e.g. date format with/without esTypes - * https://lodash.com/docs#memoize - * - * @param {KBN_FIELD_TYPES} fieldType - * @param {ES_FIELD_TYPES[]} esTypes - * @return {String} - */ - getDefaultInstanceCacheResolver(fieldType: KBN_FIELD_TYPES, esTypes: ES_FIELD_TYPES[]): string { - // @ts-ignore - return Array.isArray(esTypes) && esTypes.indexOf(fieldType) === -1 - ? [fieldType, ...esTypes].join('-') - : fieldType; - } - - /** - * Get filtered list of field formats by format type - * - * @param {KBN_FIELD_TYPES} fieldType - * @return {FieldFormat[]} - */ - getByFieldType(fieldType: KBN_FIELD_TYPES): IFieldFormatType[] { - return [...this.fieldFormats.values()] - .filter((format: IFieldFormatType) => format && format.fieldType.indexOf(fieldType) !== -1) - .map( - (format: IFieldFormatType) => - this.fieldFormatMetaParamsDecorator(format) as IFieldFormatType - ); - } - - /** - * Get the default fieldFormat instance for a field format. - * It's a memoized function that builds and reads a cache - * - * @param {KBN_FIELD_TYPES} fieldType - * @param {ES_FIELD_TYPES[]} esTypes - * @return {FieldFormat} - */ - getDefaultInstance = memoize(this.getDefaultInstancePlain, this.getDefaultInstanceCacheResolver); - - parseDefaultTypeMap(value: any) { - this.defaultMap = value; - forOwn(this, fn => { - if (isFunction(fn) && fn.cache) { - // clear all memoize caches - // @ts-ignore - fn.cache = new memoize.Cache(); - } - }); - } - - register = (fieldFormats: IFieldFormatType[]) => { - fieldFormats.forEach(fieldFormat => this.fieldFormats.set(fieldFormat.id, fieldFormat)); - - return this; - }; - - /** - * FieldFormat decorator - provide a one way to add meta-params for all field formatters - * - * @private - * @param {IFieldFormatType} fieldFormat - field format type - * @return {FieldFormat | undefined} - */ - private fieldFormatMetaParamsDecorator = ( - fieldFormat: IFieldFormatType - ): IFieldFormatType | undefined => { - const getMetaParams = (customParams: Record) => this.buildMetaParams(customParams); - - if (fieldFormat) { - return class DecoratedFieldFormat extends fieldFormat { - static id = fieldFormat.id; - static fieldType = fieldFormat.fieldType; - - constructor(params: Record = {}, getConfig?: Function) { - super(getMetaParams(params), getConfig); - } - }; - } - - return undefined; - }; - - /** - * Build Meta Params - * - * @static - * @param {Record} custom params - * @return {Record} - */ - private buildMetaParams = (customParams: T): T => ({ - parsedUrl: { - origin: window.location.origin, - pathname: window.location.pathname, - basePath: this.basePath, - }, - ...customParams, - }); -} diff --git a/src/plugins/data/public/field_formats_provider/field_formats_service.ts b/src/plugins/data/public/field_formats_provider/field_formats_service.ts deleted file mode 100644 index 42abeecc6fda00..00000000000000 --- a/src/plugins/data/public/field_formats_provider/field_formats_service.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { CoreSetup } from 'src/core/public'; -import { FieldFormatRegisty } from './field_formats'; - -import { - BoolFormat, - BytesFormat, - ColorFormat, - DateFormat, - DateNanosFormat, - DurationFormat, - IpFormat, - NumberFormat, - PercentFormat, - RelativeDateFormat, - SourceFormat, - StaticLookupFormat, - StringFormat, - TruncateFormat, - UrlFormat, -} from '../../common/'; - -export class FieldFormatsService { - private readonly fieldFormats: FieldFormatRegisty = new FieldFormatRegisty(); - - public setup(core: CoreSetup) { - this.fieldFormats.init(core); - - this.fieldFormats.register([ - BoolFormat, - BytesFormat, - ColorFormat, - DateFormat, - DateNanosFormat, - DurationFormat, - IpFormat, - NumberFormat, - PercentFormat, - RelativeDateFormat, - SourceFormat, - StaticLookupFormat, - StringFormat, - TruncateFormat, - UrlFormat, - ]); - - return this.fieldFormats as FieldFormatsSetup; - } - - public start() { - return this.fieldFormats as FieldFormatsStart; - } - - public stop() { - // nothing to do here yet - } -} - -/** @public */ -export type FieldFormatsSetup = Omit; -export type FieldFormatsStart = Omit; diff --git a/src/plugins/data/public/field_formats_provider/index.ts b/src/plugins/data/public/field_formats_provider/index.ts deleted file mode 100644 index 442d877c5316a7..00000000000000 --- a/src/plugins/data/public/field_formats_provider/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { FieldFormatRegisty } from './field_formats'; // TODO: Try to remove -export { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats_service'; diff --git a/src/plugins/data/public/field_formats_provider/types.ts b/src/plugins/data/public/field_formats_provider/types.ts deleted file mode 100644 index fc33bf4d38f850..00000000000000 --- a/src/plugins/data/public/field_formats_provider/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IFieldFormatId } from '../../common'; - -export interface FieldType { - id: IFieldFormatId; - params: Record; - es?: boolean; -} diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 19ba246ce02dd2..bc25c64f0e96e5 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -31,12 +31,6 @@ export function plugin(initializerContext: PluginInitializerContext) { export { IRequestTypesMap, IResponseTypesMap } from './search'; export * from './types'; export { - // field formats - ContentType, // only used in agg_type - FIELD_FORMAT_IDS, - IFieldFormat, - IFieldFormatId, - IFieldFormatType, // index patterns IIndexPattern, IFieldType, @@ -51,7 +45,7 @@ export { TimeRange, } from '../common'; -export * from './field_formats_provider'; +export * from './field_formats'; export * from './index_patterns'; export * from './search'; export * from './query'; @@ -61,26 +55,7 @@ export { esFilters, esKuery, esQuery, - // field formats - BoolFormat, - BytesFormat, - ColorFormat, - DateFormat, - DateNanosFormat, - DEFAULT_CONVERTER_COLOR, - DurationFormat, - FieldFormat, - getHighlightRequest, // only used in search source - IpFormat, - NumberFormat, - PercentFormat, - RelativeDateFormat, - SourceFormat, - StaticLookupFormat, - StringFormat, - TEXT_CONTEXT_TYPE, // only used in agg_types - TruncateFormat, - UrlFormat, + fieldFormats, // index patterns isFilterable, // kbn field types @@ -89,6 +64,7 @@ export { getKbnTypeNames, // utils parseInterval, + isNestedField, } from '../common'; // Export plugin after all other imports diff --git a/src/plugins/data/public/index_patterns/fields/field.ts b/src/plugins/data/public/index_patterns/fields/field.ts index 6ed3c2be8f96e4..730a2f88c5eb72 100644 --- a/src/plugins/data/public/index_patterns/fields/field.ts +++ b/src/plugins/data/public/index_patterns/fields/field.ts @@ -26,7 +26,7 @@ import { IFieldType, getKbnFieldType, IFieldSubType, - FieldFormat, + fieldFormats, shortenDottedString, } from '../../../common'; @@ -95,12 +95,12 @@ export class Field implements IFieldType { let format = spec.format; - if (!FieldFormat.isInstanceOfFieldFormat(format)) { - const fieldFormats = getFieldFormats(); + if (!fieldFormats.FieldFormat.isInstanceOfFieldFormat(format)) { + const fieldFormatsService = getFieldFormats(); format = indexPattern.fieldFormatMap[spec.name] || - fieldFormats.getDefaultInstance(spec.type, spec.esTypes); + fieldFormatsService.getDefaultInstance(spec.type, spec.esTypes); } const indexed = !!spec.indexed; diff --git a/src/plugins/data/public/index_patterns/index.ts b/src/plugins/data/public/index_patterns/index.ts index 6f4821c3917212..7444126ee6cae0 100644 --- a/src/plugins/data/public/index_patterns/index.ts +++ b/src/plugins/data/public/index_patterns/index.ts @@ -25,6 +25,7 @@ import { IndexPatternMissingIndices, validateIndexPattern, getFromSavedObject, + isDefault, } from './lib'; import { getRoutes } from './utils'; import { flattenHitWrapper, formatHitProvider } from './index_patterns'; @@ -40,6 +41,7 @@ export const indexPatterns = { getFromSavedObject, flattenHitWrapper, formatHitProvider, + isDefault, }; export { Field, FieldList, IFieldList } from './fields'; diff --git a/src/plugins/data/public/index_patterns/index_patterns/format_hit.ts b/src/plugins/data/public/index_patterns/index_patterns/format_hit.ts index 59ee18b3dcb509..f9e15c8650ce0b 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/format_hit.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/format_hit.ts @@ -19,7 +19,7 @@ import _ from 'lodash'; import { IndexPattern } from './index_pattern'; -import { ContentType } from '../../../common'; +import { fieldFormats } from '../../../common'; const formattedCache = new WeakMap(); const partialFormattedCache = new WeakMap(); @@ -31,7 +31,7 @@ export function formatHitProvider(indexPattern: IndexPattern, defaultFormat: any hit: Record, val: any, fieldName: string, - type: ContentType = 'html' + type: fieldFormats.ContentType = 'html' ) { const field = indexPattern.fields.getByName(fieldName); const format = field ? field.format : defaultFormat; diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts index 1f83e4bd5b80c6..059df6d4eb0f89 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts @@ -31,7 +31,7 @@ import { setNotifications, setFieldFormats } from '../../services'; // Temporary disable eslint, will be removed after moving to new platform folder // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { notificationServiceMock } from '../../../../../core/public/notifications/notifications_service.mock'; -import { FieldFormatRegisty } from '../../field_formats_provider'; +import { fieldFormats } from '../../../common/field_formats'; jest.mock('../../../../kibana_utils/public', () => { const originalModule = jest.requireActual('../../../../kibana_utils/public'); @@ -125,7 +125,7 @@ describe('IndexPattern', () => { setNotifications(notifications); setFieldFormats(({ getDefaultInstance: jest.fn(), - } as unknown) as FieldFormatRegisty); + } as unknown) as fieldFormats.FieldFormatsRegistry); return create(indexPatternId).then((pattern: IndexPattern) => { indexPattern = pattern; diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts index e3482dd4830357..5c09e22b6dbb4f 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts @@ -492,10 +492,13 @@ export class IndexPattern implements IIndexPattern { toasts.addError(err, { title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { - defaultMessage: 'Error fetching fields', + defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})', + values: { + id: this.id, + title: this.title, + }, }), }); - throw err; }); } diff --git a/src/plugins/data/public/index_patterns/lib/index.ts b/src/plugins/data/public/index_patterns/lib/index.ts index c878eb91154277..2893096c4af9d4 100644 --- a/src/plugins/data/public/index_patterns/lib/index.ts +++ b/src/plugins/data/public/index_patterns/lib/index.ts @@ -22,3 +22,4 @@ export * from './types'; export { validateIndexPattern } from './validate_index_pattern'; export { IndexPatternMissingIndices } from './errors'; export { getFromSavedObject } from './get_from_saved_object'; +export { isDefault } from './is_default'; diff --git a/src/plugins/data/public/index_patterns/lib/is_default.ts b/src/plugins/data/public/index_patterns/lib/is_default.ts new file mode 100644 index 00000000000000..f6aec82af89d5b --- /dev/null +++ b/src/plugins/data/public/index_patterns/lib/is_default.ts @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IIndexPattern } from '../..'; + +export const isDefault = (indexPattern: IIndexPattern) => { + // Default index patterns don't have `type` defined. + return !indexPattern.type; +}; diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 08a7a3ef11537b..847d79fdc87d1f 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -17,11 +17,11 @@ * under the License. */ import { - FieldFormatRegisty, Plugin, FieldFormatsStart, FieldFormatsSetup, IndexPatternsContract, + fieldFormats, } from '.'; import { searchSetupMock } from './search/mocks'; import { queryServiceMock } from './query/mocks'; @@ -35,9 +35,8 @@ const autocompleteMock: any = { hasQuerySuggestions: jest.fn(), }; -const fieldFormatsMock: PublicMethodsOf = { +const fieldFormatsMock: PublicMethodsOf = { getByFieldType: jest.fn(), - getConfig: jest.fn(), getDefaultConfig: jest.fn(), getDefaultInstance: jest.fn() as any, getDefaultInstanceCacheResolver: jest.fn(), @@ -59,6 +58,12 @@ const createSetupContract = (): Setup => { search: searchSetupMock, fieldFormats: fieldFormatsMock as FieldFormatsSetup, query: querySetupMock, + __LEGACY: { + esClient: { + search: jest.fn(), + msearch: jest.fn(), + }, + }, }; return setupContract; @@ -69,13 +74,28 @@ const createStartContract = (): Start => { const startContract = { autocomplete: autocompleteMock, getSuggestions: jest.fn(), - search: { search: jest.fn() }, + search: { + search: jest.fn(), + + __LEGACY: { + esClient: { + search: jest.fn(), + msearch: jest.fn(), + }, + }, + }, fieldFormats: fieldFormatsMock as FieldFormatsStart, query: queryStartMock, ui: { IndexPatternSelect: jest.fn(), SearchBar: jest.fn(), }, + __LEGACY: { + esClient: { + search: jest.fn(), + msearch: jest.fn(), + }, + }, indexPatterns: {} as IndexPatternsContract, }; return startContract; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 78abcbcfec467f..8a45d9fc2f23be 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -17,7 +17,13 @@ * under the License. */ -import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import { + PluginInitializerContext, + CoreSetup, + CoreStart, + Plugin, + PackageInfo, +} from 'src/core/public'; import { Storage, IStorageWrapper } from '../../kibana_utils/public'; import { DataPublicPluginSetup, @@ -27,11 +33,17 @@ import { } from './types'; import { AutocompleteService } from './autocomplete'; import { SearchService } from './search/search_service'; -import { FieldFormatsService } from './field_formats_provider'; +import { FieldFormatsService } from './field_formats'; import { QueryService } from './query'; import { createIndexPatternSelect } from './ui/index_pattern_select'; import { IndexPatterns } from './index_patterns'; -import { setNotifications, setFieldFormats, setOverlays, setIndexPatterns } from './services'; +import { + setNotifications, + setFieldFormats, + setOverlays, + setIndexPatterns, + setUiSettings, +} from './services'; import { createFilterAction, GLOBAL_APPLY_FILTER_ACTION } from './actions'; import { APPLY_FILTER_TRIGGER } from '../../embeddable/public'; import { createSearchBar } from './ui/search_bar/create_search_bar'; @@ -42,12 +54,14 @@ export class DataPublicPlugin implements Plugin { expect(fetchStub).toBeCalledTimes(0); expect(updateStub).toBeCalledTimes(1); }); + + test('should merge multiple conflicting app filters', async function() { + filterManager.addFilters(readyFilters, true); + const appFilter1 = _.cloneDeep(readyFilters[1]); + appFilter1.meta.negate = true; + appFilter1.$state = { + store: esFilters.FilterStateStore.APP_STATE, + }; + const appFilter2 = _.cloneDeep(readyFilters[2]); + appFilter2.meta.negate = true; + appFilter2.$state = { + store: esFilters.FilterStateStore.APP_STATE, + }; + + const globalFilters = filterManager.getFilters(); + filterManager.setFilters([...globalFilters, appFilter1, appFilter2]); + + // global filters are taking precedence over same app filters when setting + const res = filterManager.getFilters(); + expect(res).toHaveLength(3); + expect( + res.filter(function(filter) { + return filter.$state && filter.$state.store === esFilters.FilterStateStore.GLOBAL_STATE; + }).length + ).toBe(3); + }); + + test('should set app filters and remove any duplicated global filters', async function() { + filterManager.addFilters(readyFilters, true); + const appFilter1 = _.cloneDeep(readyFilters[1]); + const appFilter2 = _.cloneDeep(readyFilters[2]); + + filterManager.setAppFilters([appFilter1, appFilter2]); + + const newGlobalFilters = filterManager.getGlobalFilters(); + const newAppFilters = filterManager.getAppFilters(); + + expect(newGlobalFilters).toHaveLength(1); + expect(newAppFilters).toHaveLength(2); + }); + + test('should set global filters and remove any duplicated app filters', async function() { + filterManager.addFilters(readyFilters, false); + const globalFilter1 = _.cloneDeep(readyFilters[1]); + const globalFilter2 = _.cloneDeep(readyFilters[2]); + + filterManager.setGlobalFilters([globalFilter1, globalFilter2]); + + const newGlobalFilters = filterManager.getGlobalFilters(); + const newAppFilters = filterManager.getAppFilters(); + + expect(newGlobalFilters).toHaveLength(2); + expect(newAppFilters).toHaveLength(1); + }); }); describe('add filters', () => { diff --git a/src/plugins/data/public/query/filter_manager/filter_manager.ts b/src/plugins/data/public/query/filter_manager/filter_manager.ts index f7d0dddd5bf039..6c5cdbaffce5ea 100644 --- a/src/plugins/data/public/query/filter_manager/filter_manager.ts +++ b/src/plugins/data/public/query/filter_manager/filter_manager.ts @@ -22,7 +22,7 @@ import { Subject } from 'rxjs'; import { IUiSettingsClient } from 'src/core/public'; -import { compareFilters, COMPARE_ALL_OPTIONS } from './lib/compare_filters'; +import { COMPARE_ALL_OPTIONS, compareFilters } from './lib/compare_filters'; import { sortFilters } from './lib/sort_filters'; import { mapAndFlattenFilters } from './lib/map_and_flatten_filters'; import { uniqFilters } from './lib/uniq_filters'; @@ -45,20 +45,23 @@ export class FilterManager { const appFilters = partitionedFilters.appFilters; // existing globalFilters should be mutated by appFilters + // ignore original appFilters which are already inside globalFilters + const cleanedAppFilters: esFilters.Filter[] = []; _.each(appFilters, function(filter, i) { const match = _.find(globalFilters, function(globalFilter) { return compareFilters(globalFilter, filter); }); - // no match, do nothing - if (!match) return; + // no match, do continue with app filter + if (!match) { + return cleanedAppFilters.push(filter); + } - // matching filter in globalState, update global and remove from appState + // matching filter in globalState, update global and don't add from appState _.assign(match.meta, filter.meta); - appFilters.splice(i, 1); }); - return FilterManager.mergeFilters(appFilters, globalFilters); + return FilterManager.mergeFilters(cleanedAppFilters, globalFilters); } private static mergeFilters( @@ -161,6 +164,48 @@ export class FilterManager { this.handleStateUpdate(mergedFilters); } + /** + * Sets new global filters and leaves app filters untouched, + * Removes app filters for which there is a duplicate within new global filters + * @param newGlobalFilters + */ + public setGlobalFilters(newGlobalFilters: esFilters.Filter[]) { + newGlobalFilters = mapAndFlattenFilters(newGlobalFilters); + FilterManager.setFiltersStore(newGlobalFilters, esFilters.FilterStateStore.GLOBAL_STATE, true); + const { appFilters: currentAppFilters } = this.getPartitionedFilters(); + // remove duplicates from current app filters, to make sure global will take precedence + const filteredAppFilters = currentAppFilters.filter( + appFilter => !newGlobalFilters.find(globalFilter => compareFilters(globalFilter, appFilter)) + ); + const newFilters = this.mergeIncomingFilters({ + appFilters: filteredAppFilters, + globalFilters: newGlobalFilters, + }); + + this.handleStateUpdate(newFilters); + } + + /** + * Sets new app filters and leaves global filters untouched, + * Removes app filters for which there is a duplicate within new global filters + * @param newAppFilters + */ + public setAppFilters(newAppFilters: esFilters.Filter[]) { + newAppFilters = mapAndFlattenFilters(newAppFilters); + FilterManager.setFiltersStore(newAppFilters, esFilters.FilterStateStore.APP_STATE, true); + const { globalFilters: currentGlobalFilters } = this.getPartitionedFilters(); + // remove duplicates from current global filters, to make sure app will take precedence + const filteredGlobalFilters = currentGlobalFilters.filter( + globalFilter => !newAppFilters.find(appFilter => compareFilters(appFilter, globalFilter)) + ); + + const newFilters = this.mergeIncomingFilters({ + globalFilters: filteredGlobalFilters, + appFilters: newAppFilters, + }); + this.handleStateUpdate(newFilters); + } + public removeFilter(filter: esFilters.Filter) { const filterIndex = _.findIndex(this.filters, item => { return _.isEqual(item.meta, filter.meta) && _.isEqual(item.query, filter.query); @@ -177,10 +222,15 @@ export class FilterManager { this.setFilters([]); } - public static setFiltersStore(filters: esFilters.Filter[], store: esFilters.FilterStateStore) { + public static setFiltersStore( + filters: esFilters.Filter[], + store: esFilters.FilterStateStore, + shouldOverrideStore = false + ) { _.map(filters, (filter: esFilters.Filter) => { // Override status only for filters that didn't have state in the first place. - if (filter.$state === undefined) { + // or if shouldOverrideStore is explicitly true + if (shouldOverrideStore || filter.$state === undefined) { filter.$state = { store }; } }); diff --git a/src/plugins/data/public/query/filter_manager/index.ts b/src/plugins/data/public/query/filter_manager/index.ts index ce7a479151797c..09990adacde458 100644 --- a/src/plugins/data/public/query/filter_manager/index.ts +++ b/src/plugins/data/public/query/filter_manager/index.ts @@ -23,3 +23,4 @@ export { uniqFilters } from './lib/uniq_filters'; export { mapAndFlattenFilters } from './lib/map_and_flatten_filters'; export { onlyDisabledFiltersChanged } from './lib/only_disabled'; export { generateFilters } from './lib/generate_filters'; +export { compareFilters, COMPARE_ALL_OPTIONS } from './lib/compare_filters'; diff --git a/src/plugins/data/public/query/index.tsx b/src/plugins/data/public/query/index.tsx index dd3d11b4ac25c0..35e58575d8870f 100644 --- a/src/plugins/data/public/query/index.tsx +++ b/src/plugins/data/public/query/index.tsx @@ -24,3 +24,4 @@ export * from './filter_manager'; export * from './timefilter'; export * from './saved_query'; export * from './persisted_log'; +export * from './state_sync'; diff --git a/src/plugins/data/public/query/state_sync/index.ts b/src/plugins/data/public/query/state_sync/index.ts new file mode 100644 index 00000000000000..7eefda0d0aec1e --- /dev/null +++ b/src/plugins/data/public/query/state_sync/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { syncQuery } from './sync_query'; +export { syncAppFilters } from './sync_app_filters'; diff --git a/src/plugins/data/public/query/state_sync/sync_app_filters.test.ts b/src/plugins/data/public/query/state_sync/sync_app_filters.test.ts new file mode 100644 index 00000000000000..61270ecc099794 --- /dev/null +++ b/src/plugins/data/public/query/state_sync/sync_app_filters.test.ts @@ -0,0 +1,197 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subscription } from 'rxjs'; +import { FilterManager } from '../filter_manager'; +import { getFilter } from '../filter_manager/test_helpers/get_stub_filter'; +import { esFilters } from '../../../common'; +import { syncAppFilters } from './sync_app_filters'; +import { coreMock } from '../../../../../core/public/mocks'; +import { BaseStateContainer, createStateContainer } from '../../../../kibana_utils/public'; + +const setupMock = coreMock.createSetup(); + +setupMock.uiSettings.get.mockImplementation((key: string) => { + return true; +}); + +describe('sync_app_filters', () => { + let filterManager: FilterManager; + let appState: BaseStateContainer; + let appStateSub: Subscription; + let appStateChangeTriggered = jest.fn(); + let filterManagerChangeSub: Subscription; + let filterManagerChangeTriggered = jest.fn(); + + let gF1: esFilters.Filter; + let gF2: esFilters.Filter; + let aF1: esFilters.Filter; + let aF2: esFilters.Filter; + + beforeEach(() => { + filterManager = new FilterManager(setupMock.uiSettings); + appState = createStateContainer([] as esFilters.Filter[]); + appStateChangeTriggered = jest.fn(); + appStateSub = appState.state$.subscribe(appStateChangeTriggered); + + filterManagerChangeTriggered = jest.fn(); + filterManagerChangeSub = filterManager.getUpdates$().subscribe(filterManagerChangeTriggered); + + gF1 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, true, true, 'key1', 'value1'); + gF2 = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, false, false, 'key2', 'value2'); + aF1 = getFilter(esFilters.FilterStateStore.APP_STATE, true, true, 'key3', 'value3'); + aF2 = getFilter(esFilters.FilterStateStore.APP_STATE, false, false, 'key4', 'value4'); + }); + afterEach(() => { + appStateSub.unsubscribe(); + filterManagerChangeSub.unsubscribe(); + }); + + describe('sync from filterManager to app state', () => { + test('should sync app filters to app state when new app filters set to filterManager', () => { + const stop = syncAppFilters(filterManager, appState); + + filterManager.setFilters([gF1, aF1]); + + expect(appState.get()).toHaveLength(1); + stop(); + }); + + test('should not sync global filters to app state ', () => { + const stop = syncAppFilters(filterManager, appState); + + filterManager.setFilters([gF1, gF2]); + + expect(appState.get()).toHaveLength(0); + stop(); + }); + + test("should not trigger changes when app filters didn't change", () => { + const stop = syncAppFilters(filterManager, appState); + + filterManager.setFilters([gF1, aF1]); + + filterManager.setFilters([gF2, aF1]); + + expect(appStateChangeTriggered).toBeCalledTimes(1); + expect(appState.get()).toHaveLength(1); + + stop(); + }); + + test('should trigger changes when app filters change', () => { + const stop = syncAppFilters(filterManager, appState); + + filterManager.setFilters([gF1, aF1]); + filterManager.setFilters([gF1, aF2]); + + expect(appStateChangeTriggered).toBeCalledTimes(2); + expect(appState.get()).toHaveLength(1); + + stop(); + }); + + test('resetting filters should sync to app state', () => { + const stop = syncAppFilters(filterManager, appState); + + filterManager.setFilters([gF1, aF1]); + + expect(appState.get()).toHaveLength(1); + + filterManager.removeAll(); + + expect(appState.get()).toHaveLength(0); + + stop(); + }); + + test("shouldn't sync filters when syncing is stopped", () => { + const stop = syncAppFilters(filterManager, appState); + + filterManager.setFilters([gF1, aF1]); + + expect(appState.get()).toHaveLength(1); + + stop(); + + filterManager.removeAll(); + + expect(appState.get()).toHaveLength(1); + }); + }); + describe('sync from app state to filterManager', () => { + test('should pick up initial state from app state', () => { + appState.set([aF1]); + filterManager.setFilters([gF1]); + + const stop = syncAppFilters(filterManager, appState); + expect(filterManager.getFilters()).toHaveLength(2); + expect(appStateChangeTriggered).toBeCalledTimes(1); + + stop(); + }); + + test('changes to app state should be synced to app filters', () => { + filterManager.setFilters([gF1]); + const stop = syncAppFilters(filterManager, appState); + + appState.set([aF1]); + + expect(filterManager.getFilters()).toHaveLength(2); + expect(filterManager.getAppFilters()).toHaveLength(1); + expect(filterManager.getGlobalFilters()).toHaveLength(1); + expect(appStateChangeTriggered).toBeCalledTimes(1); + stop(); + }); + + test('global filters should remain untouched', () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + const stop = syncAppFilters(filterManager, appState); + + appState.set([]); + + expect(filterManager.getFilters()).toHaveLength(2); + expect(filterManager.getGlobalFilters()).toHaveLength(2); + expect(appStateChangeTriggered).toBeCalledTimes(1); + stop(); + }); + + test("if filters are not changed, filterManager shouldn't trigger update", () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + filterManagerChangeTriggered.mockClear(); + + appState.set([aF1, aF2]); + const stop = syncAppFilters(filterManager, appState); + appState.set([aF1, aF2]); + + expect(filterManagerChangeTriggered).toBeCalledTimes(0); + stop(); + }); + + test('stop() should stop syncing', () => { + filterManager.setFilters([gF1, gF2, aF1, aF2]); + const stop = syncAppFilters(filterManager, appState); + appState.set([]); + expect(filterManager.getFilters()).toHaveLength(2); + stop(); + appState.set([aF1]); + expect(filterManager.getFilters()).toHaveLength(2); + }); + }); +}); diff --git a/src/plugins/data/public/query/state_sync/sync_app_filters.ts b/src/plugins/data/public/query/state_sync/sync_app_filters.ts new file mode 100644 index 00000000000000..7954729cd86651 --- /dev/null +++ b/src/plugins/data/public/query/state_sync/sync_app_filters.ts @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _ from 'lodash'; +import { filter, map } from 'rxjs/operators'; +import { COMPARE_ALL_OPTIONS, compareFilters } from '../filter_manager/lib/compare_filters'; +import { esFilters } from '../../../common'; +import { FilterManager } from '../filter_manager'; +import { BaseStateContainer } from '../../../../../plugins/kibana_utils/public'; + +/** + * Helper utility to sync application's state filters, with filter manager + * @param filterManager + * @param appState + */ +export function syncAppFilters( + filterManager: FilterManager, + appState: BaseStateContainer +) { + // make sure initial app filters are picked by filterManager + filterManager.setAppFilters(_.cloneDeep(appState.get())); + + const subs = [ + filterManager + .getUpdates$() + .pipe( + map(() => filterManager.getAppFilters()), + filter( + // continue only if app state filters updated + appFilters => !compareFilters(appFilters, appState.get(), COMPARE_ALL_OPTIONS) + ) + ) + .subscribe(appFilters => { + appState.set(appFilters); + }), + + // if appFilters in dashboardStateManager changed (e.g browser history update), + // sync it to filterManager + appState.state$.subscribe(() => { + if (!compareFilters(appState.get(), filterManager.getAppFilters(), COMPARE_ALL_OPTIONS)) { + filterManager.setAppFilters(_.cloneDeep(appState.get())); + } + }), + ]; + + return () => { + subs.forEach(s => s.unsubscribe()); + }; +} diff --git a/src/plugins/data/public/query/state_sync/sync_query.test.ts b/src/plugins/data/public/query/state_sync/sync_query.test.ts new file mode 100644 index 00000000000000..0973af13cacd51 --- /dev/null +++ b/src/plugins/data/public/query/state_sync/sync_query.test.ts @@ -0,0 +1,166 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subscription } from 'rxjs'; +import { createBrowserHistory, History } from 'history'; +import { FilterManager } from '../filter_manager'; +import { getFilter } from '../filter_manager/test_helpers/get_stub_filter'; +import { esFilters } from '../../../common'; +import { coreMock } from '../../../../../core/public/mocks'; +import { + createKbnUrlStateStorage, + IKbnUrlStateStorage, + Storage, +} from '../../../../kibana_utils/public'; +import { QueryService, QueryStart } from '../query_service'; +import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; +import { TimefilterContract } from '../timefilter'; +import { QuerySyncState, syncQuery } from './sync_query'; + +const setupMock = coreMock.createSetup(); +const startMock = coreMock.createStart(); + +setupMock.uiSettings.get.mockImplementation((key: string) => { + switch (key) { + case 'filters:pinnedByDefault': + return true; + case 'timepicker:timeDefaults': + return { from: 'now-15m', to: 'now' }; + case 'timepicker:refreshIntervalDefaults': + return { pause: false, value: 0 }; + default: + throw new Error(`sync_query test: not mocked uiSetting: ${key}`); + } +}); + +describe('sync_query', () => { + let queryServiceStart: QueryStart; + let filterManager: FilterManager; + let timefilter: TimefilterContract; + let kbnUrlStateStorage: IKbnUrlStateStorage; + let history: History; + + let filterManagerChangeSub: Subscription; + let filterManagerChangeTriggered = jest.fn(); + + let gF: esFilters.Filter; + let aF: esFilters.Filter; + + const pathWithFilter = + "/#?_g=(filters:!(('$state':(store:globalState),meta:(alias:!n,disabled:!t,index:'logstash-*',key:query,negate:!t,type:custom,value:'%7B%22match%22:%7B%22key1%22:%22value1%22%7D%7D'),query:(match:(key1:value1)))),refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))"; + + beforeEach(() => { + const queryService = new QueryService(); + queryService.setup({ + uiSettings: setupMock.uiSettings, + storage: new Storage(new StubBrowserStorage()), + }); + queryServiceStart = queryService.start(startMock.savedObjects); + filterManager = queryServiceStart.filterManager; + timefilter = queryServiceStart.timefilter.timefilter; + + filterManagerChangeTriggered = jest.fn(); + filterManagerChangeSub = filterManager.getUpdates$().subscribe(filterManagerChangeTriggered); + + window.location.href = '/'; + history = createBrowserHistory(); + kbnUrlStateStorage = createKbnUrlStateStorage({ useHash: false, history }); + + gF = getFilter(esFilters.FilterStateStore.GLOBAL_STATE, true, true, 'key1', 'value1'); + aF = getFilter(esFilters.FilterStateStore.APP_STATE, true, true, 'key3', 'value3'); + }); + afterEach(() => { + filterManagerChangeSub.unsubscribe(); + }); + + test('url is actually changed when data in services changes', () => { + const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + filterManager.setFilters([gF, aF]); + kbnUrlStateStorage.flush(); // sync force location change + expect(history.location.hash).toMatchInlineSnapshot( + `"#?_g=(filters:!(('$state':(store:globalState),meta:(alias:!n,disabled:!t,index:'logstash-*',key:query,negate:!t,type:custom,value:'%7B%22match%22:%7B%22key1%22:%22value1%22%7D%7D'),query:(match:(key1:value1)))),refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))"` + ); + stop(); + }); + + test('when filters change, global filters synced to urlStorage', () => { + const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + filterManager.setFilters([gF, aF]); + expect(kbnUrlStateStorage.get('_g')?.filters).toHaveLength(1); + stop(); + }); + + test('when time range changes, time synced to urlStorage', () => { + const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + timefilter.setTime({ from: 'now-30m', to: 'now' }); + expect(kbnUrlStateStorage.get('_g')?.time).toEqual({ + from: 'now-30m', + to: 'now', + }); + stop(); + }); + + test('when refresh interval changes, refresh interval is synced to urlStorage', () => { + const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + timefilter.setRefreshInterval({ pause: true, value: 100 }); + expect(kbnUrlStateStorage.get('_g')?.refreshInterval).toEqual({ + pause: true, + value: 100, + }); + stop(); + }); + + test('when url is changed, filters synced back to filterManager', () => { + const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + kbnUrlStateStorage.cancel(); // stop initial syncing pending update + history.push(pathWithFilter); + expect(filterManager.getGlobalFilters()).toHaveLength(1); + stop(); + }); + + test('initial url should be synced with services', () => { + history.push(pathWithFilter); + + const { stop, hasInheritedQueryFromUrl } = syncQuery(queryServiceStart, kbnUrlStateStorage); + expect(hasInheritedQueryFromUrl).toBe(true); + expect(filterManager.getGlobalFilters()).toHaveLength(1); + stop(); + }); + + test("url changes shouldn't trigger services updates if data didn't change", () => { + const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + filterManagerChangeTriggered.mockClear(); + + history.push(pathWithFilter); + history.push(pathWithFilter); + history.push(pathWithFilter); + + expect(filterManagerChangeTriggered).not.toBeCalled(); + stop(); + }); + + test("if data didn't change, kbnUrlStateStorage.set shouldn't be called", () => { + const { stop } = syncQuery(queryServiceStart, kbnUrlStateStorage); + filterManager.setFilters([gF, aF]); + const spy = jest.spyOn(kbnUrlStateStorage, 'set'); + filterManager.setFilters([gF]); // global filters didn't change + expect(spy).not.toBeCalled(); + stop(); + }); +}); diff --git a/src/plugins/data/public/query/state_sync/sync_query.ts b/src/plugins/data/public/query/state_sync/sync_query.ts new file mode 100644 index 00000000000000..be641e89f9b764 --- /dev/null +++ b/src/plugins/data/public/query/state_sync/sync_query.ts @@ -0,0 +1,167 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subscription } from 'rxjs'; +import _ from 'lodash'; +import { filter, map } from 'rxjs/operators'; +import { + createStateContainer, + IKbnUrlStateStorage, + syncState, +} from '../../../../kibana_utils/public'; +import { COMPARE_ALL_OPTIONS, compareFilters } from '../filter_manager/lib/compare_filters'; +import { esFilters, RefreshInterval, TimeRange } from '../../../common'; +import { QueryStart } from '../query_service'; + +const GLOBAL_STATE_STORAGE_KEY = '_g'; + +export interface QuerySyncState { + time?: TimeRange; + refreshInterval?: RefreshInterval; + filters?: esFilters.Filter[]; +} + +/** + * Helper utility to set up syncing between query services and url's '_g' query param + */ +export const syncQuery = ( + { timefilter: { timefilter }, filterManager }: QueryStart, + urlStateStorage: IKbnUrlStateStorage +) => { + const defaultState: QuerySyncState = { + time: timefilter.getTime(), + refreshInterval: timefilter.getRefreshInterval(), + filters: filterManager.getGlobalFilters(), + }; + + // retrieve current state from `_g` url + const initialStateFromUrl = urlStateStorage.get(GLOBAL_STATE_STORAGE_KEY); + + // remember whether there were info in the URL + const hasInheritedQueryFromUrl = Boolean( + initialStateFromUrl && Object.keys(initialStateFromUrl).length + ); + + // prepare initial state, whatever was in URL takes precedences over current state in services + const initialState: QuerySyncState = { + ...defaultState, + ...initialStateFromUrl, + }; + + // create state container, which will be used for syncing with syncState() util + const querySyncStateContainer = createStateContainer( + initialState, + { + setTime: (state: QuerySyncState) => (time: TimeRange) => ({ ...state, time }), + setRefreshInterval: (state: QuerySyncState) => (refreshInterval: RefreshInterval) => ({ + ...state, + refreshInterval, + }), + setFilters: (state: QuerySyncState) => (filters: esFilters.Filter[]) => ({ + ...state, + filters, + }), + }, + { + time: (state: QuerySyncState) => () => state.time, + refreshInterval: (state: QuerySyncState) => () => state.refreshInterval, + filters: (state: QuerySyncState) => () => state.filters, + } + ); + + const subs: Subscription[] = [ + timefilter.getTimeUpdate$().subscribe(() => { + querySyncStateContainer.transitions.setTime(timefilter.getTime()); + }), + timefilter.getRefreshIntervalUpdate$().subscribe(() => { + querySyncStateContainer.transitions.setRefreshInterval(timefilter.getRefreshInterval()); + }), + filterManager + .getUpdates$() + .pipe( + map(() => filterManager.getGlobalFilters()), // we need to track only global filters here + filter(newGlobalFilters => { + // continue only if global filters changed + // and ignore app state filters + const oldGlobalFilters = querySyncStateContainer.get().filters; + return ( + !oldGlobalFilters || + !compareFilters(newGlobalFilters, oldGlobalFilters, COMPARE_ALL_OPTIONS) + ); + }) + ) + .subscribe(newGlobalFilters => { + querySyncStateContainer.transitions.setFilters(newGlobalFilters); + }), + querySyncStateContainer.state$.subscribe( + ({ time, filters: globalFilters, refreshInterval }) => { + // cloneDeep is required because services are mutating passed objects + // and state in state container is frozen + if (time && !_.isEqual(time, timefilter.getTime())) { + timefilter.setTime(_.cloneDeep(time)); + } + + if (refreshInterval && !_.isEqual(refreshInterval, timefilter.getRefreshInterval())) { + timefilter.setRefreshInterval(_.cloneDeep(refreshInterval)); + } + + if ( + globalFilters && + !compareFilters(globalFilters, filterManager.getGlobalFilters(), COMPARE_ALL_OPTIONS) + ) { + filterManager.setGlobalFilters(_.cloneDeep(globalFilters)); + } + } + ), + ]; + + // if there weren't any initial state in url, + // then put _g key into url + if (!initialStateFromUrl) { + urlStateStorage.set(GLOBAL_STATE_STORAGE_KEY, initialState, { + replace: true, + }); + } + + // trigger initial syncing from state container to services if needed + querySyncStateContainer.set(initialState); + + const { start, stop } = syncState({ + stateStorage: urlStateStorage, + stateContainer: { + ...querySyncStateContainer, + set: state => { + if (state) { + // syncState utils requires to handle incoming "null" value + querySyncStateContainer.set(state); + } + }, + }, + storageKey: GLOBAL_STATE_STORAGE_KEY, + }); + + start(); + return { + stop: () => { + subs.forEach(s => s.unsubscribe()); + stop(); + }, + hasInheritedQueryFromUrl, + }; +}; diff --git a/src/plugins/data/public/search/create_app_mount_context_search.test.ts b/src/plugins/data/public/search/create_app_mount_context_search.test.ts index fa7cdbcda3082b..15b85ee270bed1 100644 --- a/src/plugins/data/public/search/create_app_mount_context_search.test.ts +++ b/src/plugins/data/public/search/create_app_mount_context_search.test.ts @@ -18,32 +18,35 @@ */ import { createAppMountSearchContext } from './create_app_mount_context_search'; -import { from } from 'rxjs'; +import { from, BehaviorSubject } from 'rxjs'; describe('Create app mount search context', () => { it('Returns search fn when there are no strategies', () => { - const context = createAppMountSearchContext({}); + const context = createAppMountSearchContext({}, new BehaviorSubject(0)); expect(context.search).toBeDefined(); }); it(`Search throws an error when the strategy doesn't exist`, () => { - const context = createAppMountSearchContext({}); + const context = createAppMountSearchContext({}, new BehaviorSubject(0)); expect(() => context.search({}, {}, 'noexist').toPromise()).toThrowErrorMatchingInlineSnapshot( `"Strategy with name noexist does not exist"` ); }); it(`Search fn is called on appropriate strategy name`, done => { - const context = createAppMountSearchContext({ - mysearch: search => - Promise.resolve({ - search: () => from(Promise.resolve({ percentComplete: 98 })), - }), - anothersearch: search => - Promise.resolve({ - search: () => from(Promise.resolve({ percentComplete: 0 })), - }), - }); + const context = createAppMountSearchContext( + { + mysearch: search => + Promise.resolve({ + search: () => from(Promise.resolve({ percentComplete: 98 })), + }), + anothersearch: search => + Promise.resolve({ + search: () => from(Promise.resolve({ percentComplete: 0 })), + }), + }, + new BehaviorSubject(0) + ); context.search({}, {}, 'mysearch').subscribe(response => { expect(response).toEqual({ percentComplete: 98 }); @@ -52,16 +55,19 @@ describe('Create app mount search context', () => { }); it(`Search fn is called with the passed in request object`, done => { - const context = createAppMountSearchContext({ - mysearch: search => { - return Promise.resolve({ - search: request => { - expect(request).toEqual({ greeting: 'hi' }); - return from(Promise.resolve({})); - }, - }); + const context = createAppMountSearchContext( + { + mysearch: search => { + return Promise.resolve({ + search: request => { + expect(request).toEqual({ greeting: 'hi' }); + return from(Promise.resolve({})); + }, + }); + }, }, - }); + new BehaviorSubject(0) + ); context.search({ greeting: 'hi' } as any, {}, 'mysearch').subscribe( response => {}, () => {}, diff --git a/src/plugins/data/public/search/create_app_mount_context_search.ts b/src/plugins/data/public/search/create_app_mount_context_search.ts index 5659a9c863dc18..f480b8f3e042e6 100644 --- a/src/plugins/data/public/search/create_app_mount_context_search.ts +++ b/src/plugins/data/public/search/create_app_mount_context_search.ts @@ -17,8 +17,8 @@ * under the License. */ -import { mergeMap } from 'rxjs/operators'; -import { from } from 'rxjs'; +import { mergeMap, tap } from 'rxjs/operators'; +import { from, BehaviorSubject } from 'rxjs'; import { ISearchAppMountContext } from './i_search_app_mount_context'; import { ISearchGeneric } from './i_search'; import { @@ -30,7 +30,8 @@ import { TStrategyTypes } from './strategy_types'; import { DEFAULT_SEARCH_STRATEGY } from '../../common/search'; export const createAppMountSearchContext = ( - searchStrategies: TSearchStrategiesMap + searchStrategies: TSearchStrategiesMap, + loadingCount$: BehaviorSubject ): ISearchAppMountContext => { const getSearchStrategy = ( strategyName?: K @@ -48,7 +49,13 @@ export const createAppMountSearchContext = ( const strategyPromise = getSearchStrategy(strategyName); return from(strategyPromise).pipe( mergeMap(strategy => { - return strategy.search(request, options); + loadingCount$.next(loadingCount$.getValue() + 1); + return strategy.search(request, options).pipe( + tap( + error => loadingCount$.next(loadingCount$.getValue() - 1), + complete => loadingCount$.next(loadingCount$.getValue() - 1) + ) + ); }) ); }; diff --git a/src/plugins/data/public/search/es_client/get_es_client.ts b/src/plugins/data/public/search/es_client/get_es_client.ts new file mode 100644 index 00000000000000..6c271643ba0124 --- /dev/null +++ b/src/plugins/data/public/search/es_client/get_es_client.ts @@ -0,0 +1,93 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @ts-ignore +import { default as es } from 'elasticsearch-browser/elasticsearch'; +import { CoreStart, PackageInfo } from 'kibana/public'; +import { BehaviorSubject } from 'rxjs'; + +export function getEsClient( + injectedMetadata: CoreStart['injectedMetadata'], + http: CoreStart['http'], + packageInfo: PackageInfo, + loadingCount$: BehaviorSubject +) { + const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; + const esApiVersion = injectedMetadata.getInjectedVar('esApiVersion') as string; + + // Use legacy es client for msearch. + const client = es.Client({ + host: getEsUrl(http, packageInfo), + log: 'info', + requestTimeout: esRequestTimeout, + apiVersion: esApiVersion, + }); + + return { + search: wrapEsClientMethod(client, 'search', loadingCount$), + msearch: wrapEsClientMethod(client, 'msearch', loadingCount$), + create: wrapEsClientMethod(client, 'create', loadingCount$), + }; +} + +function wrapEsClientMethod(esClient: any, method: string, loadingCount$: BehaviorSubject) { + return (args: any) => { + // esClient returns a promise, with an additional abort handler + // To tap into the abort handling, we have to override that abort handler. + const customPromiseThingy = esClient[method](args); + const { abort } = customPromiseThingy; + let resolved = false; + + // Start LoadingIndicator + loadingCount$.next(loadingCount$.getValue() + 1); + + // Stop LoadingIndicator when user aborts + customPromiseThingy.abort = () => { + abort(); + if (!resolved) { + resolved = true; + loadingCount$.next(loadingCount$.getValue() - 1); + } + }; + + // Stop LoadingIndicator when promise finishes + customPromiseThingy.finally(() => { + resolved = true; + loadingCount$.next(loadingCount$.getValue() - 1); + }); + + return customPromiseThingy; + }; +} + +function getEsUrl(http: CoreStart['http'], packageInfo: PackageInfo) { + const a = document.createElement('a'); + a.href = http.basePath.prepend('/elasticsearch'); + const protocolPort = /https/.test(a.protocol) ? 443 : 80; + const port = a.port || protocolPort; + return { + host: a.hostname, + port, + protocol: a.protocol, + pathname: a.pathname, + headers: { + 'kbn-version': packageInfo.version, + }, + }; +} diff --git a/src/plugins/data/public/search/es_client/index.ts b/src/plugins/data/public/search/es_client/index.ts new file mode 100644 index 00000000000000..b1e0ce31168242 --- /dev/null +++ b/src/plugins/data/public/search/es_client/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { getEsClient } from './get_es_client'; +export { SearchRequest, SearchResponse, LegacyApiCaller } from './types'; diff --git a/src/plugins/data/public/search/es_client/types.ts b/src/plugins/data/public/search/es_client/types.ts new file mode 100644 index 00000000000000..3ca0513a14238d --- /dev/null +++ b/src/plugins/data/public/search/es_client/types.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export type SearchRequest = any; +export type SearchResponse = any; + +export interface LegacyApiCaller { + search: (searchRequest: SearchRequest) => LegacyApiCallerResponse; + msearch: (searchRequest: SearchRequest) => LegacyApiCallerResponse; +} + +interface LegacyApiCallerResponse extends Promise { + abort: () => void; +} diff --git a/src/legacy/core_plugins/data/public/search/fetch/call_client.test.ts b/src/plugins/data/public/search/fetch/call_client.test.ts similarity index 94% rename from src/legacy/core_plugins/data/public/search/fetch/call_client.test.ts rename to src/plugins/data/public/search/fetch/call_client.test.ts index 74c87d77dd4fd0..6b43157aab83b1 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/call_client.test.ts +++ b/src/plugins/data/public/search/fetch/call_client.test.ts @@ -19,7 +19,9 @@ import { callClient } from './call_client'; import { handleResponse } from './handle_response'; -import { FetchHandlers, SearchRequest, SearchStrategySearchParams } from '../types'; +import { FetchHandlers } from './types'; +import { SearchRequest } from '../..'; +import { SearchStrategySearchParams } from '../search_strategy'; const mockResponses = [{}, {}]; const mockAbortFns = [jest.fn(), jest.fn()]; @@ -76,7 +78,7 @@ describe('callClient', () => { test('Passes the additional arguments it is given to the search strategy', () => { const searchRequests = [{ _searchStrategyId: 0 }]; - const args = { es: {}, config: {}, esShardTimeout: 0 } as FetchHandlers; + const args = { searchService: {}, config: {}, esShardTimeout: 0 } as FetchHandlers; callClient(searchRequests, [], args); diff --git a/src/legacy/core_plugins/data/public/search/fetch/call_client.ts b/src/plugins/data/public/search/fetch/call_client.ts similarity index 95% rename from src/legacy/core_plugins/data/public/search/fetch/call_client.ts rename to src/plugins/data/public/search/fetch/call_client.ts index 43da27f941e4e2..6cc58b05ea183b 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/call_client.ts +++ b/src/plugins/data/public/search/fetch/call_client.ts @@ -18,15 +18,15 @@ */ import { groupBy } from 'lodash'; -import { getSearchStrategyForSearchRequest, getSearchStrategyById } from '../search_strategy'; import { handleResponse } from './handle_response'; import { FetchOptions, FetchHandlers } from './types'; -import { SearchRequest } from '../types'; +import { getSearchStrategyForSearchRequest, getSearchStrategyById } from '../search_strategy'; +import { SearchRequest } from '..'; export function callClient( searchRequests: SearchRequest[], requestsOptions: FetchOptions[] = [], - { es, config, esShardTimeout }: FetchHandlers + fetchHandlers: FetchHandlers ) { // Correlate the options with the request that they're associated with const requestOptionEntries: Array<[ @@ -53,9 +53,7 @@ export function callClient( // then an error would have been thrown above const { searching, abort } = searchStrategy!.search({ searchRequests: requests, - es, - config, - esShardTimeout, + ...fetchHandlers, }); requests.forEach((request, i) => { diff --git a/src/legacy/core_plugins/data/public/search/fetch/errors.ts b/src/plugins/data/public/search/fetch/errors.ts similarity index 88% rename from src/legacy/core_plugins/data/public/search/fetch/errors.ts rename to src/plugins/data/public/search/fetch/errors.ts index 5f5dc0452df513..e216d32e127cd4 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/errors.ts +++ b/src/plugins/data/public/search/fetch/errors.ts @@ -17,9 +17,8 @@ * under the License. */ -import { SearchError } from '../search_strategy'; -import { KbnError } from '../../../../../../plugins/kibana_utils/public'; -import { SearchResponse } from '../types'; +import { KbnError } from '../../../../kibana_utils/public'; +import { SearchResponse, SearchError } from '..'; /** * Request Failure - When an entire multi request fails diff --git a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts b/src/plugins/data/public/search/fetch/fetch_soon.test.ts similarity index 97% rename from src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts rename to src/plugins/data/public/search/fetch/fetch_soon.test.ts index 69a343c78b1e12..a8d593c8501f68 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts +++ b/src/plugins/data/public/search/fetch/fetch_soon.test.ts @@ -19,9 +19,9 @@ import { fetchSoon } from './fetch_soon'; import { callClient } from './call_client'; -import { IUiSettingsClient } from '../../../../../../core/public'; +import { IUiSettingsClient } from '../../../../../core/public'; import { FetchHandlers, FetchOptions } from './types'; -import { SearchRequest, SearchResponse } from '../types'; +import { SearchRequest, SearchResponse } from '..'; function getConfigStub(config: any = {}) { return { diff --git a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts b/src/plugins/data/public/search/fetch/fetch_soon.ts similarity index 88% rename from src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts rename to src/plugins/data/public/search/fetch/fetch_soon.ts index 75de85e02a1a2b..b1405747426ee9 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts +++ b/src/plugins/data/public/search/fetch/fetch_soon.ts @@ -19,7 +19,7 @@ import { callClient } from './call_client'; import { FetchHandlers, FetchOptions } from './types'; -import { SearchRequest, SearchResponse } from '../types'; +import { SearchRequest, SearchResponse } from '..'; /** * This function introduces a slight delay in the request process to allow multiple requests to queue @@ -28,10 +28,10 @@ import { SearchRequest, SearchResponse } from '../types'; export async function fetchSoon( request: SearchRequest, options: FetchOptions, - { es, config, esShardTimeout }: FetchHandlers + fetchHandlers: FetchHandlers ) { - const msToDelay = config.get('courier:batchSearches') ? 50 : 0; - return delayedFetch(request, options, { es, config, esShardTimeout }, msToDelay); + const msToDelay = fetchHandlers.config.get('courier:batchSearches') ? 50 : 0; + return delayedFetch(request, options, fetchHandlers, msToDelay); } /** @@ -64,7 +64,7 @@ let fetchInProgress: Promise | null = null; async function delayedFetch( request: SearchRequest, options: FetchOptions, - { es, config, esShardTimeout }: FetchHandlers, + fetchHandlers: FetchHandlers, ms: number ) { const i = requestsToFetch.length; @@ -73,7 +73,7 @@ async function delayedFetch( const responses = await (fetchInProgress = fetchInProgress || delay(() => { - const response = callClient(requestsToFetch, requestOptions, { es, config, esShardTimeout }); + const response = callClient(requestsToFetch, requestOptions, fetchHandlers); requestsToFetch = []; requestOptions = []; fetchInProgress = null; diff --git a/src/legacy/core_plugins/data/public/search/fetch/handle_response.test.ts b/src/plugins/data/public/search/fetch/handle_response.test.ts similarity index 90% rename from src/legacy/core_plugins/data/public/search/fetch/handle_response.test.ts rename to src/plugins/data/public/search/fetch/handle_response.test.ts index 231ebf56993b6e..10e6eda3de3d02 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/handle_response.test.ts +++ b/src/plugins/data/public/search/fetch/handle_response.test.ts @@ -21,9 +21,8 @@ import { handleResponse } from './handle_response'; // Temporary disable eslint, will be removed after moving to new platform folder // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { notificationServiceMock } from '../../../../../../core/public/notifications/notifications_service.mock'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { setNotifications } from '../../../../../../plugins/data/public/services'; +import { notificationServiceMock } from '../../../../../core/public/notifications/notifications_service.mock'; +import { setNotifications } from '../../services'; jest.mock('@kbn/i18n', () => { return { diff --git a/src/legacy/core_plugins/data/public/search/fetch/handle_response.tsx b/src/plugins/data/public/search/fetch/handle_response.tsx similarity index 78% rename from src/legacy/core_plugins/data/public/search/fetch/handle_response.tsx rename to src/plugins/data/public/search/fetch/handle_response.tsx index a08b7d14fd1c37..7905468f91c5f5 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/handle_response.tsx +++ b/src/plugins/data/public/search/fetch/handle_response.tsx @@ -20,12 +20,10 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer } from '@elastic/eui'; -import { ShardFailureOpenModalButton } from './components/shard_failure_open_modal_button'; -import { Request, ResponseWithShardFailure } from './components/shard_failure_types'; -import { SearchRequest, SearchResponse } from '../types'; -import { toMountPoint } from '../../../../../../plugins/kibana_react/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getNotifications } from '../../../../../../plugins/data/public/services'; +import { ShardFailureOpenModalButton, ShardFailureRequest, ShardFailureResponse } from '../../ui'; +import { toMountPoint } from '../../../../kibana_react/public'; +import { getNotifications } from '../../services'; +import { SearchRequest, SearchResponse } from '..'; export function handleResponse(request: SearchRequest, response: SearchResponse) { if (response.timed_out) { @@ -56,8 +54,8 @@ export function handleResponse(request: SearchRequest, response: SearchResponse) {description} diff --git a/src/plugins/data/public/search/fetch/index.ts b/src/plugins/data/public/search/fetch/index.ts new file mode 100644 index 00000000000000..8a80b716add321 --- /dev/null +++ b/src/plugins/data/public/search/fetch/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './types'; +export { fetchSoon } from './fetch_soon'; +export { RequestFailure } from './errors'; diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts new file mode 100644 index 00000000000000..62eb965703c3a4 --- /dev/null +++ b/src/plugins/data/public/search/fetch/types.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ISearchStart } from 'src/plugins/data/public'; +import { IUiSettingsClient } from '../../../../../core/public'; + +export interface FetchOptions { + abortSignal?: AbortSignal; + searchStrategyId?: string; +} + +export interface FetchHandlers { + searchService: ISearchStart; + config: IUiSettingsClient; + esShardTimeout: number; +} diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts index d36202debd9b9d..cf7e0268d745a0 100644 --- a/src/plugins/data/public/search/index.ts +++ b/src/plugins/data/public/search/index.ts @@ -20,6 +20,7 @@ export { ISearchAppMountContext } from './i_search_app_mount_context'; export { ISearchSetup } from './i_search_setup'; +export { ISearchStart } from './search_service'; export { ISearchContext } from './i_search_context'; @@ -39,4 +40,21 @@ export { SYNC_SEARCH_STRATEGY } from './sync_search_strategy'; export { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search'; -export { ISearchStart } from './search_service'; +export { LegacyApiCaller, SearchRequest, SearchResponse } from './es_client'; + +export { + addSearchStrategy, + hasSearchStategyForIndexPattern, + defaultSearchStrategy, + SearchError, +} from './search_strategy'; + +export { + ISearchSource, + SearchSource, + SearchSourceFields, + EsQuerySortValue, + SortDirection, +} from './search_source'; + +export { FetchOptions } from './fetch'; diff --git a/src/plugins/data/public/search/search_service.test.ts b/src/plugins/data/public/search/search_service.test.ts index 69e05e8df48e28..9ed02e1d61018f 100644 --- a/src/plugins/data/public/search/search_service.test.ts +++ b/src/plugins/data/public/search/search_service.test.ts @@ -33,7 +33,9 @@ describe('Search service', () => { describe('setup()', () => { it('exposes proper contract', async () => { - const setup = searchService.setup(mockCoreSetup); + const setup = searchService.setup(mockCoreSetup, { + version: '8', + } as any); expect(setup).toHaveProperty('registerSearchStrategyContext'); expect(setup).toHaveProperty('registerSearchStrategyProvider'); }); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 6030884c9f6b1d..dad2b3d078aa0f 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import { BehaviorSubject } from 'rxjs'; import { Plugin, CoreSetup, @@ -23,6 +24,7 @@ import { CoreStart, IContextContainer, PluginOpaqueId, + PackageInfo, } from '../../../../core/public'; import { ISearchAppMountContext } from './i_search_app_mount_context'; @@ -37,6 +39,7 @@ import { import { TStrategyTypes } from './strategy_types'; import { esSearchService } from './es_search'; import { ISearchGeneric } from './i_search'; +import { getEsClient, LegacyApiCaller } from './es_client'; /** * Extends the AppMountContext so other plugins have access @@ -50,6 +53,9 @@ declare module 'kibana/public' { export interface ISearchStart { search: ISearchGeneric; + __LEGACY: { + esClient: LegacyApiCaller; + }; } /** @@ -72,18 +78,24 @@ export class SearchService implements Plugin { * Exposes context to the search strategies. */ private contextContainer?: IContextContainer>; - + private esClient?: LegacyApiCaller; private search?: ISearchGeneric; + private readonly loadingCount$ = new BehaviorSubject(0); constructor(private initializerContext: PluginInitializerContext) {} - public setup(core: CoreSetup): ISearchSetup { - const search = (this.search = createAppMountSearchContext(this.searchStrategies).search); + public setup(core: CoreSetup, packageInfo: PackageInfo): ISearchSetup { + core.http.addLoadingCountSource(this.loadingCount$); + const search = (this.search = createAppMountSearchContext( + this.searchStrategies, + this.loadingCount$ + ).search); core.application.registerMountContext<'search'>('search', () => { return { search }; }); this.contextContainer = core.context.createContextContainer(); + this.esClient = getEsClient(core.injectedMetadata, core.http, packageInfo, this.loadingCount$); const registerSearchStrategyProvider: TRegisterSearchStrategyProvider = < T extends TStrategyTypes @@ -98,6 +110,9 @@ export class SearchService implements Plugin { const api = { registerSearchStrategyContext: this.contextContainer!.registerContext, registerSearchStrategyProvider, + __LEGACY: { + esClient: this.esClient, + }, }; api.registerSearchStrategyContext(this.initializerContext.opaqueId, 'core', () => core); @@ -115,11 +130,16 @@ export class SearchService implements Plugin { return api; } - public start(core: CoreStart) { + public start(core: CoreStart): ISearchStart { if (!this.search) { throw new Error('Search should always be defined'); } - return { search: this.search }; + return { + search: this.search, + __LEGACY: { + esClient: this.esClient!, + }, + }; } public stop() {} diff --git a/src/legacy/core_plugins/data/public/search/search_source/filter_docvalue_fields.test.ts b/src/plugins/data/public/search/search_source/filter_docvalue_fields.test.ts similarity index 100% rename from src/legacy/core_plugins/data/public/search/search_source/filter_docvalue_fields.test.ts rename to src/plugins/data/public/search/search_source/filter_docvalue_fields.test.ts diff --git a/src/legacy/core_plugins/data/public/search/search_source/filter_docvalue_fields.ts b/src/plugins/data/public/search/search_source/filter_docvalue_fields.ts similarity index 100% rename from src/legacy/core_plugins/data/public/search/search_source/filter_docvalue_fields.ts rename to src/plugins/data/public/search/search_source/filter_docvalue_fields.ts diff --git a/src/plugins/data/public/search/search_source/index.ts b/src/plugins/data/public/search/search_source/index.ts new file mode 100644 index 00000000000000..10f1b2bc332e11 --- /dev/null +++ b/src/plugins/data/public/search/search_source/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './search_source'; +export { SortDirection, EsQuerySortValue, SearchSourceFields } from './types'; diff --git a/src/legacy/core_plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts similarity index 100% rename from src/legacy/core_plugins/data/public/search/search_source/mocks.ts rename to src/plugins/data/public/search/search_source/mocks.ts diff --git a/src/legacy/core_plugins/data/public/search/search_source/normalize_sort_request.test.ts b/src/plugins/data/public/search/search_source/normalize_sort_request.test.ts similarity index 98% rename from src/legacy/core_plugins/data/public/search/search_source/normalize_sort_request.test.ts rename to src/plugins/data/public/search/search_source/normalize_sort_request.test.ts index 22d1d931a9d096..5939074d773bf0 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/normalize_sort_request.test.ts +++ b/src/plugins/data/public/search/search_source/normalize_sort_request.test.ts @@ -19,7 +19,7 @@ import { normalizeSortRequest } from './normalize_sort_request'; import { SortDirection } from './types'; -import { IIndexPattern } from '../../../../../../plugins/data/public'; +import { IIndexPattern } from '../..'; jest.mock('ui/new_platform'); diff --git a/src/legacy/core_plugins/data/public/search/search_source/normalize_sort_request.ts b/src/plugins/data/public/search/search_source/normalize_sort_request.ts similarity index 97% rename from src/legacy/core_plugins/data/public/search/search_source/normalize_sort_request.ts rename to src/plugins/data/public/search/search_source/normalize_sort_request.ts index 93834c95514dc2..9e36d2e416f039 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/normalize_sort_request.ts +++ b/src/plugins/data/public/search/search_source/normalize_sort_request.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IIndexPattern } from '../../../../../../plugins/data/public'; +import { IIndexPattern } from '../..'; import { EsQuerySortValue, SortOptions } from './types'; export function normalizeSortRequest( diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts similarity index 91% rename from src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts rename to src/plugins/data/public/search/search_source/search_source.test.ts index 28f8dba9a75de3..936a2ae25ad1fa 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -18,20 +18,30 @@ */ import { SearchSource } from '../search_source'; -import { IndexPattern } from '../../../../../../plugins/data/public'; - -jest.mock('ui/new_platform'); +import { IndexPattern } from '../..'; +import { setSearchService, setUiSettings, setInjectedMetadata } from '../../services'; + +import { + injectedMetadataServiceMock, + uiSettingsServiceMock, +} from '../../../../../core/public/mocks'; + +setUiSettings(uiSettingsServiceMock.createStartContract()); +setInjectedMetadata(injectedMetadataServiceMock.createSetupContract()); +setSearchService({ + search: jest.fn(), + __LEGACY: { + esClient: { + search: jest.fn(), + msearch: jest.fn(), + }, + }, +}); jest.mock('../fetch', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), })); -jest.mock('ui/chrome', () => ({ - dangerouslyGetActiveInjector: () => ({ - get: jest.fn(), - }), -})); - const getComputedFields = () => ({ storedFields: [], scriptFields: [], diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts new file mode 100644 index 00000000000000..7b1a4533dd1c6d --- /dev/null +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -0,0 +1,414 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * @name SearchSource + * + * @description A promise-based stream of search results that can inherit from other search sources. + * + * Because filters/queries in Kibana have different levels of persistence and come from different + * places, it is important to keep track of where filters come from for when they are saved back to + * the savedObject store in the Kibana index. To do this, we create trees of searchSource objects + * that can have associated query parameters (index, query, filter, etc) which can also inherit from + * other searchSource objects. + * + * At query time, all of the searchSource objects that have subscribers are "flattened", at which + * point the query params from the searchSource are collected while traversing up the inheritance + * chain. At each link in the chain a decision about how to merge the query params is made until a + * single set of query parameters is created for each active searchSource (a searchSource with + * subscribers). + * + * That set of query parameters is then sent to elasticsearch. This is how the filter hierarchy + * works in Kibana. + * + * Visualize, starting from a new search: + * + * - the `savedVis.searchSource` is set as the `appSearchSource`. + * - The `savedVis.searchSource` would normally inherit from the `appSearchSource`, but now it is + * upgraded to inherit from the `rootSearchSource`. + * - Any interaction with the visualization will still apply filters to the `appSearchSource`, so + * they will be stored directly on the `savedVis.searchSource`. + * - Any interaction with the time filter will be written to the `rootSearchSource`, so those + * filters will not be saved by the `savedVis`. + * - When the `savedVis` is saved to elasticsearch, it takes with it all the filters that are + * defined on it directly, but none of the ones that it inherits from other places. + * + * Visualize, starting from an existing search: + * + * - The `savedVis` loads the `savedSearch` on which it is built. + * - The `savedVis.searchSource` is set to inherit from the `saveSearch.searchSource` and set as + * the `appSearchSource`. + * - The `savedSearch.searchSource`, is set to inherit from the `rootSearchSource`. + * - Then the `savedVis` is written to elasticsearch it will be flattened and only include the + * filters created in the visualize application and will reconnect the filters from the + * `savedSearch` at runtime to prevent losing the relationship + * + * Dashboard search sources: + * + * - Each panel in a dashboard has a search source. + * - The `savedDashboard` also has a searchsource, and it is set as the `appSearchSource`. + * - Each panel's search source inherits from the `appSearchSource`, meaning that they inherit from + * the dashboard search source. + * - When a filter is added to the search box, or via a visualization, it is written to the + * `appSearchSource`. + */ + +import _ from 'lodash'; +import { normalizeSortRequest } from './normalize_sort_request'; +import { filterDocvalueFields } from './filter_docvalue_fields'; +import { fieldWildcardFilter } from '../../../../kibana_utils/public'; +import { fieldFormats, esFilters, esQuery, SearchRequest } from '../..'; +import { SearchSourceOptions, SearchSourceFields } from './types'; +import { fetchSoon, FetchOptions, RequestFailure } from '../fetch'; + +import { getSearchService, getUiSettings, getInjectedMetadata } from '../../services'; + +export type ISearchSource = Pick; + +export class SearchSource { + private id: string = _.uniqueId('data_source'); + private searchStrategyId?: string; + private parent?: SearchSource; + private requestStartHandlers: Array< + (searchSource: ISearchSource, options?: FetchOptions) => Promise + > = []; + private inheritOptions: SearchSourceOptions = {}; + public history: SearchRequest[] = []; + + constructor(private fields: SearchSourceFields = {}) {} + + /** *** + * PUBLIC API + *****/ + + setPreferredSearchStrategyId(searchStrategyId: string) { + this.searchStrategyId = searchStrategyId; + } + + setFields(newFields: SearchSourceFields) { + this.fields = newFields; + return this; + } + + setField(field: K, value: SearchSourceFields[K]) { + if (value == null) { + delete this.fields[field]; + } else { + this.fields[field] = value; + } + return this; + } + + getId() { + return this.id; + } + + getFields() { + return { ...this.fields }; + } + + /** + * Get fields from the fields + */ + getField(field: K, recurse = true): SearchSourceFields[K] { + if (!recurse || this.fields[field] !== void 0) { + return this.fields[field]; + } + const parent = this.getParent(); + return parent && parent.getField(field); + } + + /** + * Get the field from our own fields, don't traverse up the chain + */ + getOwnField(field: K): SearchSourceFields[K] { + return this.getField(field, false); + } + + create() { + return new SearchSource(); + } + + createCopy() { + const newSearchSource = new SearchSource(); + newSearchSource.setFields({ ...this.fields }); + // when serializing the internal fields we lose the internal classes used in the index + // pattern, so we have to set it again to workaround this behavior + newSearchSource.setField('index', this.getField('index')); + newSearchSource.setParent(this.getParent()); + return newSearchSource; + } + + createChild(options = {}) { + const childSearchSource = new SearchSource(); + childSearchSource.setParent(this, options); + return childSearchSource; + } + + /** + * Set a searchSource that this source should inherit from + * @param {SearchSource} parent - the parent searchSource + * @param {SearchSourceOptions} options - the inherit options + * @return {this} - chainable + */ + setParent(parent?: ISearchSource, options: SearchSourceOptions = {}) { + this.parent = parent as SearchSource; + this.inheritOptions = options; + return this; + } + + /** + * Get the parent of this SearchSource + * @return {undefined|searchSource} + */ + getParent() { + return this.parent; + } + + /** + * Fetch this source and reject the returned Promise on error + * + * @async + */ + async fetch(options: FetchOptions = {}) { + await this.requestIsStarting(options); + + const searchRequest = await this.flatten(); + this.history = [searchRequest]; + + const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number; + const response = await fetchSoon( + searchRequest, + { + ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), + ...options, + }, + { + searchService: getSearchService(), + config: getUiSettings(), + esShardTimeout, + } + ); + + if (response.error) { + throw new RequestFailure(null, response); + } + + return response; + } + + /** + * Add a handler that will be notified whenever requests start + * @param {Function} handler + * @return {undefined} + */ + onRequestStart( + handler: (searchSource: ISearchSource, options?: FetchOptions) => Promise + ) { + this.requestStartHandlers.push(handler); + } + + async getSearchRequestBody() { + const searchRequest = await this.flatten(); + return searchRequest.body; + } + + /** + * Completely destroy the SearchSource. + * @return {undefined} + */ + destroy() { + this.requestStartHandlers.length = 0; + } + + /** **** + * PRIVATE APIS + ******/ + + /** + * Called by requests of this search source when they are started + * @param {Courier.Request} request + * @param options + * @return {Promise} + */ + private requestIsStarting(options: FetchOptions = {}) { + const handlers = [...this.requestStartHandlers]; + // If callParentStartHandlers has been set to true, we also call all + // handlers of parent search sources. + if (this.inheritOptions.callParentStartHandlers) { + let searchSource = this.getParent(); + while (searchSource) { + handlers.push(...searchSource.requestStartHandlers); + searchSource = searchSource.getParent(); + } + } + + return Promise.all(handlers.map(fn => fn(this, options))); + } + + /** + * Used to merge properties into the data within ._flatten(). + * The data is passed in and modified by the function + * + * @param {object} data - the current merged data + * @param {*} val - the value at `key` + * @param {*} key - The key of `val` + * @return {undefined} + */ + private mergeProp( + data: SearchRequest, + val: SearchSourceFields[K], + key: K + ) { + val = typeof val === 'function' ? val(this) : val; + if (val == null || !key) return; + + const addToRoot = (rootKey: string, value: any) => { + data[rootKey] = value; + }; + + /** + * Add the key and val to the body of the request + */ + const addToBody = (bodyKey: string, value: any) => { + // ignore if we already have a value + if (data.body[bodyKey] == null) { + data.body[bodyKey] = value; + } + }; + + switch (key) { + case 'filter': + return addToRoot('filters', (data.filters || []).concat(val)); + case 'query': + return addToRoot(key, (data[key] || []).concat(val)); + case 'fields': + const fields = _.uniq((data[key] || []).concat(val)); + return addToRoot(key, fields); + case 'index': + case 'type': + case 'highlightAll': + return key && data[key] == null && addToRoot(key, val); + case 'searchAfter': + return addToBody('search_after', val); + case 'source': + return addToBody('_source', val); + case 'sort': + const sort = normalizeSortRequest( + val, + this.getField('index'), + getUiSettings().get('sort:options') + ); + return addToBody(key, sort); + default: + return addToBody(key, val); + } + } + + /** + * Walk the inheritance chain of a source and return its + * flat representation (taking into account merging rules) + * @returns {Promise} + * @resolved {Object|null} - the flat data of the SearchSource + */ + private mergeProps(root = this, searchRequest: SearchRequest = { body: {} }) { + Object.entries(this.fields).forEach(([key, value]) => { + this.mergeProp(searchRequest, value, key as keyof SearchSourceFields); + }); + if (this.parent) { + this.parent.mergeProps(root, searchRequest); + } + return searchRequest; + } + + private flatten() { + const searchRequest = this.mergeProps(); + + searchRequest.body = searchRequest.body || {}; + const { body, index, fields, query, filters, highlightAll } = searchRequest; + + const computedFields = index ? index.getComputedFields() : {}; + + body.stored_fields = computedFields.storedFields; + body.script_fields = body.script_fields || {}; + _.extend(body.script_fields, computedFields.scriptFields); + + const defaultDocValueFields = computedFields.docvalueFields + ? computedFields.docvalueFields + : []; + body.docvalue_fields = body.docvalue_fields || defaultDocValueFields; + + if (!body.hasOwnProperty('_source') && index) { + body._source = index.getSourceFiltering(); + } + + if (body._source) { + // exclude source fields for this index pattern specified by the user + const filter = fieldWildcardFilter(body._source.excludes, getUiSettings().get('metaFields')); + body.docvalue_fields = body.docvalue_fields.filter((docvalueField: any) => + filter(docvalueField.field) + ); + } + + // if we only want to search for certain fields + if (fields) { + // filter out the docvalue_fields, and script_fields to only include those that we are concerned with + body.docvalue_fields = filterDocvalueFields(body.docvalue_fields, fields); + body.script_fields = _.pick(body.script_fields, fields); + + // request the remaining fields from both stored_fields and _source + const remainingFields = _.difference(fields, _.keys(body.script_fields)); + body.stored_fields = remainingFields; + _.set(body, '_source.includes', remainingFields); + } + + const esQueryConfigs = esQuery.getEsQueryConfig(getUiSettings()); + body.query = esQuery.buildEsQuery(index, query, filters, esQueryConfigs); + + if (highlightAll && body.query) { + body.highlight = fieldFormats.getHighlightRequest( + body.query, + getUiSettings().get('doc_table:highlight') + ); + delete searchRequest.highlightAll; + } + + const translateToQuery = (filter: esFilters.Filter) => filter && (filter.query || filter); + + // re-write filters within filter aggregations + (function recurse(aggBranch) { + if (!aggBranch) return; + Object.keys(aggBranch).forEach(function(id) { + const agg = aggBranch[id]; + + if (agg.filters) { + // translate filters aggregations + const { filters: aggFilters } = agg.filters; + Object.keys(aggFilters).forEach(filterId => { + aggFilters[filterId] = translateToQuery(aggFilters[filterId]); + }); + } + + recurse(agg.aggs || agg.aggregations); + }); + })(body.aggs || body.aggregations); + + return searchRequest; + } +} diff --git a/src/plugins/data/public/search/search_source/types.ts b/src/plugins/data/public/search/search_source/types.ts new file mode 100644 index 00000000000000..17337c905db877 --- /dev/null +++ b/src/plugins/data/public/search/search_source/types.ts @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { NameList } from 'elasticsearch'; +import { esFilters, IndexPattern, Query } from '../..'; + +export type EsQuerySearchAfter = [string | number, string | number]; + +export enum SortDirection { + asc = 'asc', + desc = 'desc', +} + +export type EsQuerySortValue = Record; + +export interface SearchSourceFields { + type?: string; + query?: Query; + filter?: + | esFilters.Filter[] + | esFilters.Filter + | (() => esFilters.Filter[] | esFilters.Filter | undefined); + sort?: EsQuerySortValue | EsQuerySortValue[]; + highlight?: any; + highlightAll?: boolean; + aggs?: any; + from?: number; + size?: number; + source?: NameList; + version?: boolean; + fields?: NameList; + index?: IndexPattern; + searchAfter?: EsQuerySearchAfter; + timeout?: string; + terminate_after?: number; +} + +export interface SearchSourceOptions { + callParentStartHandlers?: boolean; +} + +export { ISearchSource } from './search_source'; + +export interface SortOptions { + mode?: 'min' | 'max' | 'sum' | 'avg' | 'median'; + type?: 'double' | 'long' | 'date' | 'date_nanos'; + nested?: object; + unmapped_type?: string; + distance_type?: 'arc' | 'plane'; + unit?: string; + ignore_unmapped?: boolean; + _script?: object; +} + +export interface Request { + docvalue_fields: string[]; + _source: unknown; + query: unknown; + script_fields: unknown; + sort: unknown; + stored_fields: string[]; +} + +export interface ResponseWithShardFailure { + _shards: { + failed: number; + failures: ShardFailure[]; + skipped: number; + successful: number; + total: number; + }; +} + +export interface ShardFailure { + index: string; + node: string; + reason: { + caused_by: { + reason: string; + type: string; + }; + reason: string; + lang?: string; + script?: string; + script_stack?: string[]; + type: string; + }; + shard: number; +} diff --git a/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts new file mode 100644 index 00000000000000..80ab7ceb8870fe --- /dev/null +++ b/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts @@ -0,0 +1,131 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IUiSettingsClient } from '../../../../../core/public'; +import { SearchStrategySearchParams } from './types'; +import { defaultSearchStrategy } from './default_search_strategy'; + +const { search } = defaultSearchStrategy; + +function getConfigStub(config: any = {}) { + return { + get: key => config[key], + } as IUiSettingsClient; +} + +const msearchMockResponse: any = Promise.resolve([]); +msearchMockResponse.abort = jest.fn(); +const msearchMock = jest.fn().mockReturnValue(msearchMockResponse); + +const searchMockResponse: any = Promise.resolve([]); +searchMockResponse.abort = jest.fn(); +const searchMock = jest.fn().mockReturnValue(searchMockResponse); + +const newSearchMockResponse: any = Promise.resolve([]); +newSearchMockResponse.abort = jest.fn(); +const newSearchMock = jest.fn().mockReturnValue({ + toPromise: () => searchMockResponse, +}); + +describe('defaultSearchStrategy', function() { + describe('search', function() { + let searchArgs: MockedKeys>; + let es: any; + + beforeEach(() => { + msearchMockResponse.abort.mockClear(); + msearchMock.mockClear(); + + searchMockResponse.abort.mockClear(); + searchMock.mockClear(); + + searchArgs = { + searchRequests: [ + { + index: { title: 'foo' }, + }, + ], + esShardTimeout: 0, + searchService: { + search: newSearchMock, + __LEGACY: { + esClient: { + search: searchMock, + msearch: msearchMock, + }, + }, + }, + }; + + es = searchArgs.searchService.__LEGACY.esClient; + }); + + test('does not send max_concurrent_shard_requests by default', async () => { + const config = getConfigStub({ 'courier:batchSearches': true }); + await search({ ...searchArgs, config }); + expect(es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(undefined); + }); + + test('allows configuration of max_concurrent_shard_requests', async () => { + const config = getConfigStub({ + 'courier:batchSearches': true, + 'courier:maxConcurrentShardRequests': 42, + }); + await search({ ...searchArgs, config }); + expect(es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(42); + }); + + test('should set rest_total_hits_as_int to true on a request', async () => { + const config = getConfigStub({ 'courier:batchSearches': true }); + await search({ ...searchArgs, config }); + expect(es.msearch.mock.calls[0][0]).toHaveProperty('rest_total_hits_as_int', true); + }); + + test('should set ignore_throttled=false when including frozen indices', async () => { + const config = getConfigStub({ + 'courier:batchSearches': true, + 'search:includeFrozen': true, + }); + await search({ ...searchArgs, config }); + expect(es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false); + }); + + test('should properly call abort with msearch', () => { + const config = getConfigStub({ + 'courier:batchSearches': true, + }); + search({ ...searchArgs, config }).abort(); + expect(msearchMockResponse.abort).toHaveBeenCalled(); + }); + + test('should call new search service', () => { + const config = getConfigStub(); + search({ ...searchArgs, config }); + expect(searchMock).toHaveBeenCalled(); + expect(newSearchMock).toHaveBeenCalledTimes(0); + }); + + test('should properly abort with new search service', async () => { + const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); + const config = getConfigStub({}); + search({ ...searchArgs, config }).abort(); + expect(abortSpy).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/plugins/data/public/search/search_strategy/default_search_strategy.ts new file mode 100644 index 00000000000000..6c178fd9cd4c82 --- /dev/null +++ b/src/plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -0,0 +1,100 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SearchStrategyProvider, SearchStrategySearchParams } from './types'; +import { indexPatterns } from '../../index_patterns'; +import { getSearchParams, getMSearchParams, getPreference, getTimeout } from './get_search_params'; + +export const defaultSearchStrategy: SearchStrategyProvider = { + id: 'default', + + search: params => { + return params.config.get('courier:batchSearches') ? msearch(params) : search(params); + }, + + isViable: indexPattern => { + return indexPattern && indexPatterns.isDefault(indexPattern); + }, +}; + +// @deprecated +function msearch({ + searchRequests, + searchService, + config, + esShardTimeout, +}: SearchStrategySearchParams) { + const es = searchService.__LEGACY.esClient; + const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => { + const inlineHeader = { + index: index.title || index, + search_type: searchType, + ignore_unavailable: true, + preference: getPreference(config), + }; + const inlineBody = { + ...body, + timeout: getTimeout(esShardTimeout), + }; + return `${JSON.stringify(inlineHeader)}\n${JSON.stringify(inlineBody)}`; + }); + + const searching = es.msearch({ + ...getMSearchParams(config), + body: `${inlineRequests.join('\n')}\n`, + }); + + return { + searching: searching.then(({ responses }: any) => responses), + abort: searching.abort, + }; +} + +function search({ + searchRequests, + searchService, + config, + esShardTimeout, +}: SearchStrategySearchParams) { + const abortController = new AbortController(); + const searchParams = getSearchParams(config, esShardTimeout); + const es = searchService.__LEGACY.esClient; + const promises = searchRequests.map(({ index, body }) => { + const searching = es.search({ index: index.title || index, body, ...searchParams }); + abortController.signal.addEventListener('abort', searching.abort); + return searching.catch(({ response }: any) => JSON.parse(response)); + /* + * Once #44302 is resolved, replace the old implementation with this one - + * const params = { + * index: index.title || index, + * body, + * ...searchParams, + * }; + * const { signal } = abortController; + * return searchService + * .search({ params }, { signal }) + * .toPromise() + * .then(({ rawResponse }) => rawResponse); + */ + }); + return { + searching: Promise.all(promises), + abort: () => abortController.abort(), + }; +} diff --git a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/search_strategy/get_search_params.test.ts similarity index 98% rename from src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts rename to src/plugins/data/public/search/search_strategy/get_search_params.test.ts index f856aa77bf1f8e..76f3105d7f942e 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/public/search/search_strategy/get_search_params.test.ts @@ -18,7 +18,7 @@ */ import { getMSearchParams, getSearchParams } from './get_search_params'; -import { IUiSettingsClient } from '../../../../../../core/public'; +import { IUiSettingsClient } from '../../../../../core/public'; function getConfigStub(config: any = {}) { return { diff --git a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/search_strategy/get_search_params.ts similarity index 97% rename from src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts rename to src/plugins/data/public/search/search_strategy/get_search_params.ts index de9ec4cb920e8e..9fb8f2c728c6f0 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/search_strategy/get_search_params.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IUiSettingsClient } from '../../../../../../core/public'; +import { IUiSettingsClient } from '../../../../../core/public'; const sessionId = Date.now(); diff --git a/src/plugins/data/public/search/search_strategy/index.ts b/src/plugins/data/public/search/search_strategy/index.ts new file mode 100644 index 00000000000000..330e10d7d30e4d --- /dev/null +++ b/src/plugins/data/public/search/search_strategy/index.ts @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { + addSearchStrategy, + hasSearchStategyForIndexPattern, + getSearchStrategyById, + getSearchStrategyForSearchRequest, +} from './search_strategy_registry'; + +export { SearchError, getSearchErrorType } from './search_error'; + +export { SearchStrategyProvider, SearchStrategySearchParams } from './types'; + +export { defaultSearchStrategy } from './default_search_strategy'; diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/no_op_search_strategy.ts b/src/plugins/data/public/search/search_strategy/no_op_search_strategy.ts similarity index 100% rename from src/legacy/core_plugins/data/public/search/search_strategy/no_op_search_strategy.ts rename to src/plugins/data/public/search/search_strategy/no_op_search_strategy.ts diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/search_error.ts b/src/plugins/data/public/search/search_strategy/search_error.ts similarity index 100% rename from src/legacy/core_plugins/data/public/search/search_strategy/search_error.ts rename to src/plugins/data/public/search/search_strategy/search_error.ts diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/search_strategy_registry.test.ts b/src/plugins/data/public/search/search_strategy/search_strategy_registry.test.ts similarity index 98% rename from src/legacy/core_plugins/data/public/search/search_strategy/search_strategy_registry.test.ts rename to src/plugins/data/public/search/search_strategy/search_strategy_registry.test.ts index 73b011896a97dc..eaf86e1b270d53 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/search_strategy_registry.test.ts +++ b/src/plugins/data/public/search/search_strategy/search_strategy_registry.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IndexPattern } from '../../../../../../plugins/data/public'; +import { IndexPattern } from '../..'; import { noOpSearchStrategy } from './no_op_search_strategy'; import { searchStrategies, diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/search_strategy_registry.ts b/src/plugins/data/public/search/search_strategy/search_strategy_registry.ts similarity index 95% rename from src/legacy/core_plugins/data/public/search/search_strategy/search_strategy_registry.ts rename to src/plugins/data/public/search/search_strategy/search_strategy_registry.ts index d814a04737f753..1ab6f7d4e1effc 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/search_strategy_registry.ts +++ b/src/plugins/data/public/search/search_strategy/search_strategy_registry.ts @@ -17,10 +17,10 @@ * under the License. */ -import { IndexPattern } from '../../../../../../plugins/data/public'; +import { IndexPattern } from '../..'; import { SearchStrategyProvider } from './types'; import { noOpSearchStrategy } from './no_op_search_strategy'; -import { SearchResponse } from '../types'; +import { SearchResponse } from '..'; export const searchStrategies: SearchStrategyProvider[] = []; diff --git a/src/plugins/data/public/search/search_strategy/types.ts b/src/plugins/data/public/search/search_strategy/types.ts new file mode 100644 index 00000000000000..764370d8ff6497 --- /dev/null +++ b/src/plugins/data/public/search/search_strategy/types.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IndexPattern } from '../..'; +import { FetchHandlers } from '../fetch/types'; +import { SearchRequest, SearchResponse } from '..'; + +export interface SearchStrategyProvider { + id: string; + search: (params: SearchStrategySearchParams) => SearchStrategyResponse; + isViable: (indexPattern: IndexPattern) => boolean; +} + +export interface SearchStrategyResponse { + searching: Promise; + abort: () => void; +} + +export interface SearchStrategySearchParams extends FetchHandlers { + searchRequests: SearchRequest[]; +} diff --git a/src/plugins/data/public/search/sync_search_strategy.test.ts b/src/plugins/data/public/search/sync_search_strategy.test.ts index 2737a4033a015b..cd19c4d84dce14 100644 --- a/src/plugins/data/public/search/sync_search_strategy.test.ts +++ b/src/plugins/data/public/search/sync_search_strategy.test.ts @@ -44,10 +44,8 @@ describe('Sync search strategy', () => { }, {} ); - expect(mockCoreSetup.http.fetch.mock.calls[0][0]).toBe( - `/internal/search/${SYNC_SEARCH_STRATEGY}` - ); - expect(mockCoreSetup.http.fetch.mock.calls[0][1]).toEqual({ + expect(mockCoreSetup.http.fetch.mock.calls[0][0]).toEqual({ + path: `/internal/search/${SYNC_SEARCH_STRATEGY}`, body: JSON.stringify({ serverStrategy: 'SYNC_SEARCH_STRATEGY', }), diff --git a/src/plugins/data/public/search/sync_search_strategy.ts b/src/plugins/data/public/search/sync_search_strategy.ts index 3885a97a98571a..65fe10f39aaa04 100644 --- a/src/plugins/data/public/search/sync_search_strategy.ts +++ b/src/plugins/data/public/search/sync_search_strategy.ts @@ -36,14 +36,12 @@ export const syncSearchStrategyProvider: TSearchStrategyProvider { - const response: Promise = context.core.http.fetch( - `/internal/search/${request.serverStrategy}`, - { - method: 'POST', - body: JSON.stringify(request), - signal: options.signal, - } - ); + const response: Promise = context.core.http.fetch({ + path: `/internal/search/${request.serverStrategy}`, + method: 'POST', + body: JSON.stringify(request), + signal: options.signal, + }); return from(response); }; diff --git a/src/plugins/data/public/services.ts b/src/plugins/data/public/services.ts index 76b3283220f673..6a15893f573d83 100644 --- a/src/plugins/data/public/services.ts +++ b/src/plugins/data/public/services.ts @@ -18,7 +18,7 @@ */ import { NotificationsStart } from 'src/core/public'; -import { CoreStart } from 'kibana/public'; +import { CoreSetup, CoreStart } from 'kibana/public'; import { FieldFormatsStart } from '.'; import { createGetterSetter } from '../../kibana_utils/public'; import { IndexPatternsContract } from './index_patterns'; @@ -28,6 +28,12 @@ export const [getNotifications, setNotifications] = createGetterSetter( + 'UiSettings' +); + +export const [getHttp, setHttp] = createGetterSetter('Http'); + export const [getFieldFormats, setFieldFormats] = createGetterSetter( 'FieldFormats' ); @@ -41,3 +47,11 @@ export const [getIndexPatterns, setIndexPatterns] = createGetterSetter('Query'); + +export const [getInjectedMetadata, setInjectedMetadata] = createGetterSetter< + CoreSetup['injectedMetadata'] +>('InjectedMetadata'); + +export const [getSearchService, setSearchService] = createGetterSetter< + DataPublicPluginStart['search'] +>('Search'); diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index d2af2563022482..6b6ff5e62e63fa 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -21,7 +21,7 @@ import { CoreStart } from 'src/core/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { IUiActionsSetup, IUiActionsStart } from 'src/plugins/ui_actions/public'; import { AutocompleteSetup, AutocompleteStart } from './autocomplete/types'; -import { FieldFormatsSetup, FieldFormatsStart } from './field_formats_provider'; +import { FieldFormatsSetup, FieldFormatsStart } from './field_formats'; import { ISearchSetup, ISearchStart } from './search'; import { QuerySetup, QueryStart } from './query'; import { IndexPatternSelectProps } from './ui/index_pattern_select'; diff --git a/src/plugins/data/public/ui/_index.scss b/src/plugins/data/public/ui/_index.scss index 39f29ac7775880..1ca49963f3ded8 100644 --- a/src/plugins/data/public/ui/_index.scss +++ b/src/plugins/data/public/ui/_index.scss @@ -6,3 +6,5 @@ @import './saved_query_management/index'; @import './query_string_input/index'; + +@import './shard_failure_modal/shard_failure_modal'; \ No newline at end of file diff --git a/src/plugins/data/public/ui/index.ts b/src/plugins/data/public/ui/index.ts index cd4ec3c3bf74b3..0755363c9b16b3 100644 --- a/src/plugins/data/public/ui/index.ts +++ b/src/plugins/data/public/ui/index.ts @@ -23,6 +23,15 @@ export { FilterBar } from './filter_bar'; export { QueryStringInput } from './query_string_input/query_string_input'; export { SearchBar, SearchBarProps } from './search_bar'; -// temp export - will be removed as final components are migrated to NP +// @internal +export { + ShardFailureOpenModalButton, + ShardFailureRequest, + ShardFailureResponse, +} from './shard_failure_modal'; + +// @internal export { SavedQueryManagementComponent } from './saved_query_management'; + +// @internal export { SaveQueryForm, SavedQueryMeta } from './saved_query_form'; diff --git a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap index bc08c87304fcab..2f2332bb06e3c8 100644 --- a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap +++ b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap @@ -150,6 +150,12 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "getQuerySuggestions": [MockFunction], "getValueSuggestions": [MockFunction], @@ -157,7 +163,6 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA }, "fieldFormats": Object { "getByFieldType": [MockFunction], - "getConfig": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], "getDefaultInstanceCacheResolver": [MockFunction], @@ -205,6 +210,12 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA }, }, "search": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "search": [MockFunction], }, "ui": Object { @@ -304,6 +315,10 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA }, }, }, + "fatalErrors": Object { + "add": [MockFunction], + "get$": [MockFunction], + }, "http": Object { "addLoadingCountSource": [MockFunction], "anonymousPaths": Object { @@ -776,6 +791,12 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "getQuerySuggestions": [MockFunction], "getValueSuggestions": [MockFunction], @@ -783,7 +804,6 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA }, "fieldFormats": Object { "getByFieldType": [MockFunction], - "getConfig": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], "getDefaultInstanceCacheResolver": [MockFunction], @@ -831,6 +851,12 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA }, }, "search": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "search": [MockFunction], }, "ui": Object { @@ -930,6 +956,10 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA }, }, }, + "fatalErrors": Object { + "add": [MockFunction], + "get$": [MockFunction], + }, "http": Object { "addLoadingCountSource": [MockFunction], "anonymousPaths": Object { @@ -1384,6 +1414,12 @@ exports[`QueryStringInput Should pass the query language to the language switche "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "getQuerySuggestions": [MockFunction], "getValueSuggestions": [MockFunction], @@ -1391,7 +1427,6 @@ exports[`QueryStringInput Should pass the query language to the language switche }, "fieldFormats": Object { "getByFieldType": [MockFunction], - "getConfig": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], "getDefaultInstanceCacheResolver": [MockFunction], @@ -1439,6 +1474,12 @@ exports[`QueryStringInput Should pass the query language to the language switche }, }, "search": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "search": [MockFunction], }, "ui": Object { @@ -1538,6 +1579,10 @@ exports[`QueryStringInput Should pass the query language to the language switche }, }, }, + "fatalErrors": Object { + "add": [MockFunction], + "get$": [MockFunction], + }, "http": Object { "addLoadingCountSource": [MockFunction], "anonymousPaths": Object { @@ -2007,6 +2052,12 @@ exports[`QueryStringInput Should pass the query language to the language switche "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "getQuerySuggestions": [MockFunction], "getValueSuggestions": [MockFunction], @@ -2014,7 +2065,6 @@ exports[`QueryStringInput Should pass the query language to the language switche }, "fieldFormats": Object { "getByFieldType": [MockFunction], - "getConfig": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], "getDefaultInstanceCacheResolver": [MockFunction], @@ -2062,6 +2112,12 @@ exports[`QueryStringInput Should pass the query language to the language switche }, }, "search": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "search": [MockFunction], }, "ui": Object { @@ -2161,6 +2217,10 @@ exports[`QueryStringInput Should pass the query language to the language switche }, }, }, + "fatalErrors": Object { + "add": [MockFunction], + "get$": [MockFunction], + }, "http": Object { "addLoadingCountSource": [MockFunction], "anonymousPaths": Object { @@ -2615,6 +2675,12 @@ exports[`QueryStringInput Should render the given query 1`] = ` "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "getQuerySuggestions": [MockFunction], "getValueSuggestions": [MockFunction], @@ -2622,7 +2688,6 @@ exports[`QueryStringInput Should render the given query 1`] = ` }, "fieldFormats": Object { "getByFieldType": [MockFunction], - "getConfig": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], "getDefaultInstanceCacheResolver": [MockFunction], @@ -2670,6 +2735,12 @@ exports[`QueryStringInput Should render the given query 1`] = ` }, }, "search": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "search": [MockFunction], }, "ui": Object { @@ -2769,6 +2840,10 @@ exports[`QueryStringInput Should render the given query 1`] = ` }, }, }, + "fatalErrors": Object { + "add": [MockFunction], + "get$": [MockFunction], + }, "http": Object { "addLoadingCountSource": [MockFunction], "anonymousPaths": Object { @@ -3238,6 +3313,12 @@ exports[`QueryStringInput Should render the given query 1`] = ` "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "getQuerySuggestions": [MockFunction], "getValueSuggestions": [MockFunction], @@ -3245,7 +3326,6 @@ exports[`QueryStringInput Should render the given query 1`] = ` }, "fieldFormats": Object { "getByFieldType": [MockFunction], - "getConfig": [MockFunction], "getDefaultConfig": [MockFunction], "getDefaultInstance": [MockFunction], "getDefaultInstanceCacheResolver": [MockFunction], @@ -3293,6 +3373,12 @@ exports[`QueryStringInput Should render the given query 1`] = ` }, }, "search": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "search": [MockFunction], }, "ui": Object { @@ -3392,6 +3478,10 @@ exports[`QueryStringInput Should render the given query 1`] = ` }, }, }, + "fatalErrors": Object { + "add": [MockFunction], + "get$": [MockFunction], + }, "http": Object { "addLoadingCountSource": [MockFunction], "anonymousPaths": Object { diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/__mocks__/shard_failure_request.ts b/src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_request.ts similarity index 92% rename from src/legacy/core_plugins/data/public/search/fetch/components/__mocks__/shard_failure_request.ts rename to src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_request.ts index 701ff19a38ab90..a9192ee98b1920 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/components/__mocks__/shard_failure_request.ts +++ b/src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_request.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Request } from '../shard_failure_types'; +import { ShardFailureRequest } from '../shard_failure_types'; export const shardFailureRequest = { version: true, size: 500, @@ -29,4 +29,4 @@ export const shardFailureRequest = { docvalue_fields: [], query: {}, highlight: {}, -} as Request; +} as ShardFailureRequest; diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/__mocks__/shard_failure_response.ts b/src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_response.ts similarity index 93% rename from src/legacy/core_plugins/data/public/search/fetch/components/__mocks__/shard_failure_response.ts rename to src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_response.ts index 7a519b62a9cc7f..573aeefcdf4696 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/components/__mocks__/shard_failure_response.ts +++ b/src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_response.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { ResponseWithShardFailure } from '../shard_failure_types'; +import { ShardFailureResponse } from '../shard_failure_types'; export const shardFailureResponse = { _shards: { @@ -43,4 +43,4 @@ export const shardFailureResponse = { }, ], }, -} as ResponseWithShardFailure; +} as ShardFailureResponse; diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_description.test.tsx.snap b/src/plugins/data/public/ui/shard_failure_modal/__snapshots__/shard_failure_description.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_description.test.tsx.snap rename to src/plugins/data/public/ui/shard_failure_modal/__snapshots__/shard_failure_description.test.tsx.snap diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_modal.test.tsx.snap b/src/plugins/data/public/ui/shard_failure_modal/__snapshots__/shard_failure_modal.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_modal.test.tsx.snap rename to src/plugins/data/public/ui/shard_failure_modal/__snapshots__/shard_failure_modal.test.tsx.snap diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_table.test.tsx.snap b/src/plugins/data/public/ui/shard_failure_modal/__snapshots__/shard_failure_table.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_table.test.tsx.snap rename to src/plugins/data/public/ui/shard_failure_modal/__snapshots__/shard_failure_table.test.tsx.snap diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/_shard_failure_modal.scss b/src/plugins/data/public/ui/shard_failure_modal/_shard_failure_modal.scss similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/_shard_failure_modal.scss rename to src/plugins/data/public/ui/shard_failure_modal/_shard_failure_modal.scss diff --git a/src/plugins/data/public/ui/shard_failure_modal/index.ts b/src/plugins/data/public/ui/shard_failure_modal/index.ts new file mode 100644 index 00000000000000..f4c2e26a756e37 --- /dev/null +++ b/src/plugins/data/public/ui/shard_failure_modal/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { ShardFailureRequest, ShardFailureResponse } from './shard_failure_types'; +export { ShardFailureOpenModalButton } from './shard_failure_open_modal_button'; diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_description.test.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.test.tsx similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_description.test.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.test.tsx diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_description.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx similarity index 96% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_description.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx index 60e0e35a0f1520..d440f09ca09dd7 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_description.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { EuiCodeBlock, EuiDescriptionList, EuiSpacer } from '@elastic/eui'; import { ShardFailure } from './shard_failure_types'; -import { getFlattenedObject } from '../../../../../../../legacy/utils/get_flattened_object'; +import { getFlattenedObject } from '../../../../../core/utils'; import { ShardFailureDescriptionHeader } from './shard_failure_description_header'; /** diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_description_header.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description_header.tsx similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_description_header.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_description_header.tsx diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_modal.test.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.test.tsx similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_modal.test.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.test.tsx diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_modal.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.tsx similarity index 96% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_modal.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.tsx index 65cb49c6115756..3dcab7732f7695 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_modal.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.tsx @@ -33,12 +33,12 @@ import { EuiCallOut, } from '@elastic/eui'; import { ShardFailureTable } from './shard_failure_table'; -import { ResponseWithShardFailure, Request } from './shard_failure_types'; +import { ShardFailureResponse, ShardFailureRequest } from './shard_failure_types'; export interface Props { onClose: () => void; - request: Request; - response: ResponseWithShardFailure; + request: ShardFailureRequest; + response: ShardFailureResponse; title: string; } diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_open_modal_button.test.mocks.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.mocks.tsx similarity index 87% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_open_modal_button.test.mocks.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.mocks.tsx index 4dd4d5943fadcc..516eae9d46a6b7 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_open_modal_button.test.mocks.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.mocks.tsx @@ -17,8 +17,7 @@ * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { setOverlays } from '../../../../../../../plugins/data/public/services'; +import { setOverlays } from '../../services'; import { OverlayStart } from 'kibana/public'; export const openModal = jest.fn(); diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_open_modal_button.test.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.tsx similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_open_modal_button.test.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.tsx diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_open_modal_button.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx similarity index 84% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_open_modal_button.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx index c3ff042083473c..fa42745da2e485 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_open_modal_button.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx @@ -20,15 +20,14 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButton, EuiTextAlign } from '@elastic/eui'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getOverlays } from '../../../../../../../plugins/data/public/services'; -import { toMountPoint } from '../../../../../../../plugins/kibana_react/public'; +import { getOverlays } from '../../services'; +import { toMountPoint } from '../../../../kibana_react/public'; import { ShardFailureModal } from './shard_failure_modal'; -import { ResponseWithShardFailure, Request } from './shard_failure_types'; +import { ShardFailureResponse, ShardFailureRequest } from './shard_failure_types'; interface Props { - request: Request; - response: ResponseWithShardFailure; + request: ShardFailureRequest; + response: ShardFailureResponse; title: string; } diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_table.test.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_table.test.tsx similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_table.test.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_table.test.tsx diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_table.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_table.tsx similarity index 100% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_table.tsx rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_table.tsx diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_types.ts b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_types.ts similarity index 94% rename from src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_types.ts rename to src/plugins/data/public/ui/shard_failure_modal/shard_failure_types.ts index 22fc20233cc87d..b1ce3f30c42789 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/components/shard_failure_types.ts +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_types.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -export interface Request { +export interface ShardFailureRequest { docvalue_fields: string[]; _source: unknown; query: unknown; @@ -25,7 +25,7 @@ export interface Request { stored_fields: string[]; } -export interface ResponseWithShardFailure { +export interface ShardFailureResponse { _shards: { failed: number; failures: ShardFailure[]; diff --git a/src/plugins/data/server/field_formats/field_formats_service.ts b/src/plugins/data/server/field_formats/field_formats_service.ts new file mode 100644 index 00000000000000..923904db9def0e --- /dev/null +++ b/src/plugins/data/server/field_formats/field_formats_service.ts @@ -0,0 +1,59 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { has } from 'lodash'; +import { fieldFormats } from '../../common/field_formats'; +import { IUiSettingsClient } from '../../../../core/server'; + +export class FieldFormatsService { + private readonly fieldFormatClasses: fieldFormats.IFieldFormatType[] = + fieldFormats.baseFormatters; + + public setup() { + return { + register: (customFieldFormat: fieldFormats.IFieldFormatType) => + this.fieldFormatClasses.push(customFieldFormat), + }; + } + + public start() { + return { + fieldFormatServiceFactory: async (uiSettings: IUiSettingsClient) => { + const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry(); + const uiConfigs = await uiSettings.getAll(); + const registeredUiSettings = uiSettings.getRegistered(); + + Object.keys(registeredUiSettings).forEach(key => { + if (has(uiConfigs, key) && registeredUiSettings[key].type === 'json') { + uiConfigs[key] = JSON.parse(uiConfigs[key]); + } + }); + + fieldFormatsRegistry.init((key: string) => uiConfigs[key], {}, this.fieldFormatClasses); + + return fieldFormatsRegistry; + }, + }; + } +} + +/** @public */ +export type FieldFormatsSetup = ReturnType; + +/** @public */ +export type FieldFormatsStart = ReturnType; diff --git a/src/plugins/data/server/field_formats/index.ts b/src/plugins/data/server/field_formats/index.ts new file mode 100644 index 00000000000000..4550a5781535f2 --- /dev/null +++ b/src/plugins/data/server/field_formats/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats_service'; diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 3cd088744a4391..45bd111a2ce4fd 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -18,7 +18,7 @@ */ import { PluginInitializerContext } from '../../../core/server'; -import { DataServerPlugin, DataPluginSetup } from './plugin'; +import { DataServerPlugin, DataPluginSetup, DataPluginStart } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { return new DataServerPlugin(initializerContext); @@ -29,14 +29,20 @@ export function plugin(initializerContext: PluginInitializerContext) { * @public */ export { IRequestTypesMap, IResponseTypesMap } from './search'; + export { - // field formats - FIELD_FORMAT_IDS, - IFieldFormat, - IFieldFormatId, - IFieldFormatType, + // es query + esFilters, + esKuery, + esQuery, + fieldFormats, + // kbn field types + castEsToKbnFieldTypeName, + getKbnFieldType, + getKbnTypeNames, // index patterns IIndexPattern, + isFilterable, IFieldType, IFieldSubType, // kbn field types @@ -49,6 +55,7 @@ export { TimeRange, // utils parseInterval, + isNestedField, } from '../common'; /** @@ -61,36 +68,11 @@ export { shouldReadFieldFromDocValues, indexPatterns, } from './index_patterns'; + export * from './search'; -export { - // es query - esFilters, - esKuery, - esQuery, - // field formats - BoolFormat, - BytesFormat, - ColorFormat, - DateFormat, - DateNanosFormat, - DEFAULT_CONVERTER_COLOR, - DurationFormat, - FieldFormat, - IpFormat, - NumberFormat, - PercentFormat, - RelativeDateFormat, - SourceFormat, - StaticLookupFormat, - StringFormat, - TruncateFormat, - UrlFormat, - // index patterns - isFilterable, - // kbn field types - castEsToKbnFieldTypeName, - getKbnFieldType, - getKbnTypeNames, -} from '../common'; -export { DataServerPlugin as Plugin, DataPluginSetup as PluginSetup }; +export { + DataServerPlugin as Plugin, + DataPluginSetup as PluginSetup, + DataPluginStart as PluginStart, +}; 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 8f68e63703d407..e45ad796bd9d46 100644 --- a/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts +++ b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts @@ -27,12 +27,12 @@ export class KqlTelemetryService implements Plugin { constructor(private initializerContext: PluginInitializerContext) {} public setup( - { http, savedObjects }: CoreSetup, + { http, getStartServices }: CoreSetup, { usageCollection }: { usageCollection?: UsageCollectionSetup } ) { registerKqlTelemetryRoute( http.createRouter(), - savedObjects, + getStartServices, this.initializerContext.logger.get('data', 'kql-telemetry') ); diff --git a/src/plugins/data/server/kql_telemetry/route.ts b/src/plugins/data/server/kql_telemetry/route.ts index 3185da22b12b32..d5725c859c9a90 100644 --- a/src/plugins/data/server/kql_telemetry/route.ts +++ b/src/plugins/data/server/kql_telemetry/route.ts @@ -22,7 +22,7 @@ import { schema } from '@kbn/config-schema'; export function registerKqlTelemetryRoute( router: IRouter, - savedObjects: CoreSetup['savedObjects'], + getStartServices: CoreSetup['getStartServices'], logger: Logger ) { router.post( @@ -35,6 +35,7 @@ export function registerKqlTelemetryRoute( }, }, async (context, request, response) => { + const [{ savedObjects }] = await getStartServices(); const internalRepository = savedObjects.createScopedRepository(request); const { diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts index 591fdb4c4080d2..fcd3b62b2ec67d 100644 --- a/src/plugins/data/server/plugin.ts +++ b/src/plugins/data/server/plugin.ts @@ -25,20 +25,28 @@ import { ScriptsService } from './scripts'; import { KqlTelemetryService } from './kql_telemetry'; import { UsageCollectionSetup } from '../../usage_collection/server'; import { AutocompleteService } from './autocomplete'; +import { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats'; export interface DataPluginSetup { search: ISearchSetup; + fieldFormats: FieldFormatsSetup; +} + +export interface DataPluginStart { + fieldFormats: FieldFormatsStart; } export interface DataPluginSetupDependencies { usageCollection?: UsageCollectionSetup; } -export class DataServerPlugin implements Plugin { + +export class DataServerPlugin implements Plugin { private readonly searchService: SearchService; private readonly scriptsService: ScriptsService; private readonly kqlTelemetryService: KqlTelemetryService; private readonly autocompleteService = new AutocompleteService(); private readonly indexPatterns = new IndexPatternsService(); + private readonly fieldFormats = new FieldFormatsService(); constructor(initializerContext: PluginInitializerContext) { this.searchService = new SearchService(initializerContext); @@ -53,11 +61,17 @@ export class DataServerPlugin implements Plugin { this.kqlTelemetryService.setup(core, { usageCollection }); return { + fieldFormats: this.fieldFormats.setup(), search: this.searchService.setup(core), }; } - public start(core: CoreStart) {} + public start(core: CoreStart) { + return { + fieldFormats: this.fieldFormats.start(), + }; + } + public stop() {} } diff --git a/src/plugins/data/server/search/routes.test.ts b/src/plugins/data/server/search/routes.test.ts index a2394d88f39314..6ea0799f790fcf 100644 --- a/src/plugins/data/server/search/routes.test.ts +++ b/src/plugins/data/server/search/routes.test.ts @@ -65,8 +65,13 @@ describe('Search service', () => { expect(mockResponse.ok.mock.calls[0][0]).toEqual({ body: 'yay' }); }); - it('handler throws internal error if the search throws an error', async () => { - const mockSearch = jest.fn().mockRejectedValue('oh no'); + it('handler throws an error if the search throws an error', async () => { + const mockSearch = jest.fn().mockRejectedValue({ + message: 'oh no', + body: { + error: 'oops', + }, + }); const mockContext = { core: { elasticsearch: { @@ -93,7 +98,9 @@ describe('Search service', () => { expect(mockSearch).toBeCalled(); expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody); expect(mockSearch.mock.calls[0][2]).toBe(mockParams.strategy); - expect(mockResponse.internalError).toBeCalled(); - expect(mockResponse.internalError.mock.calls[0][0]).toEqual({ body: 'oh no' }); + expect(mockResponse.customError).toBeCalled(); + const error: any = mockResponse.customError.mock.calls[0][0]; + expect(error.body.message).toBe('oh no'); + expect(error.body.attributes.error).toBe('oops'); }); }); diff --git a/src/plugins/data/server/search/routes.ts b/src/plugins/data/server/search/routes.ts index eaa72548e08ee7..6f726771c41b2f 100644 --- a/src/plugins/data/server/search/routes.ts +++ b/src/plugins/data/server/search/routes.ts @@ -39,7 +39,15 @@ export function registerSearchRoute(router: IRouter): void { const response = await context.search!.search(searchRequest, {}, strategy); return res.ok({ body: response }); } catch (err) { - return res.internalError({ body: err }); + return res.customError({ + statusCode: err.statusCode, + body: { + message: err.message, + attributes: { + error: err.body.error, + }, + }, + }); } } ); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts index d03ff93a47218a..3f71f83c55694c 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts @@ -17,13 +17,14 @@ * under the License. */ -import { useState, useRef } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { useFormContext } from '../form_context'; interface Props { path: string; initialNumberOfItems?: number; + readDefaultValueOnForm?: boolean; children: (args: { items: ArrayItem[]; addItem: () => void; @@ -52,9 +53,15 @@ export interface ArrayItem { * * Look at the README.md for some examples. */ -export const UseArray = ({ path, initialNumberOfItems, children }: Props) => { +export const UseArray = ({ + path, + initialNumberOfItems, + readDefaultValueOnForm = true, + children, +}: Props) => { + const didMountRef = useRef(false); const form = useFormContext(); - const defaultValues = form.getFieldDefaultValue(path) as any[]; + const defaultValues = readDefaultValueOnForm && (form.getFieldDefaultValue(path) as any[]); const uniqueId = useRef(0); const getInitialItemsFromValues = (values: any[]): ArrayItem[] => @@ -99,5 +106,13 @@ export const UseArray = ({ path, initialNumberOfItems, children }: Props) => { }); }; + useEffect(() => { + if (didMountRef.current) { + setItems(updatePaths(items)); + } else { + didMountRef.current = true; + } + }, [path]); + return children({ items, addItem, removeItem }); }; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx index 021d52fbe9edb7..bdcf47c8657019 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx @@ -29,17 +29,27 @@ export interface Props { defaultValue?: unknown; component?: FunctionComponent | 'input'; componentProps?: Record; + readDefaultValueOnForm?: boolean; onChange?: (value: unknown) => void; children?: (field: FieldHook) => JSX.Element; } export const UseField = React.memo( - ({ path, config, defaultValue, component, componentProps, onChange, children }: Props) => { + ({ + path, + config, + defaultValue, + component, + componentProps, + readDefaultValueOnForm = true, + onChange, + children, + }: Props) => { const form = useFormContext(); component = component === undefined ? 'input' : component; componentProps = componentProps === undefined ? {} : componentProps; - if (typeof defaultValue === 'undefined') { + if (typeof defaultValue === 'undefined' && readDefaultValueOnForm) { defaultValue = form.getFieldDefaultValue(path); } diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts index d8b2f35e117a60..2ee68eb4d7a1a9 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts @@ -198,6 +198,12 @@ export function useForm( }); formData$.current.next(currentFormData as T); + + /** + * After removing a field, the form validity might have changed + * (an invalid field might have been removed and now the form is valid) + */ + updateFormValidity(); }; const setFieldValue: FormHook['setFieldValue'] = (fieldName, value) => { diff --git a/src/plugins/home/server/index.ts b/src/plugins/home/server/index.ts index ed336f4a41d6e8..0961c729698b9d 100644 --- a/src/plugins/home/server/index.ts +++ b/src/plugins/home/server/index.ts @@ -24,3 +24,6 @@ import { PluginInitializerContext } from 'src/core/server'; import { HomeServerPlugin } from './plugin'; export const plugin = (initContext: PluginInitializerContext) => new HomeServerPlugin(initContext); + +export { INSTRUCTION_VARIANT } from './tutorials/instructions/instruction_variant'; +export { ArtifactsSchema, TutorialsCategory } from './services/tutorials'; 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 7a4909668fff2e..aac680211e52e4 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 @@ -51,7 +51,7 @@ export class SampleDataRegistry { makeSampleDataUsageCollector(usageCollections, this.initContext); } const usageTracker = usage( - core.savedObjects, + core.getStartServices().then(([coreStart]) => coreStart.savedObjects), this.initContext.logger.get('sample_data', 'telemetry') ); const router = core.http.createRouter(); diff --git a/src/plugins/home/server/services/sample_data/usage/usage.ts b/src/plugins/home/server/services/sample_data/usage/usage.ts index a06dde387bb367..59599a1bee68fc 100644 --- a/src/plugins/home/server/services/sample_data/usage/usage.ts +++ b/src/plugins/home/server/services/sample_data/usage/usage.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Logger, SavedObjectsServiceSetup } from 'kibana/server'; +import { Logger, SavedObjectsServiceStart } from 'kibana/server'; const SAVED_OBJECT_ID = 'sample-data-telemetry'; @@ -27,7 +27,7 @@ export interface SampleDataUsageTracker { } export function usage( - savedObjects: SavedObjectsServiceSetup, + savedObjects: Promise, logger: Logger ): SampleDataUsageTracker { const handleIncrementError = (err: Error) => { @@ -37,11 +37,12 @@ export function usage( logger.warn(`saved objects repository incrementCounter encountered an error: ${err}`); }; - const internalRepository = savedObjects.createInternalRepository(); + const internalRepositoryPromise = savedObjects.then(so => so.createInternalRepository()); return { addInstall: async (dataSet: string) => { try { + const internalRepository = await internalRepositoryPromise; await internalRepository.incrementCounter(SAVED_OBJECT_ID, dataSet, `installCount`); } catch (err) { handleIncrementError(err); @@ -49,6 +50,7 @@ export function usage( }, addUninstall: async (dataSet: string) => { try { + const internalRepository = await internalRepositoryPromise; await internalRepository.incrementCounter(SAVED_OBJECT_ID, dataSet, `unInstallCount`); } catch (err) { handleIncrementError(err); diff --git a/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts b/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts index 951ce935760a12..80849513a3fad1 100644 --- a/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts +++ b/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts @@ -26,17 +26,30 @@ export enum TutorialsCategory { METRICS = 'metrics', OTHER = 'other', } +export type Platform = 'WINDOWS' | 'OSX' | 'DEB' | 'RPM'; + export interface ParamTypes { NUMBER: string; STRING: string; } +export interface Instruction { + title?: string; + textPre?: string; + commands?: string[]; + textPost?: string; +} +export interface InstructionVariant { + id: string; + instructions: Instruction[]; +} export interface InstructionSetSchema { - readonly title: string; - readonly callOut: { + readonly title?: string; + readonly callOut?: { title: string; - message: string; - iconType: IconType; + message?: string; + iconType?: IconType; }; + instructionVariants: InstructionVariant[]; } export interface ParamsSchema { defaultValue: any; @@ -46,22 +59,19 @@ export interface ParamsSchema { } export interface InstructionsSchema { readonly instructionSets: InstructionSetSchema[]; - readonly params: ParamsSchema[]; + readonly params?: ParamsSchema[]; } export interface DashboardSchema { id: string; - linkLabel?: { - is: boolean; - then: any; - }; + linkLabel?: string; isOverview: boolean; } export interface ArtifactsSchema { - readonly exportedFields: { + exportedFields?: { documentationUrl: string; }; - readonly dashboards: DashboardSchema[]; - readonly application: { + dashboards: DashboardSchema[]; + application?: { path: string; label: string; }; @@ -70,29 +80,32 @@ export interface TutorialSchema { id: string; category: TutorialsCategory; name: string; - isBeta: boolean; + isBeta?: boolean; shortDescription: string; - euiIconType: IconType; // EUI icon type string, one of https://elastic.github.io/eui/#/icon; + euiIconType?: IconType; // EUI icon type string, one of https://elastic.github.io/eui/#/icon; longDescription: string; - completionTimeMinutes: number; - previewImagePath: string; + completionTimeMinutes?: number; + previewImagePath?: string; // kibana and elastic cluster running on prem onPrem: InstructionsSchema; // kibana and elastic cluster running in elastic's cloud - elasticCloud: InstructionsSchema; + elasticCloud?: InstructionsSchema; // kibana running on prem and elastic cluster running in elastic's cloud - onPremElasticCloud: InstructionsSchema; + onPremElasticCloud?: InstructionsSchema; // Elastic stack artifacts produced by product when it is setup and run. - artifacts: ArtifactsSchema; + artifacts?: ArtifactsSchema; // saved objects used by data module. - savedObjects: any[]; - savedObjectsInstallMsg: string; + savedObjects?: any[]; + savedObjectsInstallMsg?: string; +} +export interface TutorialContext { + [key: string]: unknown; } -export type TutorialProvider = (context: { [key: string]: unknown }) => TutorialSchema; +export type TutorialProvider = (context: TutorialContext) => TutorialSchema; export type TutorialContextFactory = (req: KibanaRequest) => { [key: string]: unknown }; export type ScopedTutorialContextFactory = (...args: any[]) => any; diff --git a/src/plugins/home/server/services/tutorials/tutorials_registry.ts b/src/plugins/home/server/services/tutorials/tutorials_registry.ts index be0302cbd81889..e820924d7608d0 100644 --- a/src/plugins/home/server/services/tutorials/tutorials_registry.ts +++ b/src/plugins/home/server/services/tutorials/tutorials_registry.ts @@ -25,6 +25,7 @@ import { ScopedTutorialContextFactory, } from './lib/tutorials_registry_types'; import { tutorialSchema } from './lib/tutorial_schema'; +import { builtInTutorials } from '../../tutorials/register'; export class TutorialsRegistry { private readonly tutorialProviders: TutorialProvider[] = []; // pre-register all the tutorials we know we want in here @@ -77,6 +78,8 @@ export class TutorialsRegistry { } public start() { + // pre-populate with built in tutorials + this.tutorialProviders.push(...builtInTutorials); return {}; } } diff --git a/src/plugins/home/server/tutorials/activemq_logs/index.ts b/src/plugins/home/server/tutorials/activemq_logs/index.ts new file mode 100644 index 00000000000000..6511a21b15c442 --- /dev/null +++ b/src/plugins/home/server/tutorials/activemq_logs/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function activemqLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'activemq'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'activemqLogs', + name: i18n.translate('home.tutorials.activemqLogs.nameTitle', { + defaultMessage: 'ActiveMQ logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.activemqLogs.shortDescription', { + defaultMessage: 'Collect ActiveMQ logs with Filebeat.', + }), + longDescription: i18n.translate('home.tutorials.activemqLogs.longDescription', { + defaultMessage: 'Collect ActiveMQ logs with Filebeat. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-activemq.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/activemq.svg', + artifacts: { + dashboards: [ + { + id: '26434790-1464-11ea-8fd8-030a13064883', + linkLabel: i18n.translate('home.tutorials.activemqLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'ActiveMQ Application Events', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-activemq.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/activemq_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/activemq_metrics/index.ts b/src/plugins/home/server/tutorials/activemq_metrics/index.ts new file mode 100644 index 00000000000000..3898e2b5338b1d --- /dev/null +++ b/src/plugins/home/server/tutorials/activemq_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialsCategory, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function activemqMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'activemq'; + return { + id: 'activemqMetrics', + name: i18n.translate('home.tutorials.activemqMetrics.nameTitle', { + defaultMessage: 'ActiveMQ metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.activemqMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from ActiveMQ instances.', + }), + longDescription: i18n.translate('home.tutorials.activemqMetrics.longDescription', { + defaultMessage: + 'The `activemq` Metricbeat module fetches monitoring metrics from ActiveMQ instances \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-activemq.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/activemq.svg', + isBeta: true, + artifacts: { + application: { + label: i18n.translate('home.tutorials.activemqMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-activemq.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/aerospike_metrics/index.ts b/src/plugins/home/server/tutorials/aerospike_metrics/index.ts new file mode 100644 index 00000000000000..656e7feceed0cc --- /dev/null +++ b/src/plugins/home/server/tutorials/aerospike_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialsCategory, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function aerospikeMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'aerospike'; + return { + id: 'aerospikeMetrics', + name: i18n.translate('home.tutorials.aerospikeMetrics.nameTitle', { + defaultMessage: 'Aerospike metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.aerospikeMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the Aerospike server.', + }), + longDescription: i18n.translate('home.tutorials.aerospikeMetrics.longDescription', { + defaultMessage: + 'The `aerospike` Metricbeat module fetches internal metrics from Aerospike. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-aerospike.html', + }, + }), + euiIconType: 'logoAerospike', + artifacts: { + application: { + label: i18n.translate('home.tutorials.aerospikeMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-aerospike.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/apache_logs/index.ts b/src/plugins/home/server/tutorials/apache_logs/index.ts new file mode 100644 index 00000000000000..adf94f55670960 --- /dev/null +++ b/src/plugins/home/server/tutorials/apache_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function apacheLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'apache'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'apacheLogs', + name: i18n.translate('home.tutorials.apacheLogs.nameTitle', { + defaultMessage: 'Apache logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.apacheLogs.shortDescription', { + defaultMessage: 'Collect and parse access and error logs created by the Apache HTTP server.', + }), + longDescription: i18n.translate('home.tutorials.apacheLogs.longDescription', { + defaultMessage: + 'The apache Filebeat module parses access and error logs created by the Apache HTTP server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-apache.html', + }, + }), + euiIconType: 'logoApache', + artifacts: { + dashboards: [ + { + id: 'Filebeat-Apache-Dashboard-ecs', + linkLabel: i18n.translate('home.tutorials.apacheLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Apache logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-apache.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/apache_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/apache_metrics/index.ts b/src/plugins/home/server/tutorials/apache_metrics/index.ts new file mode 100644 index 00000000000000..e272f3efb5abe9 --- /dev/null +++ b/src/plugins/home/server/tutorials/apache_metrics/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function apacheMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'apache'; + return { + id: 'apacheMetrics', + name: i18n.translate('home.tutorials.apacheMetrics.nameTitle', { + defaultMessage: 'Apache metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.apacheMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the Apache 2 HTTP server.', + }), + longDescription: i18n.translate('home.tutorials.apacheMetrics.longDescription', { + defaultMessage: + 'The `apache` Metricbeat module fetches internal metrics from the Apache 2 HTTP server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-apache.html', + }, + }), + euiIconType: 'logoApache', + artifacts: { + dashboards: [ + { + id: 'Metricbeat-Apache-HTTPD-server-status-ecs', + linkLabel: i18n.translate('home.tutorials.apacheMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Apache metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-apache.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/apache_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/auditbeat/index.ts b/src/plugins/home/server/tutorials/auditbeat/index.ts new file mode 100644 index 00000000000000..6d94e7507ff420 --- /dev/null +++ b/src/plugins/home/server/tutorials/auditbeat/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/auditbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function auditbeatSpecProvider(context: TutorialContext): TutorialSchema { + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'auditbeat', + name: i18n.translate('home.tutorials.auditbeat.nameTitle', { + defaultMessage: 'Auditbeat', + }), + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.auditbeat.shortDescription', { + defaultMessage: 'Collect audit data from your hosts.', + }), + longDescription: i18n.translate('home.tutorials.auditbeat.longDescription', { + defaultMessage: + 'Use Auditbeat to collect auditing data from your hosts. These include \ +processes, users, logins, sockets information, file accesses, and more. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.auditbeat}/auditbeat-overview.html', + }, + }), + euiIconType: 'securityAnalyticsApp', + artifacts: { + dashboards: [], + application: { + path: '/app/siem', + label: i18n.translate('home.tutorials.auditbeat.artifacts.dashboards.linkLabel', { + defaultMessage: 'SIEM App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.auditbeat}/exported-fields.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/auditbeat/screenshot.png', + onPrem: onPremInstructions(platforms, context), + elasticCloud: cloudInstructions(platforms), + onPremElasticCloud: onPremCloudInstructions(platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/aws_logs/index.ts b/src/plugins/home/server/tutorials/aws_logs/index.ts new file mode 100644 index 00000000000000..8908838bd558ab --- /dev/null +++ b/src/plugins/home/server/tutorials/aws_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function awsLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'aws'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'awsLogs', + name: i18n.translate('home.tutorials.awsLogs.nameTitle', { + defaultMessage: 'AWS S3 based logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.awsLogs.shortDescription', { + defaultMessage: 'Collect AWS logs from S3 bucket with Filebeat.', + }), + longDescription: i18n.translate('home.tutorials.awsLogs.longDescription', { + defaultMessage: + 'Collect AWS logs by exporting them to an S3 bucket which is configured with SQS notification. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-aws.html', + }, + }), + euiIconType: 'logoAWS', + artifacts: { + dashboards: [ + { + id: '4746e000-bacd-11e9-9f70-1f7bda85a5eb', + linkLabel: i18n.translate('home.tutorials.awsLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'AWS S3 server access log dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-aws.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/aws_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/aws_metrics/index.ts b/src/plugins/home/server/tutorials/aws_metrics/index.ts new file mode 100644 index 00000000000000..d00951b524530c --- /dev/null +++ b/src/plugins/home/server/tutorials/aws_metrics/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function awsMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'aws'; + return { + id: 'awsMetrics', + name: i18n.translate('home.tutorials.awsMetrics.nameTitle', { + defaultMessage: 'AWS metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.awsMetrics.shortDescription', { + defaultMessage: + 'Fetch monitoring metrics for EC2 instances from the AWS APIs and Cloudwatch.', + }), + longDescription: i18n.translate('home.tutorials.awsMetrics.longDescription', { + defaultMessage: + 'The `aws` Metricbeat module fetches monitoring metrics from the AWS APIs and Cloudwatch. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-aws.html', + }, + }), + euiIconType: 'logoAWS', + isBeta: false, + artifacts: { + dashboards: [ + { + id: 'c5846400-f7fb-11e8-af03-c999c9dea608-ecs', + linkLabel: i18n.translate('home.tutorials.awsMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'AWS metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-aws.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/aws_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/azure_metrics/index.ts b/src/plugins/home/server/tutorials/azure_metrics/index.ts new file mode 100644 index 00000000000000..72befcf8d2065c --- /dev/null +++ b/src/plugins/home/server/tutorials/azure_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function azureMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'azure'; + return { + id: 'azureMetrics', + name: i18n.translate('home.tutorials.azureMetrics.nameTitle', { + defaultMessage: 'Azure metrics', + }), + isBeta: true, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.azureMetrics.shortDescription', { + defaultMessage: 'Fetch Azure Monitor metrics.', + }), + longDescription: i18n.translate('home.tutorials.azureMetrics.longDescription', { + defaultMessage: + 'The `azure` Metricbeat module fetches Azure Monitor metrics. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-azure.html', + }, + }), + euiIconType: 'logoAzure', + artifacts: { + application: { + label: i18n.translate('home.tutorials.azureMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-azure.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/ceph_metrics/index.ts b/src/plugins/home/server/tutorials/ceph_metrics/index.ts new file mode 100644 index 00000000000000..6b5f9c4c6fe5fd --- /dev/null +++ b/src/plugins/home/server/tutorials/ceph_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function cephMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'ceph'; + return { + id: 'cephMetrics', + name: i18n.translate('home.tutorials.cephMetrics.nameTitle', { + defaultMessage: 'Ceph metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.cephMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the Ceph server.', + }), + longDescription: i18n.translate('home.tutorials.cephMetrics.longDescription', { + defaultMessage: + 'The `ceph` Metricbeat module fetches internal metrics from Ceph. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-ceph.html', + }, + }), + euiIconType: 'logoCeph', + artifacts: { + application: { + label: i18n.translate('home.tutorials.cephMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-ceph.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/cisco_logs/index.ts b/src/plugins/home/server/tutorials/cisco_logs/index.ts new file mode 100644 index 00000000000000..303dbd9a9d856a --- /dev/null +++ b/src/plugins/home/server/tutorials/cisco_logs/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function ciscoLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'cisco'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'ciscoLogs', + name: i18n.translate('home.tutorials.ciscoLogs.nameTitle', { + defaultMessage: 'Cisco', + }), + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.ciscoLogs.shortDescription', { + defaultMessage: 'Collect and parse logs received from Cisco ASA firewalls.', + }), + longDescription: i18n.translate('home.tutorials.ciscoLogs.longDescription', { + defaultMessage: + 'This is a module for Cisco network device’s logs. Currently \ +supports the "asa" fileset for Cisco ASA firewall logs received over syslog or read from a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cisco.html', + }, + }), + // euiIconType: 'logoCisco', + artifacts: { + dashboards: [], + application: { + path: '/app/siem', + label: i18n.translate('home.tutorials.ciscoLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'SIEM App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-cisco.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/cisco_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/cloudwatch_logs/index.ts b/src/plugins/home/server/tutorials/cloudwatch_logs/index.ts new file mode 100644 index 00000000000000..10f0eb3e4f34fd --- /dev/null +++ b/src/plugins/home/server/tutorials/cloudwatch_logs/index.ts @@ -0,0 +1,66 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/functionbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function cloudwatchLogsSpecProvider(context: TutorialContext): TutorialSchema { + return { + id: 'cloudwatchLogs', + name: i18n.translate('home.tutorials.cloudwatchLogs.nameTitle', { + defaultMessage: 'AWS Cloudwatch logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.cloudwatchLogs.shortDescription', { + defaultMessage: 'Collect Cloudwatch logs with Functionbeat.', + }), + longDescription: i18n.translate('home.tutorials.cloudwatchLogs.longDescription', { + defaultMessage: + 'Collect Cloudwatch logs by deploying Functionbeat to run as \ + an AWS Lambda function. \ + [Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.functionbeat}/functionbeat-getting-started.html', + }, + }), + euiIconType: 'logoAWS', + artifacts: { + dashboards: [ + // TODO + ], + exportedFields: { + documentationUrl: '{config.docs.beats.functionbeat}/exported-fields.html', + }, + }, + completionTimeMinutes: 10, + // previewImagePath: '/plugins/kibana/home/tutorial_resources/uptime_monitors/screenshot.png', + onPrem: onPremInstructions([], context), + elasticCloud: cloudInstructions(), + onPremElasticCloud: onPremCloudInstructions(), + }; +} diff --git a/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts b/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts new file mode 100644 index 00000000000000..a8146e024a37e8 --- /dev/null +++ b/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function cockroachdbMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'cockroachdb'; + return { + id: 'cockroachdbMetrics', + name: i18n.translate('home.tutorials.cockroachdbMetrics.nameTitle', { + defaultMessage: 'CockroachDB metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.cockroachdbMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from the CockroachDB server.', + }), + longDescription: i18n.translate('home.tutorials.cockroachdbMetrics.longDescription', { + defaultMessage: + 'The `cockroachdb` Metricbeat module fetches monitoring metrics from CockroachDB. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-cockroachdb.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/cockroachdb.svg', + artifacts: { + dashboards: [ + { + id: 'e3ba0c30-9766-11e9-9eea-6f554992ec1f', + linkLabel: i18n.translate( + 'home.tutorials.cockroachdbMetrics.artifacts.dashboards.linkLabel', + { + defaultMessage: 'CockroachDB metrics dashboard', + } + ), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-cockroachdb.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/cockroachdb_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/consul_metrics/index.ts b/src/plugins/home/server/tutorials/consul_metrics/index.ts new file mode 100644 index 00000000000000..8b12f38274ee9f --- /dev/null +++ b/src/plugins/home/server/tutorials/consul_metrics/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function consulMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'consul'; + return { + id: 'consulMetrics', + name: i18n.translate('home.tutorials.consulMetrics.nameTitle', { + defaultMessage: 'Consul metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.consulMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from the Consul server.', + }), + longDescription: i18n.translate('home.tutorials.consulMetrics.longDescription', { + defaultMessage: + 'The `consul` Metricbeat module fetches monitoring metrics from Consul. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-consul.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/consul.svg', + artifacts: { + dashboards: [ + { + id: '496910f0-b952-11e9-a579-f5c0a5d81340', + linkLabel: i18n.translate('home.tutorials.consulMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Consul metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-consul.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/consul_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/coredns_logs/index.ts b/src/plugins/home/server/tutorials/coredns_logs/index.ts new file mode 100644 index 00000000000000..e2f976c0f377bc --- /dev/null +++ b/src/plugins/home/server/tutorials/coredns_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'coredns'; + const platforms = ['OSX', 'DEB', 'RPM'] as const; + return { + id: 'corednsLogs', + name: i18n.translate('home.tutorials.corednsLogs.nameTitle', { + defaultMessage: 'CoreDNS logs', + }), + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.corednsLogs.shortDescription', { + defaultMessage: 'Collect the logs created by Coredns.', + }), + longDescription: i18n.translate('home.tutorials.corednsLogs.longDescription', { + defaultMessage: + 'The `coredns` Filebeat module collects the logs from \ +[CoreDNS](https://coredns.io/manual/toc/). \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-coredns.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/coredns.svg', + artifacts: { + dashboards: [ + { + id: '53aa1f70-443e-11e9-8548-ab7fbe04f038', + linkLabel: i18n.translate('home.tutorials.corednsLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'CoreDNS logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-coredns.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/coredns_logs/screenshot.jpg', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/coredns_metrics/index.ts b/src/plugins/home/server/tutorials/coredns_metrics/index.ts new file mode 100644 index 00000000000000..ad0ce4a58c738b --- /dev/null +++ b/src/plugins/home/server/tutorials/coredns_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function corednsMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'coredns'; + return { + id: 'corednsMetrics', + name: i18n.translate('home.tutorials.corednsMetrics.nameTitle', { + defaultMessage: 'CoreDNS metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.corednsMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from the CoreDNS server.', + }), + longDescription: i18n.translate('home.tutorials.corednsMetrics.longDescription', { + defaultMessage: + 'The `coredns` Metricbeat module fetches monitoring metrics from CoreDNS. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-coredns.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/coredns.svg', + artifacts: { + application: { + label: i18n.translate('home.tutorials.corednsMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-coredns.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/coredns_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/couchbase_metrics/index.ts b/src/plugins/home/server/tutorials/couchbase_metrics/index.ts new file mode 100644 index 00000000000000..66b70ba2fb456e --- /dev/null +++ b/src/plugins/home/server/tutorials/couchbase_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function couchbaseMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'couchbase'; + return { + id: 'couchbaseMetrics', + name: i18n.translate('home.tutorials.couchbaseMetrics.nameTitle', { + defaultMessage: 'Couchbase metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.couchbaseMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from Couchbase.', + }), + longDescription: i18n.translate('home.tutorials.couchbaseMetrics.longDescription', { + defaultMessage: + 'The `couchbase` Metricbeat module fetches internal metrics from Couchbase. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-couchbase.html', + }, + }), + euiIconType: 'logoCouchbase', + artifacts: { + application: { + label: i18n.translate('home.tutorials.couchbaseMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-couchbase.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/couchdb_metrics/index.ts b/src/plugins/home/server/tutorials/couchdb_metrics/index.ts new file mode 100644 index 00000000000000..e1423e96b1d475 --- /dev/null +++ b/src/plugins/home/server/tutorials/couchdb_metrics/index.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function couchdbMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'couchdb'; + return { + id: 'couchdbMetrics', + name: i18n.translate('home.tutorials.couchdbMetrics.nameTitle', { + defaultMessage: 'CouchDB metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.couchdbMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from the CouchdB server.', + }), + longDescription: i18n.translate('home.tutorials.couchdbMetrics.longDescription', { + defaultMessage: + 'The `couchdb` Metricbeat module fetches monitoring metrics from CouchDB. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-couchdb.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/couchdb.svg', + artifacts: { + dashboards: [ + { + id: '496910f0-b952-11e9-a579-f5c0a5d81340', + linkLabel: i18n.translate( + 'home.tutorials.couchdbMetrics.artifacts.dashboards.linkLabel', + { + defaultMessage: 'CouchDB metrics dashboard', + } + ), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-couchdb.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/couchdb_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/docker_metrics/index.ts b/src/plugins/home/server/tutorials/docker_metrics/index.ts new file mode 100644 index 00000000000000..4d9d0c9ee68d72 --- /dev/null +++ b/src/plugins/home/server/tutorials/docker_metrics/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function dockerMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'docker'; + return { + id: 'dockerMetrics', + name: i18n.translate('home.tutorials.dockerMetrics.nameTitle', { + defaultMessage: 'Docker metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.dockerMetrics.shortDescription', { + defaultMessage: 'Fetch metrics about your Docker containers.', + }), + longDescription: i18n.translate('home.tutorials.dockerMetrics.longDescription', { + defaultMessage: + 'The `docker` Metricbeat module fetches metrics from the Docker server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-docker.html', + }, + }), + euiIconType: 'logoDocker', + artifacts: { + dashboards: [ + { + id: 'AV4REOpp5NkDleZmzKkE-ecs', + linkLabel: i18n.translate('home.tutorials.dockerMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Docker metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-docker.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/docker_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts b/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts new file mode 100644 index 00000000000000..164214ffd749c2 --- /dev/null +++ b/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function dropwizardMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'dropwizard'; + return { + id: 'dropwizardMetrics', + name: i18n.translate('home.tutorials.dropwizardMetrics.nameTitle', { + defaultMessage: 'Dropwizard metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.dropwizardMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from Dropwizard Java application.', + }), + longDescription: i18n.translate('home.tutorials.dropwizardMetrics.longDescription', { + defaultMessage: + 'The `dropwizard` Metricbeat module fetches internal metrics from Dropwizard Java Application. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-dropwizard.html', + }, + }), + euiIconType: 'logoDropwizard', + artifacts: { + application: { + label: i18n.translate('home.tutorials.dropwizardMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-dropwizard.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts new file mode 100644 index 00000000000000..4369c805dc7c42 --- /dev/null +++ b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function elasticsearchLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'elasticsearch'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'elasticsearchLogs', + name: i18n.translate('home.tutorials.elasticsearchLogs.nameTitle', { + defaultMessage: 'Elasticsearch logs', + }), + category: TutorialsCategory.LOGGING, + isBeta: true, + shortDescription: i18n.translate('home.tutorials.elasticsearchLogs.shortDescription', { + defaultMessage: 'Collect and parse logs created by Elasticsearch.', + }), + longDescription: i18n.translate('home.tutorials.elasticsearchLogs.longDescription', { + defaultMessage: + 'The `elasticsearch` Filebeat module parses logs created by Elasticsearch. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-elasticsearch.html', + }, + }), + euiIconType: 'logoElasticsearch', + artifacts: { + application: { + label: i18n.translate('home.tutorials.elasticsearchLogs.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-elasticsearch.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts b/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts new file mode 100644 index 00000000000000..d9004e72733f93 --- /dev/null +++ b/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function elasticsearchMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'elasticsearch'; + return { + id: 'elasticsearchMetrics', + name: i18n.translate('home.tutorials.elasticsearchMetrics.nameTitle', { + defaultMessage: 'Elasticsearch metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.elasticsearchMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from Elasticsearch.', + }), + longDescription: i18n.translate('home.tutorials.elasticsearchMetrics.longDescription', { + defaultMessage: + 'The `elasticsearch` Metricbeat module fetches internal metrics from Elasticsearch. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-elasticsearch.html', + }, + }), + euiIconType: 'logoElasticsearch', + artifacts: { + application: { + label: i18n.translate('home.tutorials.elasticsearchMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-elasticsearch.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts new file mode 100644 index 00000000000000..ac2db66dff6b68 --- /dev/null +++ b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function envoyproxyLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'envoyproxy'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'envoyproxyLogs', + name: i18n.translate('home.tutorials.envoyproxyLogs.nameTitle', { + defaultMessage: 'Envoyproxy', + }), + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.envoyproxyLogs.shortDescription', { + defaultMessage: 'Collect and parse logs received from the Envoy proxy.', + }), + longDescription: i18n.translate('home.tutorials.envoyproxyLogs.longDescription', { + defaultMessage: + 'This is a filebeat module for [Envoy proxy access log](https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log). \ +It supports both standalone deployment and Envoy proxy deployment in Kubernetes. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-envoyproxy.html', + }, + }), + // euiIconType: 'logoCisco', + artifacts: { + dashboards: [], + application: { + path: '/app/siem', + label: i18n.translate('home.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'SIEM App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-envoyproxy.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/envoyproxy_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts b/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts new file mode 100644 index 00000000000000..d405e779185467 --- /dev/null +++ b/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function envoyproxyMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'envoyproxy'; + return { + id: 'envoyproxyMetrics', + name: i18n.translate('home.tutorials.envoyproxyMetrics.nameTitle', { + defaultMessage: 'Envoy Proxy metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.envoyproxyMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from Envoy Proxy.', + }), + longDescription: i18n.translate('home.tutorials.envoyproxyMetrics.longDescription', { + defaultMessage: + 'The `envoyproxy` Metricbeat module fetches monitoring metrics from Envoy Proxy. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-envoyproxy.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/envoyproxy.svg', + artifacts: { + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-envoyproxy.html', + }, + }, + completionTimeMinutes: 10, + // previewImagePath: '/plugins/kibana/home/tutorial_resources/envoyproxy_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/etcd_metrics/index.ts b/src/plugins/home/server/tutorials/etcd_metrics/index.ts new file mode 100644 index 00000000000000..919700356d98ab --- /dev/null +++ b/src/plugins/home/server/tutorials/etcd_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function etcdMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'etcd'; + return { + id: 'etcdMetrics', + name: i18n.translate('home.tutorials.etcdMetrics.nameTitle', { + defaultMessage: 'Etcd metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.etcdMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the Etcd server.', + }), + longDescription: i18n.translate('home.tutorials.etcdMetrics.longDescription', { + defaultMessage: + 'The `etcd` Metricbeat module fetches internal metrics from Etcd. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-etcd.html', + }, + }), + euiIconType: 'logoEtcd', + artifacts: { + application: { + label: i18n.translate('home.tutorials.etcdMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-etcd.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/golang_metrics/index.ts b/src/plugins/home/server/tutorials/golang_metrics/index.ts new file mode 100644 index 00000000000000..c53f8b2bba2817 --- /dev/null +++ b/src/plugins/home/server/tutorials/golang_metrics/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function golangMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'golang'; + return { + id: moduleName + 'Metrics', + name: i18n.translate('home.tutorials.golangMetrics.nameTitle', { + defaultMessage: 'Golang metrics', + }), + isBeta: true, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.golangMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from a Golang app.', + }), + longDescription: i18n.translate('home.tutorials.golangMetrics.longDescription', { + defaultMessage: + 'The `{moduleName}` Metricbeat module fetches internal metrics from a Golang app. \ +[Learn more]({learnMoreLink}).', + values: { + moduleName, + learnMoreLink: `{config.docs.beats.metricbeat}/metricbeat-module-${moduleName}.html`, + }, + }), + euiIconType: 'logoGolang', + artifacts: { + dashboards: [ + { + id: 'f2dc7320-f519-11e6-a3c9-9d1f7c42b045-ecs', + linkLabel: i18n.translate('home.tutorials.golangMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Golang metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-' + moduleName + '.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/haproxy_metrics/index.ts b/src/plugins/home/server/tutorials/haproxy_metrics/index.ts new file mode 100644 index 00000000000000..8e1c0a0da8b184 --- /dev/null +++ b/src/plugins/home/server/tutorials/haproxy_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function haproxyMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'haproxy'; + return { + id: 'haproxyMetrics', + name: i18n.translate('home.tutorials.haproxyMetrics.nameTitle', { + defaultMessage: 'HAProxy metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.haproxyMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the HAProxy server.', + }), + longDescription: i18n.translate('home.tutorials.haproxyMetrics.longDescription', { + defaultMessage: + 'The `haproxy` Metricbeat module fetches internal metrics from HAProxy. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-haproxy.html', + }, + }), + euiIconType: 'logoHAproxy', + artifacts: { + application: { + label: i18n.translate('home.tutorials.haproxyMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-haproxy.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/ibmmq_logs/index.ts b/src/plugins/home/server/tutorials/ibmmq_logs/index.ts new file mode 100644 index 00000000000000..9922cb0e6341ed --- /dev/null +++ b/src/plugins/home/server/tutorials/ibmmq_logs/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function ibmmqLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'ibmmq'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'ibmmqLogs', + name: i18n.translate('home.tutorials.ibmmqLogs.nameTitle', { + defaultMessage: 'IBM MQ logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.ibmmqLogs.shortDescription', { + defaultMessage: 'Collect IBM MQ logs with Filebeat.', + }), + longDescription: i18n.translate('home.tutorials.ibmmqLogs.longDescription', { + defaultMessage: 'Collect IBM MQ logs with Filebeat. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-ibmmq.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/ibmmq.svg', + artifacts: { + dashboards: [ + { + id: 'ba1d8830-7c7b-11e9-9645-e37efaf5baff', + linkLabel: i18n.translate('home.tutorials.ibmmqLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'IBM MQ Events', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-ibmmq.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/ibmmq_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts b/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts new file mode 100644 index 00000000000000..2055196f833b2d --- /dev/null +++ b/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function ibmmqMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'ibmmq'; + return { + id: 'ibmmqMetrics', + name: i18n.translate('home.tutorials.ibmmqMetrics.nameTitle', { + defaultMessage: 'IBM MQ metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.ibmmqMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from IBM MQ instances.', + }), + longDescription: i18n.translate('home.tutorials.ibmmqMetrics.longDescription', { + defaultMessage: + 'The `ibmmq` Metricbeat module fetches monitoring metrics from IBM MQ instances \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-ibmmq.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/ibmmq.svg', + isBeta: true, + artifacts: { + application: { + label: i18n.translate('home.tutorials.ibmmqMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-ibmmq.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/ibmmq_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/iis_logs/index.ts b/src/plugins/home/server/tutorials/iis_logs/index.ts new file mode 100644 index 00000000000000..ff9996c1b01873 --- /dev/null +++ b/src/plugins/home/server/tutorials/iis_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function iisLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'iis'; + const platforms = ['WINDOWS'] as const; + return { + id: 'iisLogs', + name: i18n.translate('home.tutorials.iisLogs.nameTitle', { + defaultMessage: 'IIS logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.iisLogs.shortDescription', { + defaultMessage: 'Collect and parse access and error logs created by the IIS HTTP server.', + }), + longDescription: i18n.translate('home.tutorials.iisLogs.longDescription', { + defaultMessage: + 'The `iis` Filebeat module parses access and error logs created by the IIS HTTP server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iis.html', + }, + }), + // euiIconType: 'logoIIS', + artifacts: { + dashboards: [ + { + id: '4278ad30-fe16-11e7-a3b0-d13028918f9f-ecs', + linkLabel: i18n.translate('home.tutorials.iisLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'IIS logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-iis.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/iis_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/instructions/auditbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/auditbeat_instructions.ts new file mode 100644 index 00000000000000..6a9dba69b193f3 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/auditbeat_instructions.ts @@ -0,0 +1,518 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { INSTRUCTION_VARIANT } from './instruction_variant'; +import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; +import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; +import { Platform, TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +export const createAuditbeatInstructions = (context?: TutorialContext) => ({ + INSTALL: { + OSX: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.install.osxTitle', { + defaultMessage: 'Download and install Auditbeat', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.install.osxTextPre', { + defaultMessage: 'First time using Auditbeat? See the [Getting Started Guide]({linkUrl}).', + values: { + linkUrl: '{config.docs.beats.auditbeat}/auditbeat-getting-started.html', + }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'tar xzvf auditbeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'cd auditbeat-{config.kibana.version}-darwin-x86_64/', + ], + }, + DEB: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.install.debTitle', { + defaultMessage: 'Download and install Auditbeat', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.install.debTextPre', { + defaultMessage: 'First time using Auditbeat? See the [Getting Started Guide]({linkUrl}).', + values: { + linkUrl: '{config.docs.beats.auditbeat}/auditbeat-getting-started.html', + }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-{config.kibana.version}-amd64.deb', + 'sudo dpkg -i auditbeat-{config.kibana.version}-amd64.deb', + ], + textPost: i18n.translate('home.tutorials.common.auditbeatInstructions.install.debTextPost', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({linkUrl}).', + values: { + linkUrl: 'https://www.elastic.co/downloads/beats/auditbeat', + }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.install.rpmTitle', { + defaultMessage: 'Download and install Auditbeat', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.install.rpmTextPre', { + defaultMessage: 'First time using Auditbeat? See the [Getting Started Guide]({linkUrl}).', + values: { + linkUrl: '{config.docs.beats.auditbeat}/auditbeat-getting-started.html', + }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-{config.kibana.version}-x86_64.rpm', + 'sudo rpm -vi auditbeat-{config.kibana.version}-x86_64.rpm', + ], + textPost: i18n.translate('home.tutorials.common.auditbeatInstructions.install.rpmTextPost', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({linkUrl}).', + values: { + linkUrl: 'https://www.elastic.co/downloads/beats/auditbeat', + }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.install.windowsTitle', { + defaultMessage: 'Download and install Auditbeat', + }), + textPre: i18n.translate( + 'home.tutorials.common.auditbeatInstructions.install.windowsTextPre', + { + defaultMessage: + 'First time using Auditbeat? See the [Getting Started Guide]({guideLinkUrl}).\n\ + 1. Download the Auditbeat Windows zip file from the [Download]({auditbeatLinkUrl}) page.\n\ + 2. Extract the contents of the zip file into {folderPath}.\n\ + 3. Rename the `{directoryName}` directory to `Auditbeat`.\n\ + 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ +**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ + 5. From the PowerShell prompt, run the following commands to install Auditbeat as a Windows service.', + values: { + folderPath: '`C:\\Program Files`', + guideLinkUrl: '{config.docs.beats.auditbeat}/auditbeat-getting-started.html', + auditbeatLinkUrl: 'https://www.elastic.co/downloads/beats/auditbeat', + directoryName: 'auditbeat-{config.kibana.version}-windows', + }, + } + ), + commands: ['cd "C:\\Program Files\\Auditbeat"', '.\\install-service-auditbeat.ps1'], + textPost: i18n.translate( + 'home.tutorials.common.auditbeatInstructions.install.windowsTextPost', + { + defaultMessage: + 'Modify the settings under {propertyName} in the {auditbeatPath} file to point to your Elasticsearch installation.', + values: { + propertyName: '`output.elasticsearch`', + auditbeatPath: '`C:\\Program Files\\Auditbeat\\auditbeat.yml`', + }, + } + ), + }, + }, + START: { + OSX: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.start.osxTitle', { + defaultMessage: 'Start Auditbeat', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.start.osxTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['./auditbeat setup', './auditbeat -e'], + }, + DEB: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.start.debTitle', { + defaultMessage: 'Start Auditbeat', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.start.debTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['sudo auditbeat setup', 'sudo service auditbeat start'], + }, + RPM: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.start.rpmTitle', { + defaultMessage: 'Start Auditbeat', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.start.rpmTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['sudo auditbeat setup', 'sudo service auditbeat start'], + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.start.windowsTitle', { + defaultMessage: 'Start Auditbeat', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.start.windowsTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['.\\auditbeat.exe setup', 'Start-Service auditbeat'], + }, + }, + CONFIG: { + OSX: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.config.osxTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`auditbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.auditbeatInstructions.config.osxTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + DEB: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.config.debTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.config.debTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`/etc/auditbeat/auditbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.auditbeatInstructions.config.debTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.config.rpmTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.config.rpmTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`/etc/auditbeat/auditbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.auditbeatInstructions.config.rpmTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.auditbeatInstructions.config.windowsTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.auditbeatInstructions.config.windowsTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`C:\\Program Files\\Auditbeat\\auditbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate( + 'home.tutorials.common.auditbeatInstructions.config.windowsTextPost', + { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + } + ), + }, + }, +}); + +export const createAuditbeatCloudInstructions = () => ({ + CONFIG: { + OSX: { + title: i18n.translate('home.tutorials.common.auditbeatCloudInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.osxTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`auditbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.osxTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + DEB: { + title: i18n.translate('home.tutorials.common.auditbeatCloudInstructions.config.debTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.debTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`/etc/auditbeat/auditbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.debTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + RPM: { + title: i18n.translate('home.tutorials.common.auditbeatCloudInstructions.config.rpmTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`/etc/auditbeat/auditbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + WINDOWS: { + title: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.windowsTitle', + { + defaultMessage: 'Edit the configuration', + } + ), + textPre: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`C:\\Program Files\\Auditbeat\\auditbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + }, +}); + +export function auditbeatStatusCheck() { + return { + title: i18n.translate('home.tutorials.common.auditbeatStatusCheck.title', { + defaultMessage: 'Status', + }), + text: i18n.translate('home.tutorials.common.auditbeatStatusCheck.text', { + defaultMessage: 'Check that data is received from Auditbeat', + }), + btnLabel: i18n.translate('home.tutorials.common.auditbeatStatusCheck.buttonLabel', { + defaultMessage: 'Check data', + }), + success: i18n.translate('home.tutorials.common.auditbeatStatusCheck.successText', { + defaultMessage: 'Data successfully received', + }), + error: i18n.translate('home.tutorials.common.auditbeatStatusCheck.errorText', { + defaultMessage: 'No data has been received yet', + }), + esHitsCheck: { + index: 'auditbeat-*', + query: { + bool: { + filter: { + term: { + 'agent.type': 'auditbeat', + }, + }, + }, + }, + }, + }; +} + +export function onPremInstructions(platforms: readonly Platform[], context?: TutorialContext) { + const AUDITBEAT_INSTRUCTIONS = createAuditbeatInstructions(context); + + const variants = []; + for (let i = 0; i < platforms.length; i++) { + const platform = platforms[i]; + const instructions = []; + instructions.push(AUDITBEAT_INSTRUCTIONS.INSTALL[platform]); + instructions.push(AUDITBEAT_INSTRUCTIONS.CONFIG[platform]); + instructions.push(AUDITBEAT_INSTRUCTIONS.START[platform]); + variants.push({ + id: INSTRUCTION_VARIANT[platform], + instructions, + }); + } + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.auditbeat.premInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: variants, + statusCheck: auditbeatStatusCheck(), + }, + ], + }; +} + +export function onPremCloudInstructions(platforms: readonly Platform[]) { + const AUDITBEAT_INSTRUCTIONS = createAuditbeatInstructions(); + const TRYCLOUD_OPTION1 = createTrycloudOption1(); + const TRYCLOUD_OPTION2 = createTrycloudOption2(); + + const variants = []; + for (let i = 0; i < platforms.length; i++) { + const platform = platforms[i]; + variants.push({ + id: INSTRUCTION_VARIANT[platform], + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + AUDITBEAT_INSTRUCTIONS.INSTALL[platform], + AUDITBEAT_INSTRUCTIONS.CONFIG[platform], + AUDITBEAT_INSTRUCTIONS.START[platform], + ], + }); + } + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: variants, + statusCheck: auditbeatStatusCheck(), + }, + ], + }; +} + +export function cloudInstructions(platforms: readonly Platform[]) { + const AUDITBEAT_INSTRUCTIONS = createAuditbeatInstructions(); + const AUDITBEAT_CLOUD_INSTRUCTIONS = createAuditbeatCloudInstructions(); + + const variants = []; + for (let i = 0; i < platforms.length; i++) { + const platform = platforms[i]; + variants.push({ + id: INSTRUCTION_VARIANT[platform], + instructions: [ + AUDITBEAT_INSTRUCTIONS.INSTALL[platform], + AUDITBEAT_CLOUD_INSTRUCTIONS.CONFIG[platform], + AUDITBEAT_INSTRUCTIONS.START[platform], + ], + }); + } + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: variants, + statusCheck: auditbeatStatusCheck(), + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/instructions/filebeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/filebeat_instructions.ts new file mode 100644 index 00000000000000..176a3901821f19 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/filebeat_instructions.ts @@ -0,0 +1,569 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { INSTRUCTION_VARIANT } from './instruction_variant'; +import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; +import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; +import { Platform, TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +export const createFilebeatInstructions = (context?: TutorialContext) => ({ + INSTALL: { + OSX: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.install.osxTitle', { + defaultMessage: 'Download and install Filebeat', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.install.osxTextPre', { + defaultMessage: 'First time using Filebeat? See the [Getting Started Guide]({linkUrl}).', + values: { + linkUrl: '{config.docs.beats.filebeat}/filebeat-getting-started.html', + }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'tar xzvf filebeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'cd filebeat-{config.kibana.version}-darwin-x86_64/', + ], + }, + DEB: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.install.debTitle', { + defaultMessage: 'Download and install Filebeat', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.install.debTextPre', { + defaultMessage: 'First time using Filebeat? See the [Getting Started Guide]({linkUrl}).', + values: { + linkUrl: '{config.docs.beats.filebeat}/filebeat-getting-started.html', + }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-amd64.deb', + 'sudo dpkg -i filebeat-{config.kibana.version}-amd64.deb', + ], + textPost: i18n.translate('home.tutorials.common.filebeatInstructions.install.debTextPost', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({linkUrl}).', + values: { + linkUrl: 'https://www.elastic.co/downloads/beats/filebeat', + }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.install.rpmTitle', { + defaultMessage: 'Download and install Filebeat', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.install.rpmTextPre', { + defaultMessage: 'First time using Filebeat? See the [Getting Started Guide]({linkUrl}).', + values: { + linkUrl: '{config.docs.beats.filebeat}/filebeat-getting-started.html', + }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-x86_64.rpm', + 'sudo rpm -vi filebeat-{config.kibana.version}-x86_64.rpm', + ], + textPost: i18n.translate('home.tutorials.common.filebeatInstructions.install.rpmTextPost', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({linkUrl}).', + values: { + linkUrl: 'https://www.elastic.co/downloads/beats/filebeat', + }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.install.windowsTitle', { + defaultMessage: 'Download and install Filebeat', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.install.windowsTextPre', { + defaultMessage: + 'First time using Filebeat? See the [Getting Started Guide]({guideLinkUrl}).\n\ + 1. Download the Filebeat Windows zip file from the [Download]({filebeatLinkUrl}) page.\n\ + 2. Extract the contents of the zip file into {folderPath}.\n\ + 3. Rename the `{directoryName}` directory to `Filebeat`.\n\ + 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ +**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ + 5. From the PowerShell prompt, run the following commands to install Filebeat as a Windows service.', + values: { + folderPath: '`C:\\Program Files`', + guideLinkUrl: '{config.docs.beats.filebeat}/filebeat-getting-started.html', + filebeatLinkUrl: 'https://www.elastic.co/downloads/beats/filebeat', + directoryName: 'filebeat-{config.kibana.version}-windows', + }, + }), + commands: ['cd "C:\\Program Files\\Filebeat"', '.\\install-service-filebeat.ps1'], + textPost: i18n.translate( + 'home.tutorials.common.filebeatInstructions.install.windowsTextPost', + { + defaultMessage: + 'Modify the settings under {propertyName} in the {filebeatPath} file to point to your Elasticsearch installation.', + values: { + propertyName: '`output.elasticsearch`', + filebeatPath: '`C:\\Program Files\\Filebeat\\filebeat.yml`', + }, + } + ), + }, + }, + START: { + OSX: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.start.osxTitle', { + defaultMessage: 'Start Filebeat', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.start.osxTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['./filebeat setup', './filebeat -e'], + }, + DEB: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.start.debTitle', { + defaultMessage: 'Start Filebeat', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.start.debTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['sudo filebeat setup', 'sudo service filebeat start'], + }, + RPM: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.start.rpmTitle', { + defaultMessage: 'Start Filebeat', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.start.rpmTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['sudo filebeat setup', 'sudo service filebeat start'], + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.start.windowsTitle', { + defaultMessage: 'Start Filebeat', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.start.windowsTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['.\\filebeat.exe setup', 'Start-Service filebeat'], + }, + }, + CONFIG: { + OSX: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.config.osxTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`filebeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.filebeatInstructions.config.osxTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + DEB: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.config.debTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.config.debTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`/etc/filebeat/filebeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.filebeatInstructions.config.debTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.config.rpmTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.config.rpmTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`/etc/filebeat/filebeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.filebeatInstructions.config.rpmTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.filebeatInstructions.config.windowsTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.filebeatInstructions.config.windowsTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`C:\\Program Files\\Filebeat\\filebeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate( + 'home.tutorials.common.filebeatInstructions.config.windowsTextPost', + { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + } + ), + }, + }, +}); + +export const createFilebeatCloudInstructions = () => ({ + CONFIG: { + OSX: { + title: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.osxTextPre', { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`filebeat.yml`', + }, + }), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.filebeatCloudInstructions.config.osxTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + DEB: { + title: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.debTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.debTextPre', { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`/etc/filebeat/filebeat.yml`', + }, + }), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.filebeatCloudInstructions.config.debTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + RPM: { + title: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.rpmTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.rpmTextPre', { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`/etc/filebeat/filebeat.yml`', + }, + }), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.filebeatCloudInstructions.config.rpmTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.windowsTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.filebeatCloudInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`C:\\Program Files\\Filebeat\\filebeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.filebeatCloudInstructions.config.windowsTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + }, +}); + +export function filebeatEnableInstructions(moduleName: string) { + return { + OSX: { + title: i18n.translate('home.tutorials.common.filebeatEnableInstructions.osxTitle', { + defaultMessage: 'Enable and configure the {moduleName} module', + values: { moduleName }, + }), + textPre: i18n.translate('home.tutorials.common.filebeatEnableInstructions.osxTextPre', { + defaultMessage: 'From the installation directory, run:', + }), + commands: ['./filebeat modules enable ' + moduleName], + textPost: i18n.translate('home.tutorials.common.filebeatEnableInstructions.osxTextPost', { + defaultMessage: 'Modify the settings in the `modules.d/{moduleName}.yml` file.', + values: { moduleName }, + }), + }, + DEB: { + title: i18n.translate('home.tutorials.common.filebeatEnableInstructions.debTitle', { + defaultMessage: 'Enable and configure the {moduleName} module', + values: { moduleName }, + }), + commands: ['sudo filebeat modules enable ' + moduleName], + textPost: i18n.translate('home.tutorials.common.filebeatEnableInstructions.debTextPost', { + defaultMessage: + 'Modify the settings in the `/etc/filebeat/modules.d/{moduleName}.yml` file.', + values: { moduleName }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.filebeatEnableInstructions.rpmTitle', { + defaultMessage: 'Enable and configure the {moduleName} module', + values: { moduleName }, + }), + commands: ['sudo filebeat modules enable ' + moduleName], + textPost: i18n.translate('home.tutorials.common.filebeatEnableInstructions.rpmTextPost', { + defaultMessage: + 'Modify the settings in the `/etc/filebeat/modules.d/{moduleName}.yml` file.', + values: { moduleName }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.filebeatEnableInstructions.windowsTitle', { + defaultMessage: 'Enable and configure the {moduleName} module', + values: { moduleName }, + }), + textPre: i18n.translate('home.tutorials.common.filebeatEnableInstructions.windowsTextPre', { + defaultMessage: 'From the {path} folder, run:', + values: { path: `C:\\Program Files\\Filebeat` }, + }), + commands: ['filebeat.exe modules enable ' + moduleName], + textPost: i18n.translate('home.tutorials.common.filebeatEnableInstructions.windowsTextPost', { + defaultMessage: 'Modify the settings in the `modules.d/{moduleName}.yml` file.', + values: { moduleName }, + }), + }, + }; +} + +export function filebeatStatusCheck(moduleName: string) { + return { + title: i18n.translate('home.tutorials.common.filebeatStatusCheck.title', { + defaultMessage: 'Module status', + }), + text: i18n.translate('home.tutorials.common.filebeatStatusCheck.text', { + defaultMessage: 'Check that data is received from the Filebeat `{moduleName}` module', + values: { moduleName }, + }), + btnLabel: i18n.translate('home.tutorials.common.filebeatStatusCheck.buttonLabel', { + defaultMessage: 'Check data', + }), + success: i18n.translate('home.tutorials.common.filebeatStatusCheck.successText', { + defaultMessage: 'Data successfully received from this module', + }), + error: i18n.translate('home.tutorials.common.filebeatStatusCheck.errorText', { + defaultMessage: 'No data has been received from this module yet', + }), + esHitsCheck: { + index: 'filebeat-*', + query: { + bool: { + filter: { + term: { + 'event.module': moduleName, + }, + }, + }, + }, + }, + }; +} + +export function onPremInstructions( + moduleName: string, + platforms: readonly Platform[] = [], + context?: TutorialContext +) { + const FILEBEAT_INSTRUCTIONS = createFilebeatInstructions(context); + + const variants = []; + for (let i = 0; i < platforms.length; i++) { + const platform = platforms[i]; + const instructions = []; + instructions.push(FILEBEAT_INSTRUCTIONS.INSTALL[platform]); + instructions.push(FILEBEAT_INSTRUCTIONS.CONFIG[platform]); + instructions.push(filebeatEnableInstructions(moduleName)[platform]); + instructions.push(FILEBEAT_INSTRUCTIONS.START[platform]); + variants.push({ + id: INSTRUCTION_VARIANT[platform], + instructions, + }); + } + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.filebeat.premInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: variants, + statusCheck: filebeatStatusCheck(moduleName), + }, + ], + }; +} + +export function onPremCloudInstructions(moduleName: string, platforms: readonly Platform[] = []) { + const FILEBEAT_INSTRUCTIONS = createFilebeatInstructions(); + const TRYCLOUD_OPTION1 = createTrycloudOption1(); + const TRYCLOUD_OPTION2 = createTrycloudOption2(); + + const variants = []; + for (let i = 0; i < platforms.length; i++) { + const platform = platforms[i]; + variants.push({ + id: INSTRUCTION_VARIANT[platform], + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + FILEBEAT_INSTRUCTIONS.INSTALL[platform], + FILEBEAT_INSTRUCTIONS.CONFIG[platform], + filebeatEnableInstructions(moduleName)[platform], + FILEBEAT_INSTRUCTIONS.START[platform], + ], + }); + } + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.filebeat.premCloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: variants, + statusCheck: filebeatStatusCheck(moduleName), + }, + ], + }; +} + +export function cloudInstructions(moduleName: string, platforms: readonly Platform[] = []) { + const FILEBEAT_INSTRUCTIONS = createFilebeatInstructions(); + const FILEBEAT_CLOUD_INSTRUCTIONS = createFilebeatCloudInstructions(); + + const variants = []; + for (let i = 0; i < platforms.length; i++) { + const platform = platforms[i]; + variants.push({ + id: INSTRUCTION_VARIANT[platform], + instructions: [ + FILEBEAT_INSTRUCTIONS.INSTALL[platform], + FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG[platform], + filebeatEnableInstructions(moduleName)[platform], + FILEBEAT_INSTRUCTIONS.START[platform], + ], + }); + } + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.filebeat.cloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: variants, + statusCheck: filebeatStatusCheck(moduleName), + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/instructions/functionbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/functionbeat_instructions.ts new file mode 100644 index 00000000000000..385880ba9780f8 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/functionbeat_instructions.ts @@ -0,0 +1,513 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { INSTRUCTION_VARIANT } from './instruction_variant'; +import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; +import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; +import { Platform, TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +export const createFunctionbeatInstructions = (context?: TutorialContext) => ({ + INSTALL: { + OSX: { + title: i18n.translate('home.tutorials.common.functionbeatInstructions.install.osxTitle', { + defaultMessage: 'Download and install Functionbeat', + }), + textPre: i18n.translate('home.tutorials.common.functionbeatInstructions.install.osxTextPre', { + defaultMessage: 'First time using Functionbeat? See the [Getting Started Guide]({link}).', + values: { link: '{config.docs.beats.functionbeat}/functionbeat-getting-started.html' }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/functionbeat/functionbeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'tar xzvf functionbeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'cd functionbeat-{config.kibana.version}-darwin-x86_64/', + ], + }, + LINUX: { + title: i18n.translate('home.tutorials.common.functionbeatInstructions.install.linuxTitle', { + defaultMessage: 'Download and install Functionbeat', + }), + textPre: i18n.translate( + 'home.tutorials.common.functionbeatInstructions.install.linuxTextPre', + { + defaultMessage: 'First time using Functionbeat? See the [Getting Started Guide]({link}).', + values: { link: '{config.docs.beats.functionbeat}/functionbeat-getting-started.html' }, + } + ), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/functionbeat/functionbeat-{config.kibana.version}-linux-x86_64.tar.gz', + 'tar xzvf functionbeat-{config.kibana.version}-linux-x86_64.tar.gz', + 'cd functionbeat-{config.kibana.version}-linux-x86_64/', + ], + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.functionbeatInstructions.install.windowsTitle', { + defaultMessage: 'Download and install Functionbeat', + }), + textPre: i18n.translate( + 'home.tutorials.common.functionbeatInstructions.install.windowsTextPre', + { + defaultMessage: + 'First time using Functionbeat? See the [Getting Started Guide]({functionbeatLink}).\n\ + 1. Download the Functionbeat Windows zip file from the [Download]({elasticLink}) page.\n\ + 2. Extract the contents of the zip file into {folderPath}.\n\ + 3. Rename the {directoryName} directory to `Functionbeat`.\n\ + 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ +**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ + 5. From the PowerShell prompt, go to the Functionbeat directory:', + values: { + directoryName: '`functionbeat-{config.kibana.version}-windows`', + folderPath: '`C:\\Program Files`', + functionbeatLink: '{config.docs.beats.functionbeat}/functionbeat-getting-started.html', + elasticLink: 'https://www.elastic.co/downloads/beats/functionbeat', + }, + } + ), + commands: ['cd "C:\\Program Files\\Functionbeat"'], + }, + }, + DEPLOY: { + OSX_LINUX: { + title: i18n.translate('home.tutorials.common.functionbeatInstructions.deploy.osxTitle', { + defaultMessage: 'Deploy Functionbeat to AWS Lambda', + }), + textPre: i18n.translate('home.tutorials.common.functionbeatInstructions.deploy.osxTextPre', { + defaultMessage: + 'This installs Functionbeat as a Lambda function.\ +The `setup` command checks the Elasticsearch configuration and loads the \ +Kibana index pattern. It is normally safe to omit this command.', + }), + commands: ['./functionbeat setup', './functionbeat deploy fn-cloudwatch-logs'], + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.functionbeatInstructions.deploy.windowsTitle', { + defaultMessage: 'Deploy Functionbeat to AWS Lambda', + }), + textPre: i18n.translate( + 'home.tutorials.common.functionbeatInstructions.deploy.windowsTextPre', + { + defaultMessage: + 'This installs Functionbeat as a Lambda function.\ +The `setup` command checks the Elasticsearch configuration and loads the \ +Kibana index pattern. It is normally safe to omit this command.', + } + ), + commands: ['.\\functionbeat.exe setup', '.\\functionbeat.exe deploy fn-cloudwatch-logs'], + }, + }, + CONFIG: { + OSX_LINUX: { + title: i18n.translate('home.tutorials.common.functionbeatInstructions.config.osxTitle', { + defaultMessage: 'Configure the Elastic cluster', + }), + textPre: i18n.translate('home.tutorials.common.functionbeatInstructions.config.osxTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`functionbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate( + 'home.tutorials.common.functionbeatInstructions.config.osxTextPost', + { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + } + ), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.functionbeatInstructions.config.windowsTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.functionbeatInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`C:\\Program Files\\Functionbeat\\functionbeat.yml`', + }, + } + ), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate( + 'home.tutorials.common.functionbeatInstructions.config.windowsTextPost', + { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + } + ), + }, + }, +}); + +export const createFunctionbeatCloudInstructions = () => ({ + CONFIG: { + OSX_LINUX: { + title: i18n.translate('home.tutorials.common.functionbeatCloudInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.functionbeatCloudInstructions.config.osxTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`functionbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.functionbeatCloudInstructions.config.osxTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + WINDOWS: { + title: i18n.translate( + 'home.tutorials.common.functionbeatCloudInstructions.config.windowsTitle', + { + defaultMessage: 'Edit the configuration', + } + ), + textPre: i18n.translate( + 'home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`C:\\Program Files\\Functionbeat\\functionbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + }, +}); + +export function functionbeatEnableInstructions() { + const defaultTitle = i18n.translate( + 'home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTitle', + { + defaultMessage: 'Configure the Cloudwatch log group', + } + ); + const defaultCommands = [ + 'functionbeat.provider.aws.functions:', + ' - name: fn-cloudwatch-logs', + ' enabled: true', + ' type: cloudwatch_logs', + ' triggers:', + ' - log_group_name: ', + 'functionbeat.provider.aws.deploy_bucket: ', + ]; + const defaultTextPost = i18n.translate( + 'home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTextPost', + { + defaultMessage: + 'Where `` is the name of the log group you want to ingest, \ +and `` is a valid S3 bucket name which will be used for staging the \ +Functionbeat deploy.', + } + ); + return { + OSX_LINUX: { + title: defaultTitle, + textPre: i18n.translate( + 'home.tutorials.common.functionbeatEnableOnPremInstructionsOSXLinux.textPre', + { + defaultMessage: 'Modify the settings in the `functionbeat.yml` file.', + } + ), + commands: defaultCommands, + textPost: defaultTextPost, + }, + WINDOWS: { + title: defaultTitle, + textPre: i18n.translate( + 'home.tutorials.common.functionbeatEnableOnPremInstructionsWindows.textPre', + { + defaultMessage: 'Modify the settings in the {path} file.', + values: { + path: '`C:\\Program Files\\Functionbeat\\functionbeat.yml`', + }, + } + ), + commands: defaultCommands, + textPost: defaultTextPost, + }, + }; +} + +export function functionbeatAWSInstructions() { + const defaultTitle = i18n.translate('home.tutorials.common.functionbeatAWSInstructions.title', { + defaultMessage: 'Set AWS credentials', + }); + const defaultPre = i18n.translate('home.tutorials.common.functionbeatAWSInstructions.textPre', { + defaultMessage: 'Set your AWS account credentials in the environment:', + }); + const defaultPost = i18n.translate('home.tutorials.common.functionbeatAWSInstructions.textPost', { + defaultMessage: + 'Where `` and `` are your account credentials and \ +`us-east-1` is the desired region.', + }); + + return { + OSX_LINUX: { + title: defaultTitle, + textPre: defaultPre, + commands: [ + 'export AWS_ACCESS_KEY_ID=', + 'export AWS_SECRET_ACCESS_KEY=', + 'export AWS_DEFAULT_REGION=us-east-1', + ], + textPost: defaultPost, + }, + WINDOWS: { + title: defaultTitle, + textPre: defaultPre, + commands: [ + 'set AWS_ACCESS_KEY_ID=', + 'set AWS_SECRET_ACCESS_KEY=', + 'set AWS_DEFAULT_REGION=us-east-1', + ], + textPost: defaultPost, + }, + }; +} + +export function functionbeatStatusCheck() { + return { + title: i18n.translate('home.tutorials.common.functionbeatStatusCheck.title', { + defaultMessage: 'Functionbeat status', + }), + text: i18n.translate('home.tutorials.common.functionbeatStatusCheck.text', { + defaultMessage: 'Check that data is received from Functionbeat', + }), + btnLabel: i18n.translate('home.tutorials.common.functionbeatStatusCheck.buttonLabel', { + defaultMessage: 'Check data', + }), + success: i18n.translate('home.tutorials.common.functionbeatStatusCheck.successText', { + defaultMessage: 'Data successfully received from Functionbeat', + }), + error: i18n.translate('home.tutorials.common.functionbeatStatusCheck.errorText', { + defaultMessage: 'No data has been received from Functionbeat yet', + }), + esHitsCheck: { + index: 'functionbeat-*', + query: { + match_all: {}, + }, + }, + }; +} + +export function onPremInstructions(platforms: Platform[], context?: TutorialContext) { + const FUNCTIONBEAT_INSTRUCTIONS = createFunctionbeatInstructions(context); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.functionbeat.premInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.OSX, + functionbeatAWSInstructions().OSX_LINUX, + functionbeatEnableInstructions().OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.CONFIG.OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, + ], + }, + { + id: INSTRUCTION_VARIANT.LINUX, + instructions: [ + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.LINUX, + functionbeatAWSInstructions().OSX_LINUX, + functionbeatEnableInstructions().OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.CONFIG.OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + functionbeatAWSInstructions().WINDOWS, + functionbeatEnableInstructions().WINDOWS, + FUNCTIONBEAT_INSTRUCTIONS.CONFIG.WINDOWS, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.WINDOWS, + ], + }, + ], + statusCheck: functionbeatStatusCheck(), + }, + ], + }; +} + +export function onPremCloudInstructions() { + const TRYCLOUD_OPTION1 = createTrycloudOption1(); + const TRYCLOUD_OPTION2 = createTrycloudOption2(); + const FUNCTIONBEAT_INSTRUCTIONS = createFunctionbeatInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.functionbeat.premCloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.OSX, + functionbeatAWSInstructions().OSX_LINUX, + functionbeatEnableInstructions().OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.CONFIG.OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, + ], + }, + { + id: INSTRUCTION_VARIANT.LINUX, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.LINUX, + functionbeatAWSInstructions().OSX_LINUX, + functionbeatEnableInstructions().OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.CONFIG.OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + functionbeatAWSInstructions().WINDOWS, + functionbeatEnableInstructions().WINDOWS, + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + FUNCTIONBEAT_INSTRUCTIONS.CONFIG.WINDOWS, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.WINDOWS, + ], + }, + ], + statusCheck: functionbeatStatusCheck(), + }, + ], + }; +} + +export function cloudInstructions() { + const FUNCTIONBEAT_INSTRUCTIONS = createFunctionbeatInstructions(); + const FUNCTIONBEAT_CLOUD_INSTRUCTIONS = createFunctionbeatCloudInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.functionbeat.cloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.OSX, + functionbeatAWSInstructions().OSX_LINUX, + functionbeatEnableInstructions().OSX_LINUX, + FUNCTIONBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, + ], + }, + { + id: INSTRUCTION_VARIANT.LINUX, + instructions: [ + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.LINUX, + functionbeatAWSInstructions().OSX_LINUX, + functionbeatEnableInstructions().OSX_LINUX, + FUNCTIONBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX_LINUX, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.OSX_LINUX, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + FUNCTIONBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + functionbeatAWSInstructions().WINDOWS, + functionbeatEnableInstructions().WINDOWS, + FUNCTIONBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS, + FUNCTIONBEAT_INSTRUCTIONS.DEPLOY.WINDOWS, + ], + }, + ], + statusCheck: functionbeatStatusCheck(), + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/instructions/get_space_id_for_beats_tutorial.ts b/src/plugins/home/server/tutorials/instructions/get_space_id_for_beats_tutorial.ts new file mode 100644 index 00000000000000..894ffc6b126d60 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/get_space_id_for_beats_tutorial.ts @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +/** + * Returns valid configuration for a beat.yml file for adding the space id + * if there is an active space and that space is not the default one. + * + * @param {object} context - Context object generated from tutorial factory (see #22760) + */ +export function getSpaceIdForBeatsTutorial(context?: TutorialContext) { + if (!context || !context.spaceId || context.isInDefaultSpace) { + return ''; + } + + return ` space.id: "${context.spaceId}"`; +} diff --git a/src/plugins/home/server/tutorials/instructions/heartbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/heartbeat_instructions.ts new file mode 100644 index 00000000000000..406bf55da43218 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/heartbeat_instructions.ts @@ -0,0 +1,699 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { INSTRUCTION_VARIANT } from './instruction_variant'; +import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; +import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; +import { Platform, TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +export const createHeartbeatInstructions = (context?: TutorialContext) => ({ + INSTALL: { + OSX: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.install.osxTitle', { + defaultMessage: 'Download and install Heartbeat', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.install.osxTextPre', { + defaultMessage: 'First time using Heartbeat? See the [Getting Started Guide]({link}).', + values: { link: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html' }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'tar xzvf heartbeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'cd heartbeat-{config.kibana.version}-darwin-x86_64/', + ], + }, + DEB: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.install.debTitle', { + defaultMessage: 'Download and install Heartbeat', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.install.debTextPre', { + defaultMessage: 'First time using Heartbeat? See the [Getting Started Guide]({link}).', + values: { link: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html' }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-{config.kibana.version}-amd64.deb', + 'sudo dpkg -i heartbeat-{config.kibana.version}-amd64.deb', + ], + textPost: i18n.translate('home.tutorials.common.heartbeatInstructions.install.debTextPost', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({link}).', + values: { link: 'https://www.elastic.co/downloads/beats/heartbeat' }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.install.rpmTitle', { + defaultMessage: 'Download and install Heartbeat', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.install.rpmTextPre', { + defaultMessage: 'First time using Heartbeat? See the [Getting Started Guide]({link}).', + values: { link: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html' }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-{config.kibana.version}-x86_64.rpm', + 'sudo rpm -vi heartbeat-{config.kibana.version}-x86_64.rpm', + ], + textPost: i18n.translate('home.tutorials.common.heartbeatInstructions.install.debTextPost', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({link}).', + values: { link: 'https://www.elastic.co/downloads/beats/heartbeat' }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.install.windowsTitle', { + defaultMessage: 'Download and install Heartbeat', + }), + textPre: i18n.translate( + 'home.tutorials.common.heartbeatInstructions.install.windowsTextPre', + { + defaultMessage: + 'First time using Heartbeat? See the [Getting Started Guide]({heartbeatLink}).\n\ + 1. Download the Heartbeat Windows zip file from the [Download]({elasticLink}) page.\n\ + 2. Extract the contents of the zip file into {folderPath}.\n\ + 3. Rename the {directoryName} directory to `Heartbeat`.\n\ + 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ +**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ + 5. From the PowerShell prompt, run the following commands to install Heartbeat as a Windows service.', + values: { + directoryName: '`heartbeat-{config.kibana.version}-windows`', + folderPath: '`C:\\Program Files`', + heartbeatLink: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html', + elasticLink: 'https://www.elastic.co/downloads/beats/heartbeat', + }, + } + ), + commands: ['cd "C:\\Program Files\\Heartbeat"', '.\\install-service-heartbeat.ps1'], + }, + }, + START: { + OSX: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.start.osxTitle', { + defaultMessage: 'Start Heartbeat', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.start.osxTextPre', { + defaultMessage: 'The `setup` command loads the Kibana index pattern.', + }), + commands: ['./heartbeat setup', './heartbeat -e'], + }, + DEB: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.start.debTitle', { + defaultMessage: 'Start Heartbeat', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.start.debTextPre', { + defaultMessage: 'The `setup` command loads the Kibana index pattern.', + }), + commands: ['sudo heartbeat setup', 'sudo service heartbeat-elastic start'], + }, + RPM: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.start.rpmTitle', { + defaultMessage: 'Start Heartbeat', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.start.rpmTextPre', { + defaultMessage: 'The `setup` command loads the Kibana index pattern.', + }), + commands: ['sudo heartbeat setup', 'sudo service heartbeat-elastic start'], + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.start.windowsTitle', { + defaultMessage: 'Start Heartbeat', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.start.windowsTextPre', { + defaultMessage: 'The `setup` command loads the Kibana index pattern.', + }), + commands: ['.\\heartbeat.exe setup', 'Start-Service heartbeat'], + }, + }, + CONFIG: { + OSX: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.config.osxTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`heartbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.heartbeatInstructions.config.osxTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + DEB: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.config.debTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.config.debTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`/etc/heartbeat/heartbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.heartbeatInstructions.config.debTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.config.rpmTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.config.rpmTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`/etc/heartbeat/heartbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.heartbeatInstructions.config.rpmTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.heartbeatInstructions.config.windowsTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.heartbeatInstructions.config.windowsTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`C:\\Program Files\\Heartbeat\\heartbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate( + 'home.tutorials.common.heartbeatInstructions.config.windowsTextPost', + { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + } + ), + }, + }, +}); + +export const createHeartbeatCloudInstructions = () => ({ + CONFIG: { + OSX: { + title: i18n.translate('home.tutorials.common.heartbeatCloudInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.osxTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`heartbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.osxTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + DEB: { + title: i18n.translate('home.tutorials.common.heartbeatCloudInstructions.config.debTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.debTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`/etc/heartbeat/heartbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.debTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + RPM: { + title: i18n.translate('home.tutorials.common.heartbeatCloudInstructions.config.rpmTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`/etc/heartbeat/heartbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + WINDOWS: { + title: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.windowsTitle', + { + defaultMessage: 'Edit the configuration', + } + ), + textPre: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`C:\\Program Files\\Heartbeat\\heartbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + }, +}); + +export function heartbeatEnableInstructionsOnPrem() { + const defaultTitle = i18n.translate( + 'home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTitle', + { + defaultMessage: 'Edit the configuration - Add monitors', + } + ); + const defaultCommands = [ + 'heartbeat.monitors:', + '- type: http', + ' urls: [""]', + ' schedule: "@every 10s"', + ]; + const defaultTextPost = i18n.translate( + 'home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTextPost', + { + defaultMessage: + 'Where {hostTemplate} is your monitored URL, For more details on how to configure Monitors in \ + Heartbeat, read the [Heartbeat configuration docs.]({configureLink})', + values: { + configureLink: '{config.docs.beats.heartbeat}/heartbeat-configuration.html', + hostTemplate: '``', + }, + } + ); + return { + OSX: { + title: defaultTitle, + textPre: i18n.translate( + 'home.tutorials.common.heartbeatEnableOnPremInstructions.osxTextPre', + { + defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', + } + ), + commands: defaultCommands, + textPost: defaultTextPost, + }, + DEB: { + title: defaultTitle, + textPre: i18n.translate( + 'home.tutorials.common.heartbeatEnableOnPremInstructions.debTextPre', + { + defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', + } + ), + commands: defaultCommands, + textPost: defaultTextPost, + }, + RPM: { + title: defaultTitle, + textPre: i18n.translate( + 'home.tutorials.common.heartbeatEnableOnPremInstructions.rpmTextPre', + { + defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', + } + ), + commands: defaultCommands, + textPost: defaultTextPost, + }, + WINDOWS: { + title: defaultTitle, + textPre: i18n.translate( + 'home.tutorials.common.heartbeatEnableOnPremInstructions.windowsTextPre', + { + defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', + } + ), + commands: defaultCommands, + textPost: defaultTextPost, + }, + }; +} + +export function heartbeatEnableInstructionsCloud() { + const defaultTitle = i18n.translate( + 'home.tutorials.common.heartbeatEnableCloudInstructions.defaultTitle', + { + defaultMessage: 'Edit the configuration - Add monitors', + } + ); + const defaultCommands = [ + 'heartbeat.monitors:', + '- type: http', + ' urls: ["http://elastic.co"]', + ' schedule: "@every 10s"', + ]; + const defaultTextPost = i18n.translate( + 'home.tutorials.common.heartbeatEnableCloudInstructions.defaultTextPost', + { + defaultMessage: + 'For more details on how to configure Monitors in Heartbeat, read the [Heartbeat configuration docs.]({configureLink})', + values: { configureLink: '{config.docs.beats.heartbeat}/heartbeat-configuration.html' }, + } + ); + return { + OSX: { + title: defaultTitle, + textPre: i18n.translate('home.tutorials.common.heartbeatEnableCloudInstructions.osxTextPre', { + defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', + }), + commands: defaultCommands, + textPost: defaultTextPost, + }, + DEB: { + title: defaultTitle, + textPre: i18n.translate('home.tutorials.common.heartbeatEnableCloudInstructions.debTextPre', { + defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', + }), + commands: defaultCommands, + textPost: defaultTextPost, + }, + RPM: { + title: defaultTitle, + textPre: i18n.translate('home.tutorials.common.heartbeatEnableCloudInstructions.rpmTextPre', { + defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', + }), + commands: defaultCommands, + textPost: defaultTextPost, + }, + WINDOWS: { + title: defaultTitle, + textPre: i18n.translate( + 'home.tutorials.common.heartbeatEnableCloudInstructions.windowsTextPre', + { + defaultMessage: 'Edit the `heartbeat.monitors` setting in the `heartbeat.yml` file.', + } + ), + commands: defaultCommands, + textPost: defaultTextPost, + }, + }; +} + +export function heartbeatStatusCheck() { + return { + title: i18n.translate('home.tutorials.common.heartbeatStatusCheck.title', { + defaultMessage: 'Heartbeat status', + }), + text: i18n.translate('home.tutorials.common.heartbeatStatusCheck.text', { + defaultMessage: 'Check that data is received from Heartbeat', + }), + btnLabel: i18n.translate('home.tutorials.common.heartbeatStatusCheck.buttonLabel', { + defaultMessage: 'Check data', + }), + success: i18n.translate('home.tutorials.common.heartbeatStatusCheck.successText', { + defaultMessage: 'Data successfully received from Heartbeat', + }), + error: i18n.translate('home.tutorials.common.heartbeatStatusCheck.errorText', { + defaultMessage: 'No data has been received from Heartbeat yet', + }), + esHitsCheck: { + index: 'heartbeat-*', + query: { + match_all: {}, + }, + }, + }; +} + +export function onPremInstructions(platforms: Platform[], context?: TutorialContext) { + const HEARTBEAT_INSTRUCTIONS = createHeartbeatInstructions(context); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.heartbeat.premInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + HEARTBEAT_INSTRUCTIONS.INSTALL.OSX, + HEARTBEAT_INSTRUCTIONS.CONFIG.OSX, + heartbeatEnableInstructionsOnPrem().OSX, + HEARTBEAT_INSTRUCTIONS.START.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [ + HEARTBEAT_INSTRUCTIONS.INSTALL.DEB, + HEARTBEAT_INSTRUCTIONS.CONFIG.DEB, + heartbeatEnableInstructionsOnPrem().DEB, + HEARTBEAT_INSTRUCTIONS.START.DEB, + ], + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [ + HEARTBEAT_INSTRUCTIONS.INSTALL.RPM, + HEARTBEAT_INSTRUCTIONS.CONFIG.RPM, + heartbeatEnableInstructionsOnPrem().RPM, + HEARTBEAT_INSTRUCTIONS.START.RPM, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + HEARTBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + HEARTBEAT_INSTRUCTIONS.CONFIG.WINDOWS, + heartbeatEnableInstructionsOnPrem().WINDOWS, + HEARTBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: heartbeatStatusCheck(), + }, + ], + }; +} + +export function onPremCloudInstructions() { + const TRYCLOUD_OPTION1 = createTrycloudOption1(); + const TRYCLOUD_OPTION2 = createTrycloudOption2(); + const HEARTBEAT_INSTRUCTIONS = createHeartbeatInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.heartbeat.premCloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + HEARTBEAT_INSTRUCTIONS.INSTALL.OSX, + HEARTBEAT_INSTRUCTIONS.CONFIG.OSX, + heartbeatEnableInstructionsCloud().OSX, + HEARTBEAT_INSTRUCTIONS.START.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + HEARTBEAT_INSTRUCTIONS.INSTALL.DEB, + HEARTBEAT_INSTRUCTIONS.CONFIG.DEB, + heartbeatEnableInstructionsCloud().DEB, + HEARTBEAT_INSTRUCTIONS.START.DEB, + ], + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + HEARTBEAT_INSTRUCTIONS.INSTALL.RPM, + HEARTBEAT_INSTRUCTIONS.CONFIG.RPM, + heartbeatEnableInstructionsCloud().RPM, + HEARTBEAT_INSTRUCTIONS.START.RPM, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + HEARTBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + HEARTBEAT_INSTRUCTIONS.CONFIG.WINDOWS, + heartbeatEnableInstructionsCloud().WINDOWS, + HEARTBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: heartbeatStatusCheck(), + }, + ], + }; +} + +export function cloudInstructions() { + const HEARTBEAT_INSTRUCTIONS = createHeartbeatInstructions(); + const HEARTBEAT_CLOUD_INSTRUCTIONS = createHeartbeatCloudInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.heartbeat.cloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + HEARTBEAT_INSTRUCTIONS.INSTALL.OSX, + HEARTBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX, + heartbeatEnableInstructionsCloud().OSX, + HEARTBEAT_INSTRUCTIONS.START.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [ + HEARTBEAT_INSTRUCTIONS.INSTALL.DEB, + HEARTBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB, + heartbeatEnableInstructionsCloud().DEB, + HEARTBEAT_INSTRUCTIONS.START.DEB, + ], + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [ + HEARTBEAT_INSTRUCTIONS.INSTALL.RPM, + HEARTBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM, + heartbeatEnableInstructionsCloud().RPM, + HEARTBEAT_INSTRUCTIONS.START.RPM, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + HEARTBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + HEARTBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS, + heartbeatEnableInstructionsCloud().WINDOWS, + HEARTBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: heartbeatStatusCheck(), + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/instructions/instruction_variant.ts b/src/plugins/home/server/tutorials/instructions/instruction_variant.ts new file mode 100644 index 00000000000000..d026a3bdf22084 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/instruction_variant.ts @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const INSTRUCTION_VARIANT = { + ESC: 'esc', + OSX: 'osx', + DEB: 'deb', + RPM: 'rpm', + DOCKER: 'docker', + WINDOWS: 'windows', + NODE: 'node', + DJANGO: 'django', + FLASK: 'flask', + RAILS: 'rails', + RACK: 'rack', + JS: 'js', + GO: 'go', + JAVA: 'java', + DOTNET: 'dotnet', + LINUX: 'linux', +}; + +const DISPLAY_MAP = { + [INSTRUCTION_VARIANT.ESC]: 'Elastic Cloud', + [INSTRUCTION_VARIANT.OSX]: 'macOS', + [INSTRUCTION_VARIANT.DEB]: 'DEB', + [INSTRUCTION_VARIANT.RPM]: 'RPM', + [INSTRUCTION_VARIANT.DOCKER]: 'Docker', + [INSTRUCTION_VARIANT.WINDOWS]: 'Windows', + [INSTRUCTION_VARIANT.NODE]: 'Node.js', + [INSTRUCTION_VARIANT.DJANGO]: 'Django', + [INSTRUCTION_VARIANT.FLASK]: 'Flask', + [INSTRUCTION_VARIANT.RAILS]: 'Ruby on Rails', + [INSTRUCTION_VARIANT.RACK]: 'Rack', + [INSTRUCTION_VARIANT.JS]: 'RUM (JS)', + [INSTRUCTION_VARIANT.GO]: 'Go', + [INSTRUCTION_VARIANT.JAVA]: 'Java', + [INSTRUCTION_VARIANT.DOTNET]: '.NET', + [INSTRUCTION_VARIANT.LINUX]: 'Linux', +}; + +/** + * Convert instruction variant id into display text. + * + * @params {String} id - instruction variant id as defined from INSTRUCTION_VARIANT + * @return {String} display name + */ +export function getDisplayText(id: keyof typeof INSTRUCTION_VARIANT) { + if (id in DISPLAY_MAP) { + return DISPLAY_MAP[id]; + } + return id; +} diff --git a/src/plugins/home/server/tutorials/instructions/logstash_instructions.ts b/src/plugins/home/server/tutorials/instructions/logstash_instructions.ts new file mode 100644 index 00000000000000..3e5345565a7534 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/logstash_instructions.ts @@ -0,0 +1,106 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +export const createLogstashInstructions = () => ({ + INSTALL: { + OSX: [ + { + title: i18n.translate('home.tutorials.common.logstashInstructions.install.java.osxTitle', { + defaultMessage: 'Download and install the Java Runtime Environment', + }), + textPre: i18n.translate( + 'home.tutorials.common.logstashInstructions.install.java.osxTextPre', + { + defaultMessage: 'Follow the installation instructions [here]({link}).', + values: { + link: 'https://docs.oracle.com/javase/8/docs/technotes/guides/install/mac_jre.html', + }, + } + ), + }, + { + title: i18n.translate( + 'home.tutorials.common.logstashInstructions.install.logstash.osxTitle', + { + defaultMessage: 'Download and install Logstash', + } + ), + textPre: i18n.translate( + 'home.tutorials.common.logstashInstructions.install.logstash.osxTextPre', + { + defaultMessage: 'First time using Logstash? See the [Getting Started Guide]({link}).', + values: { + link: + '{config.docs.base_url}guide/en/logstash/current/getting-started-with-logstash.html', + }, + } + ), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/logstash/logstash-{config.kibana.version}.tar.gz', + 'tar xzvf logstash-{config.kibana.version}.tar.gz', + ], + }, + ], + WINDOWS: [ + { + title: i18n.translate( + 'home.tutorials.common.logstashInstructions.install.java.windowsTitle', + { + defaultMessage: 'Download and install the Java Runtime Environment', + } + ), + textPre: i18n.translate( + 'home.tutorials.common.logstashInstructions.install.java.windowsTextPre', + { + defaultMessage: 'Follow the installation instructions [here]({link}).', + values: { + link: + 'https://docs.oracle.com/javase/8/docs/technotes/guides/install/windows_jre_install.html', + }, + } + ), + }, + { + title: i18n.translate( + 'home.tutorials.common.logstashInstructions.install.logstash.windowsTitle', + { + defaultMessage: 'Download and install Logstash', + } + ), + textPre: i18n.translate( + 'home.tutorials.common.logstashInstructions.install.logstash.windowsTextPre', + { + defaultMessage: + 'First time using Logstash? See the [Getting Started Guide]({logstashLink}).\n\ + 1. [Download]({elasticLink}) the Logstash Windows zip file.\n\ + 2. Extract the contents of the zip file.', + values: { + logstashLink: + '{config.docs.base_url}guide/en/logstash/current/getting-started-with-logstash.html', + elasticLink: + 'https://artifacts.elastic.co/downloads/logstash/logstash-{config.kibana.version}.zip', + }, + } + ), + }, + ], + }, +}); diff --git a/src/plugins/home/server/tutorials/instructions/metricbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/metricbeat_instructions.ts new file mode 100644 index 00000000000000..77efe0958a6153 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/metricbeat_instructions.ts @@ -0,0 +1,649 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { INSTRUCTION_VARIANT } from './instruction_variant'; +import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; +import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; +import { TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +export const createMetricbeatInstructions = (context?: TutorialContext) => ({ + INSTALL: { + OSX: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.install.osxTitle', { + defaultMessage: 'Download and install Metricbeat', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.install.osxTextPre', { + defaultMessage: 'First time using Metricbeat? See the [Getting Started Guide]({link}).', + values: { link: '{config.docs.beats.metricbeat}/metricbeat-getting-started.html' }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'tar xzvf metricbeat-{config.kibana.version}-darwin-x86_64.tar.gz', + 'cd metricbeat-{config.kibana.version}-darwin-x86_64/', + ], + }, + DEB: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.install.debTitle', { + defaultMessage: 'Download and install Metricbeat', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.install.debTextPre', { + defaultMessage: 'First time using Metricbeat? See the [Getting Started Guide]({link}).', + values: { link: '{config.docs.beats.metricbeat}/metricbeat-getting-started.html' }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-amd64.deb', + 'sudo dpkg -i metricbeat-{config.kibana.version}-amd64.deb', + ], + textPost: i18n.translate('home.tutorials.common.metricbeatInstructions.install.debTextPost', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({link}).', + values: { link: 'https://www.elastic.co/downloads/beats/metricbeat' }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.install.rpmTitle', { + defaultMessage: 'Download and install Metricbeat', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.install.rpmTextPre', { + defaultMessage: 'First time using Metricbeat? See the [Getting Started Guide]({link}).', + values: { link: '{config.docs.beats.metricbeat}/metricbeat-getting-started.html' }, + }), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-x86_64.rpm', + 'sudo rpm -vi metricbeat-{config.kibana.version}-x86_64.rpm', + ], + textPost: i18n.translate('home.tutorials.common.metricbeatInstructions.install.debTextPost', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({link}).', + values: { link: 'https://www.elastic.co/downloads/beats/metricbeat' }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.install.windowsTitle', { + defaultMessage: 'Download and install Metricbeat', + }), + textPre: i18n.translate( + 'home.tutorials.common.metricbeatInstructions.install.windowsTextPre', + { + defaultMessage: + 'First time using Metricbeat? See the [Getting Started Guide]({metricbeatLink}).\n\ + 1. Download the Metricbeat Windows zip file from the [Download]({elasticLink}) page.\n\ + 2. Extract the contents of the zip file into {folderPath}.\n\ + 3. Rename the {directoryName} directory to `Metricbeat`.\n\ + 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ +**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ + 5. From the PowerShell prompt, run the following commands to install Metricbeat as a Windows service.', + values: { + directoryName: '`metricbeat-{config.kibana.version}-windows`', + folderPath: '`C:\\Program Files`', + metricbeatLink: '{config.docs.beats.metricbeat}/metricbeat-getting-started.html', + elasticLink: 'https://www.elastic.co/downloads/beats/metricbeat', + }, + } + ), + commands: ['cd "C:\\Program Files\\Metricbeat"', '.\\install-service-metricbeat.ps1'], + textPost: i18n.translate( + 'home.tutorials.common.metricbeatInstructions.install.windowsTextPost', + { + defaultMessage: + 'Modify the settings under `output.elasticsearch` in the {path} file to point to your Elasticsearch installation.', + values: { path: '`C:\\Program Files\\Metricbeat\\metricbeat.yml`' }, + } + ), + }, + }, + START: { + OSX: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.start.osxTitle', { + defaultMessage: 'Start Metricbeat', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.start.osxTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['./metricbeat setup', './metricbeat -e'], + }, + DEB: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.start.debTitle', { + defaultMessage: 'Start Metricbeat', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.start.debTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['sudo metricbeat setup', 'sudo service metricbeat start'], + }, + RPM: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.start.rpmTitle', { + defaultMessage: 'Start Metricbeat', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.start.rpmTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['sudo metricbeat setup', 'sudo service metricbeat start'], + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.start.windowsTitle', { + defaultMessage: 'Start Metricbeat', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.start.windowsTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['.\\metricbeat.exe setup', 'Start-Service metricbeat'], + }, + }, + CONFIG: { + OSX: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.config.osxTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`metricbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.metricbeatInstructions.config.osxTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + DEB: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.config.debTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.config.debTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`/etc/metricbeat/metricbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.metricbeatInstructions.config.debTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.config.rpmTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.common.metricbeatInstructions.config.rpmTextPre', { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`/etc/metricbeat/metricbeat.yml`', + }, + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate('home.tutorials.common.metricbeatInstructions.config.rpmTextPost', { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.metricbeatInstructions.config.windowsTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.metricbeatInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`C:\\Program Files\\Metricbeat\\metricbeat.yml`', + }, + } + ), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate( + 'home.tutorials.common.metricbeatInstructions.config.windowsTextPost', + { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + } + ), + }, + }, +}); + +export const createMetricbeatCloudInstructions = () => ({ + CONFIG: { + OSX: { + title: i18n.translate('home.tutorials.common.metricbeatCloudInstructions.config.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.osxTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`metricbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.osxTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + DEB: { + title: i18n.translate('home.tutorials.common.metricbeatCloudInstructions.config.debTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.debTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`/etc/metricbeat/metricbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.debTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + RPM: { + title: i18n.translate('home.tutorials.common.metricbeatCloudInstructions.config.rpmTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`/etc/metricbeat/metricbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + WINDOWS: { + title: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.windowsTitle', + { + defaultMessage: 'Edit the configuration', + } + ), + textPre: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`C:\\Program Files\\Metricbeat\\metricbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + }, +}); + +export function metricbeatEnableInstructions(moduleName: string) { + return { + OSX: { + title: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.osxTitle', { + defaultMessage: 'Enable and configure the {moduleName} module', + values: { moduleName }, + }), + textPre: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.osxTextPre', { + defaultMessage: 'From the installation directory, run:', + }), + commands: ['./metricbeat modules enable ' + moduleName], + textPost: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.osxTextPost', { + defaultMessage: 'Modify the settings in the `modules.d/{moduleName}.yml` file.', + values: { moduleName }, + }), + }, + DEB: { + title: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.debTitle', { + defaultMessage: 'Enable and configure the {moduleName} module', + values: { moduleName }, + }), + commands: ['sudo metricbeat modules enable ' + moduleName], + textPost: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.debTextPost', { + defaultMessage: + 'Modify the settings in the `/etc/metricbeat/modules.d/{moduleName}.yml` file.', + values: { moduleName }, + }), + }, + RPM: { + title: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.rpmTitle', { + defaultMessage: 'Enable and configure the {moduleName} module', + values: { moduleName }, + }), + commands: ['sudo metricbeat modules enable ' + moduleName], + textPost: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.rpmTextPost', { + defaultMessage: + 'Modify the settings in the `/etc/metricbeat/modules.d/{moduleName}.yml` file.', + values: { moduleName }, + }), + }, + WINDOWS: { + title: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.windowsTitle', { + defaultMessage: 'Enable and configure the {moduleName} module', + values: { moduleName }, + }), + textPre: i18n.translate('home.tutorials.common.metricbeatEnableInstructions.windowsTextPre', { + defaultMessage: 'From the {path} folder, run:', + values: { path: `C:\\Program Files\\Metricbeat` }, + }), + commands: ['.\\metricbeat.exe modules enable ' + moduleName], + textPost: i18n.translate( + 'home.tutorials.common.metricbeatEnableInstructions.windowsTextPost', + { + defaultMessage: 'Modify the settings in the `modules.d/{moduleName}.yml` file.', + values: { moduleName }, + } + ), + }, + }; +} + +export function metricbeatStatusCheck(moduleName: string) { + return { + title: i18n.translate('home.tutorials.common.metricbeatStatusCheck.title', { + defaultMessage: 'Module status', + }), + text: i18n.translate('home.tutorials.common.metricbeatStatusCheck.text', { + defaultMessage: 'Check that data is received from the Metricbeat `{moduleName}` module', + values: { moduleName }, + }), + btnLabel: i18n.translate('home.tutorials.common.metricbeatStatusCheck.buttonLabel', { + defaultMessage: 'Check data', + }), + success: i18n.translate('home.tutorials.common.metricbeatStatusCheck.successText', { + defaultMessage: 'Data successfully received from this module', + }), + error: i18n.translate('home.tutorials.common.metricbeatStatusCheck.errorText', { + defaultMessage: 'No data has been received from this module yet', + }), + esHitsCheck: { + index: 'metricbeat-*', + query: { + bool: { + filter: { + term: { + 'event.module': moduleName, + }, + }, + }, + }, + }, + }; +} + +export function onPremInstructions(moduleName: string, context?: TutorialContext) { + const METRICBEAT_INSTRUCTIONS = createMetricbeatInstructions(context); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.metricbeat.premInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + METRICBEAT_INSTRUCTIONS.INSTALL.OSX, + METRICBEAT_INSTRUCTIONS.CONFIG.OSX, + metricbeatEnableInstructions(moduleName).OSX, + METRICBEAT_INSTRUCTIONS.START.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [ + METRICBEAT_INSTRUCTIONS.INSTALL.DEB, + METRICBEAT_INSTRUCTIONS.CONFIG.DEB, + metricbeatEnableInstructions(moduleName).DEB, + METRICBEAT_INSTRUCTIONS.START.DEB, + ], + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [ + METRICBEAT_INSTRUCTIONS.INSTALL.RPM, + METRICBEAT_INSTRUCTIONS.CONFIG.RPM, + metricbeatEnableInstructions(moduleName).RPM, + METRICBEAT_INSTRUCTIONS.START.RPM, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS, + metricbeatEnableInstructions(moduleName).WINDOWS, + METRICBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: metricbeatStatusCheck(moduleName), + }, + ], + }; +} + +export function onPremCloudInstructions(moduleName: string) { + const TRYCLOUD_OPTION1 = createTrycloudOption1(); + const TRYCLOUD_OPTION2 = createTrycloudOption2(); + const METRICBEAT_INSTRUCTIONS = createMetricbeatInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.metricbeat.premCloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + METRICBEAT_INSTRUCTIONS.INSTALL.OSX, + METRICBEAT_INSTRUCTIONS.CONFIG.OSX, + metricbeatEnableInstructions(moduleName).OSX, + METRICBEAT_INSTRUCTIONS.START.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + METRICBEAT_INSTRUCTIONS.INSTALL.DEB, + METRICBEAT_INSTRUCTIONS.CONFIG.DEB, + metricbeatEnableInstructions(moduleName).DEB, + METRICBEAT_INSTRUCTIONS.START.DEB, + ], + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + METRICBEAT_INSTRUCTIONS.INSTALL.RPM, + METRICBEAT_INSTRUCTIONS.CONFIG.RPM, + metricbeatEnableInstructions(moduleName).RPM, + METRICBEAT_INSTRUCTIONS.START.RPM, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS, + metricbeatEnableInstructions(moduleName).WINDOWS, + METRICBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: metricbeatStatusCheck(moduleName), + }, + ], + }; +} + +export function cloudInstructions(moduleName: string) { + const METRICBEAT_INSTRUCTIONS = createMetricbeatInstructions(); + const METRICBEAT_CLOUD_INSTRUCTIONS = createMetricbeatCloudInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.metricbeat.cloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + METRICBEAT_INSTRUCTIONS.INSTALL.OSX, + METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX, + metricbeatEnableInstructions(moduleName).OSX, + METRICBEAT_INSTRUCTIONS.START.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [ + METRICBEAT_INSTRUCTIONS.INSTALL.DEB, + METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB, + metricbeatEnableInstructions(moduleName).DEB, + METRICBEAT_INSTRUCTIONS.START.DEB, + ], + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [ + METRICBEAT_INSTRUCTIONS.INSTALL.RPM, + METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM, + metricbeatEnableInstructions(moduleName).RPM, + METRICBEAT_INSTRUCTIONS.START.RPM, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS, + metricbeatEnableInstructions(moduleName).WINDOWS, + METRICBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: metricbeatStatusCheck(moduleName), + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/instructions/onprem_cloud_instructions.ts b/src/plugins/home/server/tutorials/instructions/onprem_cloud_instructions.ts new file mode 100644 index 00000000000000..d3b17410c4ffaf --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/onprem_cloud_instructions.ts @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +export const createTrycloudOption1 = () => ({ + title: i18n.translate('home.tutorials.common.premCloudInstructions.option1.title', { + defaultMessage: 'Option 1: Try in Elastic Cloud', + }), + textPre: i18n.translate('home.tutorials.common.premCloudInstructions.option1.textPre', { + defaultMessage: + 'Go to [Elastic Cloud]({link}). Register if you \ +do not already have an account. Free 14-day trial available.\n\n\ +Log into the Elastic Cloud console\n\n\ +To create a cluster, in Elastic Cloud console:\n\ + 1. Select **Create Deployment** and specify the **Deployment Name**\n\ + 2. Modify the other deployment options as needed (or not, the defaults are great to get started)\n\ + 3. Click **Create Deployment**\n\ + 4. Wait until deployment creation completes\n\ + 5. Go to the new Cloud Kibana instance and follow the Kibana Home instructions', + values: { + link: 'https://www.elastic.co/cloud/as-a-service/signup?blade=kib', + }, + }), +}); + +export const createTrycloudOption2 = () => ({ + title: i18n.translate('home.tutorials.common.premCloudInstructions.option2.title', { + defaultMessage: 'Option 2: Connect local Kibana to a Cloud instance', + }), + textPre: i18n.translate('home.tutorials.common.premCloudInstructions.option2.textPre', { + defaultMessage: + 'If you are running this Kibana instance against a hosted Elasticsearch instance, \ +proceed with manual setup.\n\n\ +Save the **Elasticsearch** endpoint as {urlTemplate} and the cluster **Password** as {passwordTemplate} for your records', + values: { + urlTemplate: '``', + passwordTemplate: '``', + }, + }), +}); diff --git a/src/legacy/core_plugins/kibana/common/tutorials/param_types.js b/src/plugins/home/server/tutorials/instructions/param_types.ts similarity index 100% rename from src/legacy/core_plugins/kibana/common/tutorials/param_types.js rename to src/plugins/home/server/tutorials/instructions/param_types.ts diff --git a/src/plugins/home/server/tutorials/instructions/winlogbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/winlogbeat_instructions.ts new file mode 100644 index 00000000000000..cc18f2ce9705d2 --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/winlogbeat_instructions.ts @@ -0,0 +1,263 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { INSTRUCTION_VARIANT } from './instruction_variant'; +import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; +import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; +import { TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +export const createWinlogbeatInstructions = (context?: TutorialContext) => ({ + INSTALL: { + WINDOWS: { + title: i18n.translate('home.tutorials.common.winlogbeatInstructions.install.windowsTitle', { + defaultMessage: 'Download and install Winlogbeat', + }), + textPre: i18n.translate( + 'home.tutorials.common.winlogbeatInstructions.install.windowsTextPre', + { + defaultMessage: + 'First time using Winlogbeat? See the [Getting Started Guide]({winlogbeatLink}).\n\ + 1. Download the Winlogbeat Windows zip file from the [Download]({elasticLink}) page.\n\ + 2. Extract the contents of the zip file into {folderPath}.\n\ + 3. Rename the {directoryName} directory to `Winlogbeat`.\n\ + 4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select \ +**Run As Administrator**). If you are running Windows XP, you might need to download and install PowerShell.\n\ + 5. From the PowerShell prompt, run the following commands to install Winlogbeat as a Windows service.', + values: { + directoryName: '`winlogbeat-{config.kibana.version}-windows`', + folderPath: '`C:\\Program Files`', + winlogbeatLink: '{config.docs.beats.winlogbeat}/winlogbeat-getting-started.html', + elasticLink: 'https://www.elastic.co/downloads/beats/winlogbeat', + }, + } + ), + commands: ['cd "C:\\Program Files\\Winlogbeat"', '.\\install-service-winlogbeat.ps1'], + textPost: i18n.translate( + 'home.tutorials.common.winlogbeatInstructions.install.windowsTextPost', + { + defaultMessage: + 'Modify the settings under `output.elasticsearch` in the {path} file to point to your Elasticsearch installation.', + values: { path: '`C:\\Program Files\\Winlogbeat\\winlogbeat.yml`' }, + } + ), + }, + }, + START: { + WINDOWS: { + title: i18n.translate('home.tutorials.common.winlogbeatInstructions.start.windowsTitle', { + defaultMessage: 'Start Winlogbeat', + }), + textPre: i18n.translate('home.tutorials.common.winlogbeatInstructions.start.windowsTextPre', { + defaultMessage: + 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, omit this command.', + }), + commands: ['.\\winlogbeat.exe setup', 'Start-Service winlogbeat'], + }, + }, + CONFIG: { + WINDOWS: { + title: i18n.translate('home.tutorials.common.winlogbeatInstructions.config.windowsTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.common.winlogbeatInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information:', + values: { + path: '`C:\\Program Files\\Winlogbeat\\winlogbeat.yml`', + }, + } + ), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: "elastic"', + ' password: ""', + 'setup.kibana:', + ' host: ""', + getSpaceIdForBeatsTutorial(context), + ], + textPost: i18n.translate( + 'home.tutorials.common.winlogbeatInstructions.config.windowsTextPost', + { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user, {esUrlTemplate} is the URL of Elasticsearch, \ +and {kibanaUrlTemplate} is the URL of Kibana.', + values: { + passwordTemplate: '``', + esUrlTemplate: '``', + kibanaUrlTemplate: '``', + }, + } + ), + }, + }, +}); + +export const createWinlogbeatCloudInstructions = () => ({ + CONFIG: { + WINDOWS: { + title: i18n.translate( + 'home.tutorials.common.winlogbeatCloudInstructions.config.windowsTitle', + { + defaultMessage: 'Edit the configuration', + } + ), + textPre: i18n.translate( + 'home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPre', + { + defaultMessage: 'Modify {path} to set the connection information for Elastic Cloud:', + values: { + path: '`C:\\Program Files\\Winlogbeat\\winlogbeat.yml`', + }, + } + ), + commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], + textPost: i18n.translate( + 'home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPost', + { + defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', + values: { passwordTemplate: '``' }, + } + ), + }, + }, +}); + +export function winlogbeatStatusCheck() { + return { + title: i18n.translate('home.tutorials.common.winlogbeatStatusCheck.title', { + defaultMessage: 'Module status', + }), + text: i18n.translate('home.tutorials.common.winlogbeatStatusCheck.text', { + defaultMessage: 'Check that data is received from Winlogbeat', + }), + btnLabel: i18n.translate('home.tutorials.common.winlogbeatStatusCheck.buttonLabel', { + defaultMessage: 'Check data', + }), + success: i18n.translate('home.tutorials.common.winlogbeatStatusCheck.successText', { + defaultMessage: 'Data successfully received', + }), + error: i18n.translate('home.tutorials.common.winlogbeatStatusCheck.errorText', { + defaultMessage: 'No data has been received yet', + }), + esHitsCheck: { + index: 'winlogbeat-*', + query: { + bool: { + filter: { + term: { + 'agent.type': 'winlogbeat', + }, + }, + }, + }, + }, + }; +} + +export function onPremInstructions(context?: TutorialContext) { + const WINLOGBEAT_INSTRUCTIONS = createWinlogbeatInstructions(context); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.winlogbeat.premInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + WINLOGBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + WINLOGBEAT_INSTRUCTIONS.CONFIG.WINDOWS, + WINLOGBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: winlogbeatStatusCheck(), + }, + ], + }; +} + +export function onPremCloudInstructions() { + const TRYCLOUD_OPTION1 = createTrycloudOption1(); + const TRYCLOUD_OPTION2 = createTrycloudOption2(); + const WINLOGBEAT_INSTRUCTIONS = createWinlogbeatInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.winlogbeat.premCloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + WINLOGBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + WINLOGBEAT_INSTRUCTIONS.CONFIG.WINDOWS, + WINLOGBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: winlogbeatStatusCheck(), + }, + ], + }; +} + +export function cloudInstructions() { + const WINLOGBEAT_INSTRUCTIONS = createWinlogbeatInstructions(); + const WINLOGBEAT_CLOUD_INSTRUCTIONS = createWinlogbeatCloudInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate( + 'home.tutorials.common.winlogbeat.cloudInstructions.gettingStarted.title', + { + defaultMessage: 'Getting Started', + } + ), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + WINLOGBEAT_INSTRUCTIONS.INSTALL.WINDOWS, + WINLOGBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS, + WINLOGBEAT_INSTRUCTIONS.START.WINDOWS, + ], + }, + ], + statusCheck: winlogbeatStatusCheck(), + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/iptables_logs/index.ts b/src/plugins/home/server/tutorials/iptables_logs/index.ts new file mode 100644 index 00000000000000..e3f2124347b6bb --- /dev/null +++ b/src/plugins/home/server/tutorials/iptables_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function iptablesLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'iptables'; + const platforms = ['DEB', 'RPM'] as const; + return { + id: 'iptablesLogs', + name: i18n.translate('home.tutorials.iptablesLogs.nameTitle', { + defaultMessage: 'Iptables / Ubiquiti', + }), + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.iptablesLogs.shortDescription', { + defaultMessage: 'Collect and parse iptables and ip6tables logs or from Ubiqiti firewalls.', + }), + longDescription: i18n.translate('home.tutorials.iptablesLogs.longDescription', { + defaultMessage: + 'This is a module for iptables and ip6tables logs. It parses logs \ +received over the network via syslog or from a file. Also, it understands the \ +prefix added by some Ubiquiti firewalls, which includes the rule set name, rule \ +number and the action performed on the traffic (allow/deny).. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iptables.html', + }, + }), + // euiIconType: 'logoUbiquiti', + artifacts: { + dashboards: [], + application: { + path: '/app/siem', + label: i18n.translate('home.tutorials.iptablesLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'SIEM App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-iptables.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/iptables_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/kafka_logs/index.ts b/src/plugins/home/server/tutorials/kafka_logs/index.ts new file mode 100644 index 00000000000000..74aa1ef772c85a --- /dev/null +++ b/src/plugins/home/server/tutorials/kafka_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function kafkaLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'kafka'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'kafkaLogs', + name: i18n.translate('home.tutorials.kafkaLogs.nameTitle', { + defaultMessage: 'Kafka logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.kafkaLogs.shortDescription', { + defaultMessage: 'Collect and parse logs created by Kafka.', + }), + longDescription: i18n.translate('home.tutorials.kafkaLogs.longDescription', { + defaultMessage: + 'The `kafka` Filebeat module parses logs created by Kafka. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-kafka.html', + }, + }), + euiIconType: 'logoKafka', + artifacts: { + dashboards: [ + { + id: '943caca0-87ee-11e7-ad9c-db80de0bf8d3-ecs', + linkLabel: i18n.translate('home.tutorials.kafkaLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Kafka logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-kafka.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/kafka_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/kafka_metrics/index.ts b/src/plugins/home/server/tutorials/kafka_metrics/index.ts new file mode 100644 index 00000000000000..98be309ca89cda --- /dev/null +++ b/src/plugins/home/server/tutorials/kafka_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function kafkaMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'kafka'; + return { + id: 'kafkaMetrics', + name: i18n.translate('home.tutorials.kafkaMetrics.nameTitle', { + defaultMessage: 'Kafka metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.kafkaMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the Kafka server.', + }), + longDescription: i18n.translate('home.tutorials.kafkaMetrics.longDescription', { + defaultMessage: + 'The `kafka` Metricbeat module fetches internal metrics from Kafka. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kafka.html', + }, + }), + euiIconType: 'logoKafka', + artifacts: { + application: { + label: i18n.translate('home.tutorials.kafkaMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-kafka.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/kibana_metrics/index.ts b/src/plugins/home/server/tutorials/kibana_metrics/index.ts new file mode 100644 index 00000000000000..c087212c46f783 --- /dev/null +++ b/src/plugins/home/server/tutorials/kibana_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function kibanaMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'kibana'; + return { + id: 'kibanaMetrics', + name: i18n.translate('home.tutorials.kibanaMetrics.nameTitle', { + defaultMessage: 'Kibana metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.kibanaMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from Kibana.', + }), + longDescription: i18n.translate('home.tutorials.kibanaMetrics.longDescription', { + defaultMessage: + 'The `kibana` Metricbeat module fetches internal metrics from Kibana. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kibana.html', + }, + }), + euiIconType: 'logoKibana', + artifacts: { + application: { + label: i18n.translate('home.tutorials.kibanaMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-kibana.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts b/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts new file mode 100644 index 00000000000000..466f713d35e061 --- /dev/null +++ b/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function kubernetesMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'kubernetes'; + return { + id: 'kubernetesMetrics', + name: i18n.translate('home.tutorials.kubernetesMetrics.nameTitle', { + defaultMessage: 'Kubernetes metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.kubernetesMetrics.shortDescription', { + defaultMessage: 'Fetch metrics from your Kubernetes installation.', + }), + longDescription: i18n.translate('home.tutorials.kubernetesMetrics.longDescription', { + defaultMessage: + 'The `kubernetes` Metricbeat module fetches metrics from the Kubernetes APIs. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kubernetes.html', + }, + }), + euiIconType: 'logoKubernetes', + artifacts: { + dashboards: [ + { + id: 'AV4RGUqo5NkDleZmzKuZ-ecs', + linkLabel: i18n.translate( + 'home.tutorials.kubernetesMetrics.artifacts.dashboards.linkLabel', + { + defaultMessage: 'Kubernetes metrics dashboard', + } + ), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-kubernetes.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/kubernetes_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/logstash_logs/index.ts b/src/plugins/home/server/tutorials/logstash_logs/index.ts new file mode 100644 index 00000000000000..276ceedbbcc680 --- /dev/null +++ b/src/plugins/home/server/tutorials/logstash_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function logstashLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'logstash'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'logstashLogs', + name: i18n.translate('home.tutorials.logstashLogs.nameTitle', { + defaultMessage: 'Logstash logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.logstashLogs.shortDescription', { + defaultMessage: 'Collect and parse debug and slow logs created by Logstash itself.', + }), + longDescription: i18n.translate('home.tutorials.logstashLogs.longDescription', { + defaultMessage: + 'The `logstash` Filebeat module parses debug and slow logs created by Logstash itself. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-logstash.html', + }, + }), + euiIconType: 'logoLogstash', + artifacts: { + dashboards: [ + { + id: 'Filebeat-Logstash-Log-Dashboard-ecs', + linkLabel: i18n.translate('home.tutorials.logstashLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Logstash logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-logstash.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/logstash_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/logstash_metrics/index.ts b/src/plugins/home/server/tutorials/logstash_metrics/index.ts new file mode 100644 index 00000000000000..122f143e4b8343 --- /dev/null +++ b/src/plugins/home/server/tutorials/logstash_metrics/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function logstashMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'logstash'; + return { + id: moduleName + 'Metrics', + name: i18n.translate('home.tutorials.logstashMetrics.nameTitle', { + defaultMessage: 'Logstash metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.logstashMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from a Logstash server.', + }), + longDescription: i18n.translate('home.tutorials.logstashMetrics.longDescription', { + defaultMessage: + 'The `{moduleName}` Metricbeat module fetches internal metrics from a Logstash server. \ +[Learn more]({learnMoreLink}).', + values: { + moduleName, + learnMoreLink: `{config.docs.beats.metricbeat}/metricbeat-module-${moduleName}.html`, + }, + }), + euiIconType: 'logoLogstash', + artifacts: { + application: { + label: i18n.translate('home.tutorials.logstashMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-' + moduleName + '.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/memcached_metrics/index.ts b/src/plugins/home/server/tutorials/memcached_metrics/index.ts new file mode 100644 index 00000000000000..1c9c9d975e4b89 --- /dev/null +++ b/src/plugins/home/server/tutorials/memcached_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function memcachedMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'memcached'; + return { + id: 'memcachedMetrics', + name: i18n.translate('home.tutorials.memcachedMetrics.nameTitle', { + defaultMessage: 'Memcached metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.memcachedMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the Memcached server.', + }), + longDescription: i18n.translate('home.tutorials.memcachedMetrics.longDescription', { + defaultMessage: + 'The `memcached` Metricbeat module fetches internal metrics from Memcached. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-memcached.html', + }, + }), + euiIconType: 'logoMemcached', + artifacts: { + application: { + label: i18n.translate('home.tutorials.memcachedMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-memcached.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/mongodb_metrics/index.ts b/src/plugins/home/server/tutorials/mongodb_metrics/index.ts new file mode 100644 index 00000000000000..1a10dc38494711 --- /dev/null +++ b/src/plugins/home/server/tutorials/mongodb_metrics/index.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function mongodbMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'mongodb'; + return { + id: 'mongodbMetrics', + name: i18n.translate('home.tutorials.mongodbMetrics.nameTitle', { + defaultMessage: 'MongoDB metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.mongodbMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from MongoDB.', + }), + longDescription: i18n.translate('home.tutorials.mongodbMetrics.longDescription', { + defaultMessage: + 'The `mongodb` Metricbeat module fetches internal metrics from the MongoDB server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mongodb.html', + }, + }), + euiIconType: 'logoMongodb', + artifacts: { + dashboards: [ + { + id: 'Metricbeat-MongoDB-ecs', + linkLabel: i18n.translate( + 'home.tutorials.mongodbMetrics.artifacts.dashboards.linkLabel', + { + defaultMessage: 'MongoDB metrics dashboard', + } + ), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-mongodb.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/mongodb_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/mssql_metrics/index.ts b/src/plugins/home/server/tutorials/mssql_metrics/index.ts new file mode 100644 index 00000000000000..cea46c3220d5ad --- /dev/null +++ b/src/plugins/home/server/tutorials/mssql_metrics/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function mssqlMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'mssql'; + return { + id: 'mssqlMetrics', + name: i18n.translate('home.tutorials.mssqlMetrics.nameTitle', { + defaultMessage: 'Microsoft SQL Server Metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.mssqlMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from a Microsoft SQL Server instance', + }), + longDescription: i18n.translate('home.tutorials.mssqlMetrics.longDescription', { + defaultMessage: + 'The `mssql` Metricbeat module fetches monitoring, log and performance metrics from a Microsoft SQL Server instance. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mssql.html', + }, + }), + // euiIconType: 'logoMSSQL', + isBeta: false, + artifacts: { + dashboards: [ + { + id: 'a2ead240-18bb-11e9-9836-f37dedd3b411-ecs', + linkLabel: i18n.translate('home.tutorials.mssqlMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Microsoft SQL Server metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-mssql.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/mssql_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/munin_metrics/index.ts b/src/plugins/home/server/tutorials/munin_metrics/index.ts new file mode 100644 index 00000000000000..e438d3015c77c0 --- /dev/null +++ b/src/plugins/home/server/tutorials/munin_metrics/index.ts @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function muninMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'munin'; + return { + id: 'muninMetrics', + name: i18n.translate('home.tutorials.muninMetrics.nameTitle', { + defaultMessage: 'Munin metrics', + }), + isBeta: true, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.muninMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the Munin server.', + }), + longDescription: i18n.translate('home.tutorials.muninMetrics.longDescription', { + defaultMessage: + 'The `munin` Metricbeat module fetches internal metrics from Munin. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-munin.html', + }, + }), + artifacts: { + application: { + label: i18n.translate('home.tutorials.muninMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-munin.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/mysql_logs/index.ts b/src/plugins/home/server/tutorials/mysql_logs/index.ts new file mode 100644 index 00000000000000..e003f4dfd47e48 --- /dev/null +++ b/src/plugins/home/server/tutorials/mysql_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function mysqlLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'mysql'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'mysqlLogs', + name: i18n.translate('home.tutorials.mysqlLogs.nameTitle', { + defaultMessage: 'MySQL logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.mysqlLogs.shortDescription', { + defaultMessage: 'Collect and parse error and slow logs created by MySQL.', + }), + longDescription: i18n.translate('home.tutorials.mysqlLogs.longDescription', { + defaultMessage: + 'The `mysql` Filebeat module parses error and slow logs created by MySQL. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-mysql.html', + }, + }), + euiIconType: 'logoMySQL', + artifacts: { + dashboards: [ + { + id: 'Filebeat-MySQL-Dashboard-ecs', + linkLabel: i18n.translate('home.tutorials.mysqlLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'MySQL logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-mysql.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/mysql_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/mysql_metrics/index.ts b/src/plugins/home/server/tutorials/mysql_metrics/index.ts new file mode 100644 index 00000000000000..d18cc31512e711 --- /dev/null +++ b/src/plugins/home/server/tutorials/mysql_metrics/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function mysqlMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'mysql'; + return { + id: 'mysqlMetrics', + name: i18n.translate('home.tutorials.mysqlMetrics.nameTitle', { + defaultMessage: 'MySQL metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.mysqlMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from MySQL.', + }), + longDescription: i18n.translate('home.tutorials.mysqlMetrics.longDescription', { + defaultMessage: + 'The `mysql` Metricbeat module fetches internal metrics from the MySQL server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mysql.html', + }, + }), + euiIconType: 'logoMySQL', + artifacts: { + dashboards: [ + { + id: '66881e90-0006-11e7-bf7f-c9acc3d3e306-ecs', + linkLabel: i18n.translate('home.tutorials.mysqlMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'MySQL metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-mysql.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/mysql_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/nats_logs/index.ts b/src/plugins/home/server/tutorials/nats_logs/index.ts new file mode 100644 index 00000000000000..3f6cb36d8d49e3 --- /dev/null +++ b/src/plugins/home/server/tutorials/nats_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function natsLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'nats'; + const platforms = ['DEB', 'RPM'] as const; + return { + id: 'natsLogs', + name: i18n.translate('home.tutorials.natsLogs.nameTitle', { + defaultMessage: 'NATS logs', + }), + category: TutorialsCategory.LOGGING, + isBeta: true, + shortDescription: i18n.translate('home.tutorials.natsLogs.shortDescription', { + defaultMessage: 'Collect and parse logs created by Nats.', + }), + longDescription: i18n.translate('home.tutorials.natsLogs.longDescription', { + defaultMessage: + 'The `nats` Filebeat module parses logs created by Nats. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-nats.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/nats.svg', + artifacts: { + dashboards: [ + { + id: 'Filebeat-nats-overview-ecs', + linkLabel: i18n.translate('home.tutorials.natsLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'NATS logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-nats.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/nats_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/nats_metrics/index.ts b/src/plugins/home/server/tutorials/nats_metrics/index.ts new file mode 100644 index 00000000000000..27b5507ff6672e --- /dev/null +++ b/src/plugins/home/server/tutorials/nats_metrics/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function natsMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'nats'; + return { + id: 'natsMetrics', + name: i18n.translate('home.tutorials.natsMetrics.nameTitle', { + defaultMessage: 'NATS metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.natsMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from the Nats server.', + }), + longDescription: i18n.translate('home.tutorials.natsMetrics.longDescription', { + defaultMessage: + 'The `nats` Metricbeat module fetches monitoring metrics from Nats. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-nats.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/nats.svg', + artifacts: { + dashboards: [ + { + id: 'Metricbeat-Nats-Dashboard-ecs', + linkLabel: i18n.translate('home.tutorials.natsMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'NATS metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-nats.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/nats_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/netflow/common_instructions.ts b/src/plugins/home/server/tutorials/netflow/common_instructions.ts new file mode 100644 index 00000000000000..8fe24ba9c7994b --- /dev/null +++ b/src/plugins/home/server/tutorials/netflow/common_instructions.ts @@ -0,0 +1,281 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +export function createCommonNetflowInstructions() { + return { + CONFIG: { + ON_PREM: { + OSX: [ + { + title: i18n.translate('home.tutorials.netflow.common.config.onPrem.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.netflow.common.config.onPrem.osxTextPre', { + defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', + values: { + logstashConfigPath: '`config/logstash.yml`', + }, + }), + commands: ['modules:', ' - name: netflow', ' var.input.udp.port: '], + textPost: i18n.translate('home.tutorials.netflow.common.config.onPrem.osxTextPost', { + defaultMessage: + 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data.', + values: { + udpPort: '``', + }, + }), + }, + ], + WINDOWS: [ + { + title: i18n.translate('home.tutorials.netflow.common.config.onPrem.windowsTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('home.tutorials.netflow.common.config.onPrem.windowsTextPre', { + defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', + values: { + logstashConfigPath: '`config\\logstash.yml`', + }, + }), + commands: ['modules:', ' - name: netflow', ' var.input.udp.port: '], + textPost: i18n.translate( + 'home.tutorials.netflow.common.config.onPrem.windowsTextPost', + { + defaultMessage: + 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data.', + values: { + udpPort: '``', + }, + } + ), + }, + ], + }, + ON_PREM_ELASTIC_CLOUD: { + OSX: [ + { + title: i18n.translate( + 'home.tutorials.netflow.common.config.onPremElasticCloud.osxTitle', + { + defaultMessage: 'Edit the configuration', + } + ), + textPre: i18n.translate( + 'home.tutorials.netflow.common.config.onPremElasticCloud.osxTextPre', + { + defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', + values: { + logstashConfigPath: '`config/logstash.yml`', + }, + } + ), + commands: [ + 'modules:', + ' - name: netflow', + ' var.input.udp.port: ', + ' var.elasticsearch.hosts: [ "" ]', + ' var.elasticsearch.username: elastic', + ' var.elasticsearch.password: ', + ], + textPost: i18n.translate( + 'home.tutorials.netflow.common.config.onPremElasticCloud.osxTextPost', + { + defaultMessage: + 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data, \ + {esUrl} is the URL of Elasticsearch running on Elastic Cloud, and \ + {password} is the password of the {elastic} user.', + values: { + elastic: '`elastic`', + esUrl: '``', + password: '``', + udpPort: '``', + }, + } + ), + }, + ], + WINDOWS: [ + { + title: i18n.translate( + 'home.tutorials.netflow.common.config.onPremElasticCloud.windowsTitle', + { + defaultMessage: 'Edit the configuration', + } + ), + textPre: i18n.translate( + 'home.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPre', + { + defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', + values: { + logstashConfigPath: '`config\\logstash.yml`', + }, + } + ), + commands: [ + 'modules:', + ' - name: netflow', + ' var.input.udp.port: ', + ' var.elasticsearch.hosts: [ "" ]', + ' var.elasticsearch.username: elastic', + ' var.elasticsearch.password: ', + ], + textPost: i18n.translate( + 'home.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPost', + { + defaultMessage: + 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data, \ + {esUrl} is the URL of Elasticsearch running on Elastic Cloud, and \ + {password} is the password of the {elastic} user.', + values: { + elastic: '`elastic`', + esUrl: '``', + password: '``', + udpPort: '``', + }, + } + ), + }, + ], + }, + ELASTIC_CLOUD: { + OSX: [ + { + title: i18n.translate('home.tutorials.netflow.common.config.elasticCloud.osxTitle', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate( + 'home.tutorials.netflow.common.config.elasticCloud.osxTextPre', + { + defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', + values: { + logstashConfigPath: '`config/logstash.yml`', + }, + } + ), + commands: [ + 'cloud.id: "{config.cloud.id}"', + 'cloud.auth: "elastic:"', + ' ', + 'modules:', + ' - name: netflow', + ' var.input.udp.port: ', + ], + textPost: i18n.translate( + 'home.tutorials.netflow.common.config.elasticCloud.osxTextPost', + { + defaultMessage: + 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data and \ + {password} is the password of the {elastic} user.', + values: { + elastic: '`elastic`', + password: '``', + udpPort: '``', + }, + } + ), + }, + ], + WINDOWS: [ + { + title: i18n.translate( + 'home.tutorials.netflow.common.config.elasticCloud.windowsTitle', + { + defaultMessage: 'Edit the configuration', + } + ), + textPre: i18n.translate( + 'home.tutorials.netflow.common.config.elasticCloud.windowsTextPre', + { + defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', + values: { + logstashConfigPath: '`config\\logstash.yml`', + }, + } + ), + commands: [ + 'cloud.id: "{config.cloud.id}"', + 'cloud.auth: "elastic:"', + ' ', + 'modules:', + ' - name: netflow', + ' var.input.udp.port: ', + ], + textPost: i18n.translate( + 'home.tutorials.netflow.common.config.elasticCloud.windowsTextPost', + { + defaultMessage: + 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data and \ + {password} is the password of the {elastic} user.', + values: { + elastic: '`elastic`', + password: '``', + udpPort: '``', + }, + } + ), + }, + ], + }, + }, + SETUP: { + OSX: [ + { + title: i18n.translate('home.tutorials.netflow.common.setup.osxTitle', { + defaultMessage: 'Run the Netflow module', + }), + textPre: i18n.translate('home.tutorials.netflow.common.setup.osxTextPre', { + defaultMessage: 'Run:', + }), + commands: ['./bin/logstash --modules netflow --setup'], + textPost: i18n.translate('home.tutorials.netflow.common.setup.osxTextPost', { + defaultMessage: + 'The {setupOption} option creates a {netflowPrefix} index pattern in Elasticsearch and imports \ + Kibana dashboards and visualizations. Omit this option for subsequent runs to avoid overwriting existing dashboards.', + values: { + setupOption: '`--setup`', + netflowPrefix: '`netflow-*`', + }, + }), + }, + ], + WINDOWS: [ + { + title: i18n.translate('home.tutorials.netflow.common.setup.windowsTitle', { + defaultMessage: 'Run the Netflow module', + }), + textPre: i18n.translate('home.tutorials.netflow.common.setup.windowsTextPre', { + defaultMessage: 'Run:', + }), + commands: ['bin\\logstash --modules netflow --setup'], + textPost: i18n.translate('home.tutorials.netflow.common.setup.windowsTextPost', { + defaultMessage: + 'The {setupOption} option creates a {netflowPrefix} index pattern in Elasticsearch and imports \ + Kibana dashboards and visualizations. Omit this option for subsequent runs to avoid overwriting existing dashboards.', + values: { + setupOption: '`--setup`', + netflowPrefix: '`netflow-*`', + }, + }), + }, + ], + }, + }; +} diff --git a/src/plugins/home/server/tutorials/netflow/elastic_cloud.ts b/src/plugins/home/server/tutorials/netflow/elastic_cloud.ts new file mode 100644 index 00000000000000..ac64aef7300045 --- /dev/null +++ b/src/plugins/home/server/tutorials/netflow/elastic_cloud.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import { INSTRUCTION_VARIANT } from '../instructions/instruction_variant'; +import { createLogstashInstructions } from '../instructions/logstash_instructions'; +import { createCommonNetflowInstructions } from './common_instructions'; + +// TODO: compare with onPremElasticCloud and onPrem scenarios and extract out common bits +export function createElasticCloudInstructions() { + const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); + const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate('home.tutorials.netflow.elasticCloudInstructions.title', { + defaultMessage: 'Getting Started', + }), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, + ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ELASTIC_CLOUD.OSX, + ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, + ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ELASTIC_CLOUD.WINDOWS, + ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, + ], + }, + ], + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/netflow/index.ts b/src/plugins/home/server/tutorials/netflow/index.ts new file mode 100644 index 00000000000000..7c6fcadcff625a --- /dev/null +++ b/src/plugins/home/server/tutorials/netflow/index.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import { TutorialsCategory } from '../../services/tutorials'; +import { createOnPremInstructions } from './on_prem'; +import { createElasticCloudInstructions } from './elastic_cloud'; +import { createOnPremElasticCloudInstructions } from './on_prem_elastic_cloud'; + +export function netflowSpecProvider() { + return { + id: 'netflow', + name: 'Netflow', + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.netflow.tutorialShortDescription', { + defaultMessage: 'Collect Netflow records sent by a Netflow exporter.', + }), + longDescription: i18n.translate('home.tutorials.netflow.tutorialLongDescription', { + defaultMessage: + 'The Logstash Netflow module collects and parses network flow data, \ +indexes the events into Elasticsearch, and installs a suite of Kibana dashboards. \ +This module support Netflow Version 5 and 9. [Learn more]({linkUrl}).', + values: { + linkUrl: '{config.docs.logstash}/netflow-module.html', + }, + }), + completionTimeMinutes: 10, + // previewImagePath: 'kibana-apache.png', TODO + onPrem: createOnPremInstructions(), + elasticCloud: createElasticCloudInstructions(), + onPremElasticCloud: createOnPremElasticCloudInstructions(), + }; +} diff --git a/src/plugins/home/server/tutorials/netflow/on_prem.ts b/src/plugins/home/server/tutorials/netflow/on_prem.ts new file mode 100644 index 00000000000000..c7cd36d0736327 --- /dev/null +++ b/src/plugins/home/server/tutorials/netflow/on_prem.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import { INSTRUCTION_VARIANT } from '../instructions/instruction_variant'; +import { createLogstashInstructions } from '../instructions/logstash_instructions'; +import { createCommonNetflowInstructions } from './common_instructions'; + +// TODO: compare with onPremElasticCloud and elasticCloud scenarios and extract out common bits +export function createOnPremInstructions() { + const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); + const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate('home.tutorials.netflow.onPremInstructions.title', { + defaultMessage: 'Getting Started', + }), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, + ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.OSX, + ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, + ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.WINDOWS, + ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, + ], + }, + ], + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/netflow/on_prem_elastic_cloud.ts b/src/plugins/home/server/tutorials/netflow/on_prem_elastic_cloud.ts new file mode 100644 index 00000000000000..c01a9a5382f88e --- /dev/null +++ b/src/plugins/home/server/tutorials/netflow/on_prem_elastic_cloud.ts @@ -0,0 +1,68 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import { INSTRUCTION_VARIANT } from '../instructions/instruction_variant'; +import { createLogstashInstructions } from '../instructions/logstash_instructions'; +import { + createTrycloudOption1, + createTrycloudOption2, +} from '../instructions/onprem_cloud_instructions'; +import { createCommonNetflowInstructions } from './common_instructions'; + +// TODO: compare with onPrem and elasticCloud scenarios and extract out common bits +export function createOnPremElasticCloudInstructions() { + const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); + const TRYCLOUD_OPTION1 = createTrycloudOption1(); + const TRYCLOUD_OPTION2 = createTrycloudOption2(); + const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); + + return { + instructionSets: [ + { + title: i18n.translate('home.tutorials.netflow.onPremElasticCloudInstructions.title', { + defaultMessage: 'Getting Started', + }), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, + ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM_ELASTIC_CLOUD.OSX, + ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: [ + TRYCLOUD_OPTION1, + TRYCLOUD_OPTION2, + ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, + ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM_ELASTIC_CLOUD.WINDOWS, + ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, + ], + }, + ], + }, + ], + }; +} diff --git a/src/plugins/home/server/tutorials/nginx_logs/index.ts b/src/plugins/home/server/tutorials/nginx_logs/index.ts new file mode 100644 index 00000000000000..756d4a171d858a --- /dev/null +++ b/src/plugins/home/server/tutorials/nginx_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function nginxLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'nginx'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'nginxLogs', + name: i18n.translate('home.tutorials.nginxLogs.nameTitle', { + defaultMessage: 'Nginx logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.nginxLogs.shortDescription', { + defaultMessage: 'Collect and parse access and error logs created by the Nginx HTTP server.', + }), + longDescription: i18n.translate('home.tutorials.nginxLogs.longDescription', { + defaultMessage: + 'The `nginx` Filebeat module parses access and error logs created by the Nginx HTTP server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-nginx.html', + }, + }), + euiIconType: 'logoNginx', + artifacts: { + dashboards: [ + { + id: '55a9e6e0-a29e-11e7-928f-5dbe6f6f5519-ecs', + linkLabel: i18n.translate('home.tutorials.nginxLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Nginx logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-nginx.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/nginx_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/nginx_metrics/index.ts b/src/plugins/home/server/tutorials/nginx_metrics/index.ts new file mode 100644 index 00000000000000..82af4d6c42dd86 --- /dev/null +++ b/src/plugins/home/server/tutorials/nginx_metrics/index.ts @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function nginxMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'nginx'; + return { + id: 'nginxMetrics', + name: i18n.translate('home.tutorials.nginxMetrics.nameTitle', { + defaultMessage: 'Nginx metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.nginxMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the Nginx HTTP server.', + }), + longDescription: i18n.translate('home.tutorials.nginxMetrics.longDescription', { + defaultMessage: + 'The `nginx` Metricbeat module fetches internal metrics from the 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. \ +[Learn more]({learnMoreLink}).', + values: { + statusModuleLink: + '[ngx_http_stub_status_module](http://nginx.org/en/docs/http/ngx_http_stub_status_module.html)', + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-nginx.html', + }, + }), + euiIconType: 'logoNginx', + artifacts: { + dashboards: [ + { + id: '023d2930-f1a5-11e7-a9ef-93c69af7b129-ecs', + linkLabel: i18n.translate('home.tutorials.nginxMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Nginx metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-nginx.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/nginx_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/osquery_logs/index.ts b/src/plugins/home/server/tutorials/osquery_logs/index.ts new file mode 100644 index 00000000000000..bce928519f66d5 --- /dev/null +++ b/src/plugins/home/server/tutorials/osquery_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function osqueryLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'osquery'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'osqueryLogs', + name: i18n.translate('home.tutorials.osqueryLogs.nameTitle', { + defaultMessage: 'Osquery logs', + }), + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.osqueryLogs.shortDescription', { + defaultMessage: 'Collect the result logs created by osqueryd.', + }), + longDescription: i18n.translate('home.tutorials.osqueryLogs.longDescription', { + defaultMessage: + 'The `osquery` Filebeat module collects the JSON result logs collected by `osqueryd`. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-osquery.html', + }, + }), + euiIconType: 'logoOsquery', + artifacts: { + dashboards: [ + { + id: '69f5ae20-eb02-11e7-8f04-51231daa5b05-ecs', + linkLabel: i18n.translate('home.tutorials.osqueryLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Osquery logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-osquery.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/osquery_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts b/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts new file mode 100644 index 00000000000000..a6c98fb16671fe --- /dev/null +++ b/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function phpfpmMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'php_fpm'; + return { + id: 'phpfpmMetrics', + name: i18n.translate('home.tutorials.phpFpmMetrics.nameTitle', { + defaultMessage: 'PHP-FPM metrics', + }), + category: TutorialsCategory.METRICS, + isBeta: false, + shortDescription: i18n.translate('home.tutorials.phpFpmMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from PHP-FPM.', + }), + longDescription: i18n.translate('home.tutorials.phpFpmMetrics.longDescription', { + defaultMessage: + 'The `php_fpm` Metricbeat module fetches internal metrics from the PHP-FPM server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-php_fpm.html', + }, + }), + euiIconType: 'logoPhp', + artifacts: { + dashboards: [ + /* { + id: 'TODO', + linkLabel: 'PHP-FPM metrics dashboard', + isOverview: true + }*/ + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-php_fpm.html', + }, + }, + completionTimeMinutes: 10, + // previewImagePath: '/plugins/kibana/home/tutorial_resources/php_fpm_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/postgresql_logs/index.ts b/src/plugins/home/server/tutorials/postgresql_logs/index.ts new file mode 100644 index 00000000000000..def9f71c9d2df9 --- /dev/null +++ b/src/plugins/home/server/tutorials/postgresql_logs/index.ts @@ -0,0 +1,76 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function postgresqlLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'postgresql'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'postgresqlLogs', + name: i18n.translate('home.tutorials.postgresqlLogs.nameTitle', { + defaultMessage: 'PostgreSQL logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.postgresqlLogs.shortDescription', { + defaultMessage: 'Collect and parse error and slow logs created by PostgreSQL.', + }), + longDescription: i18n.translate('home.tutorials.postgresqlLogs.longDescription', { + defaultMessage: + 'The `postgresql` Filebeat module parses error and slow logs created by PostgreSQL. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-postgresql.html', + }, + }), + euiIconType: 'logoPostgres', + artifacts: { + dashboards: [ + { + id: '158be870-87f4-11e7-ad9c-db80de0bf8d3-ecs', + linkLabel: i18n.translate( + 'home.tutorials.postgresqlLogs.artifacts.dashboards.linkLabel', + { + defaultMessage: 'PostgreSQL logs dashboard', + } + ), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-postgresql.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/postgresql_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/postgresql_metrics/index.ts b/src/plugins/home/server/tutorials/postgresql_metrics/index.ts new file mode 100644 index 00000000000000..b16267aeb0de65 --- /dev/null +++ b/src/plugins/home/server/tutorials/postgresql_metrics/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function postgresqlMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'postgresql'; + return { + id: 'postgresqlMetrics', + name: i18n.translate('home.tutorials.postgresqlMetrics.nameTitle', { + defaultMessage: 'PostgreSQL metrics', + }), + category: TutorialsCategory.METRICS, + isBeta: false, + shortDescription: i18n.translate('home.tutorials.postgresqlMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from PostgreSQL.', + }), + longDescription: i18n.translate('home.tutorials.postgresqlMetrics.longDescription', { + defaultMessage: + 'The `postgresql` Metricbeat module fetches internal metrics from the PostgreSQL server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-postgresql.html', + }, + }), + euiIconType: 'logoPostgres', + artifacts: { + dashboards: [ + /* + { + id: 'TODO', + linkLabel: 'PostgreSQL metrics dashboard', + isOverview: true + } + */ + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-postgresql.html', + }, + }, + completionTimeMinutes: 10, + // previewImagePath: '/plugins/kibana/home/tutorial_resources/postgresql_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/prometheus_metrics/index.ts b/src/plugins/home/server/tutorials/prometheus_metrics/index.ts new file mode 100644 index 00000000000000..d79ce652db0d0e --- /dev/null +++ b/src/plugins/home/server/tutorials/prometheus_metrics/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function prometheusMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'prometheus'; + return { + id: moduleName + 'Metrics', + name: i18n.translate('home.tutorials.prometheusMetrics.nameTitle', { + defaultMessage: 'Prometheus metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.prometheusMetrics.shortDescription', { + defaultMessage: 'Fetch metrics from a Prometheus exporter.', + }), + longDescription: i18n.translate('home.tutorials.prometheusMetrics.longDescription', { + defaultMessage: + 'The `{moduleName}` Metricbeat module fetches metrics from Prometheus endpoint. \ +[Learn more]({learnMoreLink}).', + values: { + moduleName, + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-' + moduleName + '.html', + }, + }), + euiIconType: 'logoPrometheus', + artifacts: { + application: { + label: i18n.translate('home.tutorials.prometheusMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-' + moduleName + '.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts b/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts new file mode 100644 index 00000000000000..b62a7ff7314204 --- /dev/null +++ b/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts @@ -0,0 +1,76 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function rabbitmqMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'rabbitmq'; + return { + id: 'rabbitmqMetrics', + name: i18n.translate('home.tutorials.rabbitmqMetrics.nameTitle', { + defaultMessage: 'RabbitMQ metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.rabbitmqMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the RabbitMQ server.', + }), + longDescription: i18n.translate('home.tutorials.rabbitmqMetrics.longDescription', { + defaultMessage: + 'The `rabbitmq` Metricbeat module fetches internal metrics from the RabbitMQ server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-rabbitmq.html', + }, + }), + euiIconType: 'logoRabbitmq', + isBeta: false, + artifacts: { + dashboards: [ + { + id: 'AV4YobKIge1VCbKU_qVo-ecs', + linkLabel: i18n.translate( + 'home.tutorials.rabbitmqMetrics.artifacts.dashboards.linkLabel', + { + defaultMessage: 'RabbitMQ metrics dashboard', + } + ), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-rabbitmq.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/rabbitmq_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/redis_logs/index.ts b/src/plugins/home/server/tutorials/redis_logs/index.ts new file mode 100644 index 00000000000000..27c288ce9c381b --- /dev/null +++ b/src/plugins/home/server/tutorials/redis_logs/index.ts @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function redisLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'redis'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'redisLogs', + name: i18n.translate('home.tutorials.redisLogs.nameTitle', { + defaultMessage: 'Redis logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.redisLogs.shortDescription', { + defaultMessage: 'Collect and parse error and slow logs created by Redis.', + }), + longDescription: i18n.translate('home.tutorials.redisLogs.longDescription', { + defaultMessage: + 'The `redis` Filebeat module parses error and slow logs created by Redis. \ +For Redis to write error logs, make sure the `logfile` option, from the \ +Redis configuration file, is set to `redis-server.log`. \ +The slow logs are read directly from Redis via the `SLOWLOG` command. \ +For Redis to record slow logs, make sure the `slowlog-log-slower-than` \ +option is set. \ +Note that the `slowlog` fileset is experimental. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-redis.html', + }, + }), + euiIconType: 'logoRedis', + artifacts: { + dashboards: [ + { + id: '7fea2930-478e-11e7-b1f0-cb29bac6bf8b-ecs', + linkLabel: i18n.translate('home.tutorials.redisLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Redis logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-redis.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/redis_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/redis_metrics/index.ts b/src/plugins/home/server/tutorials/redis_metrics/index.ts new file mode 100644 index 00000000000000..27c7780653168b --- /dev/null +++ b/src/plugins/home/server/tutorials/redis_metrics/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function redisMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'redis'; + return { + id: 'redisMetrics', + name: i18n.translate('home.tutorials.redisMetrics.nameTitle', { + defaultMessage: 'Redis metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.redisMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from Redis.', + }), + longDescription: i18n.translate('home.tutorials.redisMetrics.longDescription', { + defaultMessage: + 'The `redis` Metricbeat module fetches internal metrics from the Redis server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-redis.html', + }, + }), + euiIconType: 'logoRedis', + artifacts: { + dashboards: [ + { + id: 'AV4YjZ5pux-M-tCAunxK-ecs', + linkLabel: i18n.translate('home.tutorials.redisMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Redis metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-redis.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/redis_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/register.ts b/src/plugins/home/server/tutorials/register.ts new file mode 100644 index 00000000000000..ab5788865bd8ea --- /dev/null +++ b/src/plugins/home/server/tutorials/register.ts @@ -0,0 +1,161 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { systemLogsSpecProvider } from './system_logs'; +import { systemMetricsSpecProvider } from './system_metrics'; +import { apacheLogsSpecProvider } from './apache_logs'; +import { apacheMetricsSpecProvider } from './apache_metrics'; +import { elasticsearchLogsSpecProvider } from './elasticsearch_logs'; +import { iisLogsSpecProvider } from './iis_logs'; +import { kafkaLogsSpecProvider } from './kafka_logs'; +import { logstashLogsSpecProvider } from './logstash_logs'; +import { nginxLogsSpecProvider } from './nginx_logs'; +import { nginxMetricsSpecProvider } from './nginx_metrics'; +import { mysqlLogsSpecProvider } from './mysql_logs'; +import { mysqlMetricsSpecProvider } from './mysql_metrics'; +import { mongodbMetricsSpecProvider } from './mongodb_metrics'; +import { osqueryLogsSpecProvider } from './osquery_logs'; +import { phpfpmMetricsSpecProvider } from './php_fpm_metrics'; +import { postgresqlMetricsSpecProvider } from './postgresql_metrics'; +import { postgresqlLogsSpecProvider } from './postgresql_logs'; +import { rabbitmqMetricsSpecProvider } from './rabbitmq_metrics'; +import { redisLogsSpecProvider } from './redis_logs'; +import { redisMetricsSpecProvider } from './redis_metrics'; +import { suricataLogsSpecProvider } from './suricata_logs'; +import { dockerMetricsSpecProvider } from './docker_metrics'; +import { kubernetesMetricsSpecProvider } from './kubernetes_metrics'; +import { uwsgiMetricsSpecProvider } from './uwsgi_metrics'; +import { netflowSpecProvider } from './netflow'; +import { traefikLogsSpecProvider } from './traefik_logs'; +import { cephMetricsSpecProvider } from './ceph_metrics'; +import { aerospikeMetricsSpecProvider } from './aerospike_metrics'; +import { couchbaseMetricsSpecProvider } from './couchbase_metrics'; +import { dropwizardMetricsSpecProvider } from './dropwizard_metrics'; +import { elasticsearchMetricsSpecProvider } from './elasticsearch_metrics'; +import { etcdMetricsSpecProvider } from './etcd_metrics'; +import { haproxyMetricsSpecProvider } from './haproxy_metrics'; +import { kafkaMetricsSpecProvider } from './kafka_metrics'; +import { kibanaMetricsSpecProvider } from './kibana_metrics'; +import { memcachedMetricsSpecProvider } from './memcached_metrics'; +import { muninMetricsSpecProvider } from './munin_metrics'; +import { vSphereMetricsSpecProvider } from './vsphere_metrics'; +import { windowsMetricsSpecProvider } from './windows_metrics'; +import { windowsEventLogsSpecProvider } from './windows_event_logs'; +import { golangMetricsSpecProvider } from './golang_metrics'; +import { logstashMetricsSpecProvider } from './logstash_metrics'; +import { prometheusMetricsSpecProvider } from './prometheus_metrics'; +import { zookeeperMetricsSpecProvider } from './zookeeper_metrics'; +import { uptimeMonitorsSpecProvider } from './uptime_monitors'; +import { cloudwatchLogsSpecProvider } from './cloudwatch_logs'; +import { awsMetricsSpecProvider } from './aws_metrics'; +import { mssqlMetricsSpecProvider } from './mssql_metrics'; +import { natsMetricsSpecProvider } from './nats_metrics'; +import { natsLogsSpecProvider } from './nats_logs'; +import { zeekLogsSpecProvider } from './zeek_logs'; +import { corednsMetricsSpecProvider } from './coredns_metrics'; +import { corednsLogsSpecProvider } from './coredns_logs'; +import { auditbeatSpecProvider } from './auditbeat'; +import { iptablesLogsSpecProvider } from './iptables_logs'; +import { ciscoLogsSpecProvider } from './cisco_logs'; +import { envoyproxyLogsSpecProvider } from './envoyproxy_logs'; +import { couchdbMetricsSpecProvider } from './couchdb_metrics'; +import { consulMetricsSpecProvider } from './consul_metrics'; +import { cockroachdbMetricsSpecProvider } from './cockroachdb_metrics'; +import { traefikMetricsSpecProvider } from './traefik_metrics'; +import { awsLogsSpecProvider } from './aws_logs'; +import { activemqLogsSpecProvider } from './activemq_logs'; +import { activemqMetricsSpecProvider } from './activemq_metrics'; +import { azureMetricsSpecProvider } from './azure_metrics'; +import { ibmmqLogsSpecProvider } from './ibmmq_logs'; +import { stanMetricsSpecProvider } from './stan_metrics'; +import { envoyproxyMetricsSpecProvider } from './envoyproxy_metrics'; +import { ibmmqMetricsSpecProvider } from './ibmmq_metrics'; +import { statsdMetricsSpecProvider } from './statsd_metrics'; + +export const builtInTutorials = [ + systemLogsSpecProvider, + systemMetricsSpecProvider, + apacheLogsSpecProvider, + apacheMetricsSpecProvider, + elasticsearchLogsSpecProvider, + iisLogsSpecProvider, + kafkaLogsSpecProvider, + logstashLogsSpecProvider, + nginxLogsSpecProvider, + nginxMetricsSpecProvider, + mysqlLogsSpecProvider, + mysqlMetricsSpecProvider, + mongodbMetricsSpecProvider, + osqueryLogsSpecProvider, + phpfpmMetricsSpecProvider, + postgresqlMetricsSpecProvider, + postgresqlLogsSpecProvider, + rabbitmqMetricsSpecProvider, + redisLogsSpecProvider, + redisMetricsSpecProvider, + suricataLogsSpecProvider, + dockerMetricsSpecProvider, + kubernetesMetricsSpecProvider, + uwsgiMetricsSpecProvider, + netflowSpecProvider, + traefikLogsSpecProvider, + cephMetricsSpecProvider, + aerospikeMetricsSpecProvider, + couchbaseMetricsSpecProvider, + dropwizardMetricsSpecProvider, + elasticsearchMetricsSpecProvider, + etcdMetricsSpecProvider, + haproxyMetricsSpecProvider, + kafkaMetricsSpecProvider, + kibanaMetricsSpecProvider, + memcachedMetricsSpecProvider, + muninMetricsSpecProvider, + vSphereMetricsSpecProvider, + windowsMetricsSpecProvider, + windowsEventLogsSpecProvider, + golangMetricsSpecProvider, + logstashMetricsSpecProvider, + prometheusMetricsSpecProvider, + zookeeperMetricsSpecProvider, + uptimeMonitorsSpecProvider, + cloudwatchLogsSpecProvider, + awsMetricsSpecProvider, + mssqlMetricsSpecProvider, + natsMetricsSpecProvider, + natsLogsSpecProvider, + zeekLogsSpecProvider, + corednsMetricsSpecProvider, + corednsLogsSpecProvider, + auditbeatSpecProvider, + iptablesLogsSpecProvider, + ciscoLogsSpecProvider, + envoyproxyLogsSpecProvider, + couchdbMetricsSpecProvider, + consulMetricsSpecProvider, + cockroachdbMetricsSpecProvider, + traefikMetricsSpecProvider, + awsLogsSpecProvider, + activemqLogsSpecProvider, + activemqMetricsSpecProvider, + azureMetricsSpecProvider, + ibmmqLogsSpecProvider, + ibmmqMetricsSpecProvider, + stanMetricsSpecProvider, + envoyproxyMetricsSpecProvider, + statsdMetricsSpecProvider, +]; diff --git a/src/plugins/home/server/tutorials/stan_metrics/index.ts b/src/plugins/home/server/tutorials/stan_metrics/index.ts new file mode 100644 index 00000000000000..7dd949704d3cfc --- /dev/null +++ b/src/plugins/home/server/tutorials/stan_metrics/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function stanMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'stan'; + return { + id: 'stanMetrics', + name: i18n.translate('home.tutorials.stanMetrics.nameTitle', { + defaultMessage: 'STAN metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.stanMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from the STAN server.', + }), + longDescription: i18n.translate('home.tutorials.stanMetrics.longDescription', { + defaultMessage: + 'The `stan` Metricbeat module fetches monitoring metrics from STAN. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-stan.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/stan.svg', + artifacts: { + dashboards: [ + { + id: 'dbf2e220-37ce-11ea-a9c8-152a657da3ab', + linkLabel: i18n.translate('home.tutorials.stanMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Stan metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-stan.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/stan_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/statsd_metrics/index.ts b/src/plugins/home/server/tutorials/statsd_metrics/index.ts new file mode 100644 index 00000000000000..c1d4a354e94967 --- /dev/null +++ b/src/plugins/home/server/tutorials/statsd_metrics/index.ts @@ -0,0 +1,61 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory, TutorialSchema } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +export function statsdMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'statsd'; + return { + id: 'statsdMetrics', + name: i18n.translate('home.tutorials.statsdMetrics.nameTitle', { + defaultMessage: 'Statsd metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.statsdMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from statsd.', + }), + longDescription: i18n.translate('home.tutorials.statsdMetrics.longDescription', { + defaultMessage: + 'The `statsd` Metricbeat module fetches monitoring metrics from statsd. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-statsd.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/statsd.svg', + artifacts: { + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-statsd.html', + }, + }, + completionTimeMinutes: 10, + // previewImagePath: '', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/suricata_logs/index.ts b/src/plugins/home/server/tutorials/suricata_logs/index.ts new file mode 100644 index 00000000000000..ac19cf0987b840 --- /dev/null +++ b/src/plugins/home/server/tutorials/suricata_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function suricataLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'suricata'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'suricataLogs', + name: i18n.translate('home.tutorials.suricataLogs.nameTitle', { + defaultMessage: 'Suricata logs', + }), + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.suricataLogs.shortDescription', { + defaultMessage: 'Collect the result logs created by Suricata IDS/IPS/NSM.', + }), + longDescription: i18n.translate('home.tutorials.suricataLogs.longDescription', { + defaultMessage: + 'The `suricata` Filebeat module collects the logs from the \ +[Suricata Eve JSON output](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html). \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-suricata.html', + }, + }), + // euiIconType: 'logoSuricata', + artifacts: { + dashboards: [ + { + id: '69f5ae20-eb02-11e7-8f04-51231daa5b05', + linkLabel: i18n.translate('home.tutorials.suricataLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Suricata logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-suricata.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/suricata_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/system_logs/index.ts b/src/plugins/home/server/tutorials/system_logs/index.ts new file mode 100644 index 00000000000000..fc2fa4f49fd5f4 --- /dev/null +++ b/src/plugins/home/server/tutorials/system_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function systemLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'system'; + const platforms = ['OSX', 'DEB', 'RPM'] as const; + return { + id: 'systemLogs', + name: i18n.translate('home.tutorials.systemLogs.nameTitle', { + defaultMessage: 'System logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.systemLogs.shortDescription', { + defaultMessage: 'Collect and parse logs written by the local Syslog server.', + }), + longDescription: i18n.translate('home.tutorials.systemLogs.longDescription', { + defaultMessage: + 'The `system` Filebeat module collects and parses logs created by the system logging service of common \ +Unix/Linux based distributions. This module is not available on Windows. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-system.html', + }, + }), + artifacts: { + dashboards: [ + { + id: 'Filebeat-syslog-dashboard-ecs', + linkLabel: i18n.translate('home.tutorials.systemLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'System logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-system.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/system_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/system_metrics/index.ts b/src/plugins/home/server/tutorials/system_metrics/index.ts new file mode 100644 index 00000000000000..b0355e1118a969 --- /dev/null +++ b/src/plugins/home/server/tutorials/system_metrics/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function systemMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'system'; + return { + id: 'systemMetrics', + name: i18n.translate('home.tutorials.systemMetrics.nameTitle', { + defaultMessage: 'System metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.systemMetrics.shortDescription', { + defaultMessage: 'Collect CPU, memory, network, and disk statistics from the host.', + }), + longDescription: i18n.translate('home.tutorials.systemMetrics.longDescription', { + defaultMessage: + 'The `system` Metricbeat module collects CPU, memory, network, and disk statistics from the host. \ +It collects system wide statistics and statistics per process and filesystem. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-system.html', + }, + }), + artifacts: { + dashboards: [ + { + id: 'Metricbeat-system-overview-ecs', + linkLabel: i18n.translate('home.tutorials.systemMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'System metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-system.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/system_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/traefik_logs/index.ts b/src/plugins/home/server/tutorials/traefik_logs/index.ts new file mode 100644 index 00000000000000..423023a3902e5a --- /dev/null +++ b/src/plugins/home/server/tutorials/traefik_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'traefik'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'traefikLogs', + name: i18n.translate('home.tutorials.traefikLogs.nameTitle', { + defaultMessage: 'Traefik logs', + }), + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.traefikLogs.shortDescription', { + defaultMessage: 'Collect and parse access logs created by the Traefik Proxy.', + }), + longDescription: i18n.translate('home.tutorials.traefikLogs.longDescription', { + defaultMessage: + 'The `traefik` Filebeat module parses access logs created by Traefik. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-traefik.html', + }, + }), + // euiIconType: 'logoTraefik', + artifacts: { + dashboards: [ + { + id: 'Filebeat-Traefik-Dashboard-ecs', + linkLabel: i18n.translate('home.tutorials.traefikLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Traefik logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-traefik.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/traefik_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/traefik_metrics/index.ts b/src/plugins/home/server/tutorials/traefik_metrics/index.ts new file mode 100644 index 00000000000000..8fe81eca4c601a --- /dev/null +++ b/src/plugins/home/server/tutorials/traefik_metrics/index.ts @@ -0,0 +1,61 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory, TutorialSchema } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; + +export function traefikMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'traefik'; + return { + id: 'traefikMetrics', + name: i18n.translate('home.tutorials.traefikMetrics.nameTitle', { + defaultMessage: 'Traefik metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.traefikMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from Traefik.', + }), + longDescription: i18n.translate('home.tutorials.traefikMetrics.longDescription', { + defaultMessage: + 'The `traefik` Metricbeat module fetches monitoring metrics from Traefik. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-traefik.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/traefik.svg', + artifacts: { + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-traefik.html', + }, + }, + completionTimeMinutes: 10, + // previewImagePath: '/plugins/kibana/home/tutorial_resources/traefik_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/uptime_monitors/index.ts b/src/plugins/home/server/tutorials/uptime_monitors/index.ts new file mode 100644 index 00000000000000..207bc0cb479be1 --- /dev/null +++ b/src/plugins/home/server/tutorials/uptime_monitors/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/heartbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function uptimeMonitorsSpecProvider(context: TutorialContext): TutorialSchema { + return { + id: 'uptimeMonitors', + name: i18n.translate('home.tutorials.uptimeMonitors.nameTitle', { + defaultMessage: 'Uptime Monitors', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.uptimeMonitors.shortDescription', { + defaultMessage: 'Monitor services for their availability', + }), + longDescription: i18n.translate('home.tutorials.uptimeMonitors.longDescription', { + defaultMessage: + 'Monitor services for their availability with active probing. \ + Given a list of URLs, Heartbeat asks the simple question: Are you alive? \ + [Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.heartbeat}/heartbeat-getting-started.html', + }, + }), + euiIconType: 'uptimeApp', + artifacts: { + dashboards: [], + application: { + path: '/app/uptime', + label: i18n.translate('home.tutorials.uptimeMonitors.artifacts.dashboards.linkLabel', { + defaultMessage: 'Uptime App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.heartbeat}/exported-fields.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/uptime_monitors/screenshot.png', + onPrem: onPremInstructions([], context), + elasticCloud: cloudInstructions(), + onPremElasticCloud: onPremCloudInstructions(), + }; +} diff --git a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts new file mode 100644 index 00000000000000..fc36cfe8698675 --- /dev/null +++ b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function uwsgiMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'uwsgi'; + return { + id: 'uwsgiMetrics', + name: i18n.translate('home.tutorials.uwsgiMetrics.nameTitle', { + defaultMessage: 'uWSGI metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.uwsgiMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from the uWSGI server.', + }), + longDescription: i18n.translate('home.tutorials.uwsgiMetrics.longDescription', { + defaultMessage: + 'The `uwsgi` Metricbeat module fetches internal metrics from the uWSGI server. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-uwsgi.html', + }, + }), + // euiIconType: 'logouWSGI', + isBeta: false, + artifacts: { + dashboards: [ + { + id: '32fca290-f0af-11e7-b9ff-9f96241065de-ecs', + linkLabel: i18n.translate('home.tutorials.uwsgiMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'uWSGI metrics dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-uwsgi.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/uwsgi_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts new file mode 100644 index 00000000000000..3ea57cdbc0e442 --- /dev/null +++ b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function vSphereMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'vsphere'; + return { + id: 'vsphereMetrics', + name: i18n.translate('home.tutorials.vsphereMetrics.nameTitle', { + defaultMessage: 'vSphere metrics', + }), + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.vsphereMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from vSphere.', + }), + longDescription: i18n.translate('home.tutorials.vsphereMetrics.longDescription', { + defaultMessage: + 'The `vsphere` Metricbeat module fetches internal metrics from a vSphere cluster. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-vsphere.html', + }, + }), + // euiIconType: 'logoVSphere', + isBeta: true, + artifacts: { + application: { + label: i18n.translate('home.tutorials.vsphereMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-vsphere.html', + }, + }, + completionTimeMinutes: 10, + // previewImagePath: '/plugins/kibana/home/tutorial_resources/vsphere_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/windows_event_logs/index.ts b/src/plugins/home/server/tutorials/windows_event_logs/index.ts new file mode 100644 index 00000000000000..5349bedb212797 --- /dev/null +++ b/src/plugins/home/server/tutorials/windows_event_logs/index.ts @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/winlogbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function windowsEventLogsSpecProvider(context: TutorialContext): TutorialSchema { + return { + id: 'windowsEventLogs', + name: i18n.translate('home.tutorials.windowsEventLogs.nameTitle', { + defaultMessage: 'Windows Event Log', + }), + isBeta: false, + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.windowsEventLogs.shortDescription', { + defaultMessage: 'Fetch logs from the Windows Event Log.', + }), + longDescription: i18n.translate('home.tutorials.windowsEventLogs.longDescription', { + defaultMessage: + 'Use Winlogbeat to collect the logs from the Windows Event Log. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.winlogbeat}/index.html', + }, + }), + euiIconType: 'logoWindows', + artifacts: { + application: { + label: i18n.translate('home.tutorials.windowsEventLogs.artifacts.application.label', { + defaultMessage: 'SIEM App', + }), + path: '/app/siem', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.winlogbeat}/exported-fields.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(context), + elasticCloud: cloudInstructions(), + onPremElasticCloud: onPremCloudInstructions(), + }; +} diff --git a/src/plugins/home/server/tutorials/windows_metrics/index.ts b/src/plugins/home/server/tutorials/windows_metrics/index.ts new file mode 100644 index 00000000000000..fa855a82b3b776 --- /dev/null +++ b/src/plugins/home/server/tutorials/windows_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function windowsMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'windows'; + return { + id: 'windowsMetrics', + name: i18n.translate('home.tutorials.windowsMetrics.nameTitle', { + defaultMessage: 'Windows metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.windowsMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from Windows.', + }), + longDescription: i18n.translate('home.tutorials.windowsMetrics.longDescription', { + defaultMessage: + 'The `windows` Metricbeat module fetches internal metrics from Windows. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-windows.html', + }, + }), + euiIconType: 'logoWindows', + artifacts: { + application: { + label: i18n.translate('home.tutorials.windowsMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-windows.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/home/server/tutorials/zeek_logs/index.ts b/src/plugins/home/server/tutorials/zeek_logs/index.ts new file mode 100644 index 00000000000000..c015545046c99f --- /dev/null +++ b/src/plugins/home/server/tutorials/zeek_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'zeek'; + const platforms = ['OSX', 'DEB', 'RPM'] as const; + return { + id: 'zeekLogs', + name: i18n.translate('home.tutorials.zeekLogs.nameTitle', { + defaultMessage: 'Zeek logs', + }), + category: TutorialsCategory.SIEM, + shortDescription: i18n.translate('home.tutorials.zeekLogs.shortDescription', { + defaultMessage: 'Collect the logs created by Zeek/Bro.', + }), + longDescription: i18n.translate('home.tutorials.zeekLogs.longDescription', { + defaultMessage: + 'The `zeek` Filebeat module collects the logs from \ +[Zeek](https://www.zeek.org//documentation/index.html). \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-zeek.html', + }, + }), + // TODO: euiIconType: 'logoZeek', + artifacts: { + dashboards: [ + { + id: '7cbb5410-3700-11e9-aa6d-ff445a78330c', + linkLabel: i18n.translate('home.tutorials.zeekLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Zeek logs dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-zeek.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/zeek_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts new file mode 100644 index 00000000000000..dcecbb6d4a812e --- /dev/null +++ b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/metricbeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function zookeeperMetricsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'zookeeper'; + return { + id: moduleName + 'Metrics', + name: i18n.translate('home.tutorials.zookeeperMetrics.nameTitle', { + defaultMessage: 'Zookeeper metrics', + }), + isBeta: false, + category: TutorialsCategory.METRICS, + shortDescription: i18n.translate('home.tutorials.zookeeperMetrics.shortDescription', { + defaultMessage: 'Fetch internal metrics from a Zookeeper server.', + }), + longDescription: i18n.translate('home.tutorials.zookeeperMetrics.longDescription', { + defaultMessage: + 'The `{moduleName}` Metricbeat module fetches internal metrics from a Zookeeper server. \ +[Learn more]({learnMoreLink}).', + values: { + moduleName, + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-' + moduleName + '.html', + }, + }), + artifacts: { + application: { + label: i18n.translate('home.tutorials.zookeeperMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover', + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-' + moduleName + '.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName), + }; +} diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index cfe89f16e99dd5..81f2e694e8e5b5 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -25,5 +25,6 @@ export * from './overlays'; export * from './ui_settings'; export * from './field_icon'; export * from './table_list_view'; +export * from './split_panel'; export { useUrlTracker } from './use_url_tracker'; export { toMountPoint } from './util'; diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx b/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx index 1522c6b42824c5..2a43f29024ba7a 100644 --- a/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx +++ b/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx @@ -164,6 +164,7 @@ class SavedObjectFinderUi extends React.Component< if (query === this.state.query) { this.setState({ isFetchingItems: false, + page: 0, items: resp.savedObjects.map(savedObject => { const { attributes: { title }, diff --git a/src/plugins/console/public/application/components/split_panel/__snapshots__/split_panel.test.tsx.snap b/src/plugins/kibana_react/public/split_panel/__snapshots__/split_panel.test.tsx.snap similarity index 100% rename from src/plugins/console/public/application/components/split_panel/__snapshots__/split_panel.test.tsx.snap rename to src/plugins/kibana_react/public/split_panel/__snapshots__/split_panel.test.tsx.snap diff --git a/src/plugins/console/public/application/components/split_panel/components/resizer.tsx b/src/plugins/kibana_react/public/split_panel/components/resizer.tsx similarity index 94% rename from src/plugins/console/public/application/components/split_panel/components/resizer.tsx rename to src/plugins/kibana_react/public/split_panel/components/resizer.tsx index 67fe92b7eb03a2..306db4c7d9a638 100644 --- a/src/plugins/console/public/application/components/split_panel/components/resizer.tsx +++ b/src/plugins/kibana_react/public/split_panel/components/resizer.tsx @@ -35,7 +35,7 @@ export function Resizer(props: Props) { - -
    -
    -
    -`; - exports[`Storyshots components/Export/WorkpadExport enabled 1`] = `
    ( -
    - -
    - )); diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/__examples__/workpad_export.examples.tsx b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/__examples__/workpad_export.examples.tsx index 7e401194f44f18..92e7cca40ee3ab 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/__examples__/workpad_export.examples.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/__examples__/workpad_export.examples.tsx @@ -8,26 +8,13 @@ import { action } from '@storybook/addon-actions'; import React from 'react'; import { WorkpadExport } from '../workpad_export'; -storiesOf('components/Export/WorkpadExport', module) - .add('enabled', () => ( - { - action(`getExportUrl('${type}')`); - return type; - }} - /> - )) - .add('disabled', () => ( - { - action(`getExportUrl('${type}')`); - return type; - }} - /> - )); +storiesOf('components/Export/WorkpadExport', module).add('enabled', () => ( + { + action(`getExportUrl('${type}')`); + return type; + }} + /> +)); diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/disabled_panel.tsx b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/disabled_panel.tsx deleted file mode 100644 index 85d1174f50bbd7..00000000000000 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/disabled_panel.tsx +++ /dev/null @@ -1,50 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiText, EuiSpacer, EuiCodeBlock, EuiCode } from '@elastic/eui'; -import { Clipboard } from '../../clipboard'; - -const REPORTING_CONFIG = `xpack.reporting: - enabled: true - capture.browser.type: chromium`; - -interface Props { - /** Handler to invoke when the Kibana configuration is copied. */ - onCopy: () => void; -} - -/** - * A panel to display within the Export menu when reporting is disabled. - */ -export const DisabledPanel = ({ onCopy }: Props) => ( -
    - -

    - kibana.yml, - }} - /> -

    -
    - - - - {REPORTING_CONFIG} - - -
    -); diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/index.ts b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/index.ts index 2b2a582fb45263..39611dd6c2994c 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/index.ts +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/index.ts @@ -10,8 +10,6 @@ import { jobCompletionNotifications } from '../../../../../reporting/public/lib/ // @ts-ignore Untyped local import { getWorkpad, getPages } from '../../../state/selectors/workpad'; // @ts-ignore Untyped local -import { getReportingBrowserType } from '../../../state/selectors/app'; -// @ts-ignore Untyped local import { notify } from '../../../lib/notify'; import { getWindow } from '../../../lib/get_window'; // @ts-ignore Untyped local @@ -34,7 +32,6 @@ const { WorkpadHeaderWorkpadExport: strings } = ComponentStrings; const mapStateToProps = (state: State) => ({ workpad: getWorkpad(state), pageCount: getPages(state).length, - enabled: getReportingBrowserType(state) === 'chromium', }); const getAbsoluteUrl = (path: string) => { @@ -51,15 +48,13 @@ const getAbsoluteUrl = (path: string) => { interface Props { workpad: CanvasWorkpad; pageCount: number; - enabled: boolean; } export const WorkpadExport = compose( connect(mapStateToProps), withKibana, withProps( - ({ workpad, pageCount, enabled, kibana }: Props & WithKibanaProps): ComponentProps => ({ - enabled, + ({ workpad, pageCount, kibana }: Props & WithKibanaProps): ComponentProps => ({ getExportUrl: type => { if (type === 'pdf') { const pdfUrl = getPdfUrl(workpad, { pageCount }, kibana.services.http.basePath.prepend); diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/workpad_export.tsx b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/workpad_export.tsx index 0558652fb60294..522be043ec4577 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/workpad_export.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/workpad_export.tsx @@ -9,7 +9,6 @@ import PropTypes from 'prop-types'; import { EuiButtonIcon, EuiContextMenu, EuiIcon } from '@elastic/eui'; // @ts-ignore Untyped local import { Popover } from '../../popover'; -import { DisabledPanel } from './disabled_panel'; import { PDFPanel } from './pdf_panel'; import { ShareWebsiteFlyout } from './flyout'; @@ -29,8 +28,6 @@ export type OnCloseFn = (type: CloseTypes) => void; export type GetExportUrlFn = (type: ExportUrlTypes) => string; export interface Props { - /** True if exporting is enabled, false otherwise. */ - enabled: boolean; /** Handler to invoke when an export URL is copied to the clipboard. */ onCopy: OnCopyFn; /** Handler to invoke when an end product is exported. */ @@ -42,12 +39,7 @@ export interface Props { /** * The Menu for Exporting a Workpad from Canvas. */ -export const WorkpadExport: FunctionComponent = ({ - enabled, - onCopy, - onExport, - getExportUrl, -}) => { +export const WorkpadExport: FunctionComponent = ({ onCopy, onExport, getExportUrl }) => { const [showFlyout, setShowFlyout] = useState(false); const onClose = () => { @@ -106,16 +98,7 @@ export const WorkpadExport: FunctionComponent = ({ panel: { id: 1, title: strings.getShareDownloadPDFTitle(), - content: enabled ? ( - getPDFPanel(closePopover) - ) : ( - { - onCopy('reportingConfig'); - closePopover(); - }} - /> - ), + content: getPDFPanel(closePopover), }, }, { @@ -160,7 +143,6 @@ export const WorkpadExport: FunctionComponent = ({ }; WorkpadExport.propTypes = { - enabled: PropTypes.bool.isRequired, onCopy: PropTypes.func.isRequired, onExport: PropTypes.func.isRequired, getExportUrl: PropTypes.func.isRequired, diff --git a/x-pack/legacy/plugins/canvas/public/legacy.ts b/x-pack/legacy/plugins/canvas/public/legacy.ts index 61e12893b3e02f..254fba0f23ad27 100644 --- a/x-pack/legacy/plugins/canvas/public/legacy.ts +++ b/x-pack/legacy/plugins/canvas/public/legacy.ts @@ -9,8 +9,6 @@ import { CanvasStartDeps } from './plugin'; // eslint-disable-line import/order // @ts-ignore Untyped Kibana Lib import chrome, { loadingCount } from 'ui/chrome'; // eslint-disable-line import/order -// @ts-ignore Untyped Module -import { uiModules } from 'ui/modules'; // eslint-disable-line import/order import { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; // eslint-disable-line import/order import { Storage } from '../../../../../src/plugins/kibana_utils/public'; // eslint-disable-line import/order // @ts-ignore Untyped Kibana Lib @@ -25,6 +23,7 @@ const shimCoreStart = { ...npStart.core, }; const shimSetupPlugins = {}; + const shimStartPlugins: CanvasStartDeps = { ...npStart.plugins, __LEGACY: { @@ -33,12 +32,9 @@ const shimStartPlugins: CanvasStartDeps = { // ToDo: Copy directly into canvas formatMsg, QueryString, - // ToDo: Remove in favor of core.application.register - setRootController: chrome.setRootController, storage: Storage, // ToDo: Won't be a part of New Platform. Will need to handle internally trackSubUrlForApp: chrome.trackSubUrlForApp, - uiModules, }, }; diff --git a/x-pack/legacy/plugins/canvas/public/plugin.tsx b/x-pack/legacy/plugins/canvas/public/plugin.tsx index 155eef99632a0d..7928d46067908b 100644 --- a/x-pack/legacy/plugins/canvas/public/plugin.tsx +++ b/x-pack/legacy/plugins/canvas/public/plugin.tsx @@ -7,15 +7,15 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Chrome } from 'ui/chrome'; -import { IModule } from 'angular'; import { i18n } from '@kbn/i18n'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { CoreSetup, CoreStart, Plugin } from '../../../../../src/core/public'; // @ts-ignore: Untyped Local -import { initStateManagement, initLocationProvider } from './angular/config'; -import { CanvasRootControllerFactory } from './angular/controllers'; -// @ts-ignore: Untypled Local -import { initStore } from './angular/services'; +import { CapabilitiesStrings } from '../i18n'; +const { ReadOnlyBadge: strings } = CapabilitiesStrings; + +import { createStore } from './store'; + // @ts-ignore: untyped local component import { HelpMenu } from './components/help_menu/help_menu'; // @ts-ignore: untyped local @@ -40,12 +40,8 @@ export interface CanvasStartDeps { absoluteToParsedUrl: (url: string, basePath: string) => any; formatMsg: any; QueryString: any; - setRootController: Chrome['setRootController']; storage: typeof Storage; trackSubUrlForApp: Chrome['trackSubUrlForApp']; - uiModules: { - get: (module: string) => IModule; - }; }; } @@ -67,6 +63,22 @@ export class CanvasPlugin // Things like registering functions to the interpreter that need // to be available everywhere, not just in Canvas + core.application.register({ + id: 'canvas', + title: 'Canvas App', + async mount(context, params) { + // Load application bundle + const { renderApp } = await import('./application'); + + // Setup our store + const canvasStore = await createStore(core, plugins); + + // Get start services + const [coreStart, depsStart] = await core.getStartServices(); + + return renderApp(coreStart, depsStart, params, canvasStore); + }, + }); return {}; } @@ -74,14 +86,19 @@ export class CanvasPlugin loadExpressionTypes(); loadTransitions(); - initStateManagement(core, plugins); - initLocationProvider(core, plugins); - initStore(core, plugins); initClipboard(plugins.__LEGACY.storage); initLoadingIndicator(core.http.addLoadingCountSource); - const CanvasRootController = CanvasRootControllerFactory(core, plugins); - plugins.__LEGACY.setRootController('canvas', CanvasRootController); + core.chrome.setBadge( + core.application.capabilities.canvas && core.application.capabilities.canvas.save + ? undefined + : { + text: strings.getText(), + tooltip: strings.getTooltip(), + iconType: 'glasses', + } + ); + core.chrome.setHelpExtension({ appName: i18n.translate('xpack.canvas.helpMenu.appName', { defaultMessage: 'Canvas', diff --git a/x-pack/legacy/plugins/canvas/public/state/selectors/app.ts b/x-pack/legacy/plugins/canvas/public/state/selectors/app.ts index 255d45cf558fcc..d68702a30d6450 100644 --- a/x-pack/legacy/plugins/canvas/public/state/selectors/app.ts +++ b/x-pack/legacy/plugins/canvas/public/state/selectors/app.ts @@ -32,10 +32,6 @@ export function getBasePath(state: State): State['app']['basePath'] { return state.app.basePath; } -export function getReportingBrowserType(state: State): State['app']['reportingBrowserType'] { - return state.app.reportingBrowserType; -} - // return true only when the required parameters are in the state export function isAppReady(state: State): boolean { const appReady = getAppReady(state); diff --git a/x-pack/legacy/plugins/canvas/public/store.ts b/x-pack/legacy/plugins/canvas/public/store.ts new file mode 100644 index 00000000000000..0a378979f6ad99 --- /dev/null +++ b/x-pack/legacy/plugins/canvas/public/store.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; + * you may not use this file except in compliance with the Elastic License. + */ + +// @ts-ignore Untyped local +import { createStore as createReduxStore } from './state/store'; +// @ts-ignore Untyped local +import { getInitialState } from './state/initial_state'; + +import { CoreSetup } from '../../../../../src/core/public'; +import { CanvasSetupDeps } from './plugin'; + +export async function createStore(core: CoreSetup, plugins: CanvasSetupDeps) { + const initialState = getInitialState(); + + const basePath = core.http.basePath.get(); + + // Retrieve server functions + const serverFunctionsResponse = await core.http.get(`/api/interpreter/fns`); + const serverFunctions = Object.values(serverFunctionsResponse); + + initialState.app = { + basePath, + serverFunctions, + ready: false, + }; + + return createReduxStore(initialState); +} diff --git a/x-pack/legacy/plugins/canvas/server/plugin.ts b/x-pack/legacy/plugins/canvas/server/plugin.ts index 07f4b7d9ac6dbb..ac3edbabce930e 100644 --- a/x-pack/legacy/plugins/canvas/server/plugin.ts +++ b/x-pack/legacy/plugins/canvas/server/plugin.ts @@ -13,25 +13,11 @@ export class Plugin { public setup(core: CoreSetup, plugins: PluginsSetup) { routes(core); - const { serverFunctions } = plugins.interpreter.register({ serverFunctions: functions }); + plugins.interpreter.register({ serverFunctions: functions }); core.injectUiAppVars('canvas', async () => { - const config = core.getServerConfig(); - const basePath = config.get('server.basePath'); - const reportingBrowserType = (() => { - const configKey = 'xpack.reporting.capture.browser.type'; - if (!config.has(configKey)) { - return null; - } - return config.get(configKey); - })(); - return { ...plugins.kibana.injectedUiAppVars, - kbnIndex: config.get('kibana.index'), - serverFunctions: serverFunctions.toArray(), - basePath, - reportingBrowserType, }; }); diff --git a/x-pack/legacy/plugins/canvas/types/state.ts b/x-pack/legacy/plugins/canvas/types/state.ts index 3aca3003f9dc50..171c5515fbb2aa 100644 --- a/x-pack/legacy/plugins/canvas/types/state.ts +++ b/x-pack/legacy/plugins/canvas/types/state.ts @@ -32,9 +32,7 @@ export interface AppState { } interface StoreAppState { - kbnVersion: string; basePath: string; - reportingBrowserType: string; // TODO: These server functions are actually missing the fn because they are serialized from the server serverFunctions: CanvasFunction[]; ready: boolean; diff --git a/x-pack/legacy/plugins/dashboard_mode/index.js b/x-pack/legacy/plugins/dashboard_mode/index.js index 4a042498443220..94655adf981b48 100644 --- a/x-pack/legacy/plugins/dashboard_mode/index.js +++ b/x-pack/legacy/plugins/dashboard_mode/index.js @@ -5,15 +5,13 @@ */ import { resolve } from 'path'; - +import { i18n } from '@kbn/i18n'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; import { CONFIG_DASHBOARD_ONLY_MODE_ROLES } from './common'; - import { createDashboardModeRequestInterceptor } from './server'; -import { i18n } from '@kbn/i18n'; - // Copied largely from plugins/kibana/index.js. The dashboard viewer includes just the dashboard section of -// the standard kibana plugin. We don't want to include code for the other links (visualize, dev tools, etc) +// the standard kibana plugin. We don't want to include code for the other links (visualize, dev tools, etc) // since it's view only, but we want the urls to be the same, so we are using largely the same setup. export function dashboardMode(kibana) { const kbnBaseUrl = '/app/kibana'; @@ -64,6 +62,7 @@ export function dashboardMode(kibana) { } ), icon: 'plugins/kibana/dashboard/assets/dashboard.svg', + category: DEFAULT_APP_CATEGORIES.analyze, }, ], }, diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index 391973f6d909b4..fbf917054edbff 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -34,6 +34,7 @@ import 'ui/color_maps'; import 'ui/agg_response'; import 'ui/agg_types'; import 'leaflet'; +import 'plugins/kibana/dashboard/legacy'; import { npStart } from 'ui/new_platform'; import { localApplicationService } from 'plugins/kibana/local_application_service'; diff --git a/x-pack/legacy/plugins/file_upload/public/components/json_index_file_picker.js b/x-pack/legacy/plugins/file_upload/public/components/json_index_file_picker.js index f1e74919d734b3..0ee4f76ebf9d0c 100644 --- a/x-pack/legacy/plugins/file_upload/public/components/json_index_file_picker.js +++ b/x-pack/legacy/plugins/file_upload/public/components/json_index_file_picker.js @@ -13,6 +13,8 @@ import { MAX_FILE_SIZE } from '../../common/constants/file_import'; import _ from 'lodash'; const ACCEPTABLE_FILETYPES = ['json', 'geojson']; +const acceptedFileTypeString = ACCEPTABLE_FILETYPES.map(type => `.${type}`).join(','); +const acceptedFileTypeStringMessage = ACCEPTABLE_FILETYPES.map(type => `.${type}`).join(', '); export class JsonIndexFilePicker extends Component { state = { @@ -103,6 +105,7 @@ export class JsonIndexFilePicker extends Component { const splitNameArr = name.split('.'); const fileType = splitNameArr.pop(); if (!ACCEPTABLE_FILETYPES.includes(fileType)) { + //should only occur if browser does not accept the accept parameter throw new Error( i18n.translate('xpack.fileUpload.jsonIndexFilePicker.acceptableTypesError', { defaultMessage: 'File is not one of acceptable types: {types}', @@ -252,7 +255,10 @@ export class JsonIndexFilePicker extends Component { ) : ( {i18n.translate('xpack.fileUpload.jsonIndexFilePicker.formatsAccepted', { - defaultMessage: 'Formats accepted: .json, .geojson', + defaultMessage: 'Formats accepted: {acceptedFileTypeStringMessage}', + values: { + acceptedFileTypeStringMessage, + }, })}{' '}
    } onChange={this._fileHandler} + accept={acceptedFileTypeString} /> diff --git a/x-pack/legacy/plugins/graph/index.ts b/x-pack/legacy/plugins/graph/index.ts index 601a239574e6b5..f798fa5e9f39d4 100644 --- a/x-pack/legacy/plugins/graph/index.ts +++ b/x-pack/legacy/plugins/graph/index.ts @@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n'; import migrations from './migrations'; import mappings from './mappings.json'; import { LegacyPluginInitializer } from '../../../../src/legacy/plugin_discovery/types'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; export const graph: LegacyPluginInitializer = kibana => { return new kibana.Plugin({ @@ -25,6 +26,7 @@ export const graph: LegacyPluginInitializer = kibana => { icon: 'plugins/graph/icon.png', euiIconType: 'graphApp', main: 'plugins/graph/index', + category: DEFAULT_APP_CATEGORIES.analyze, }, styleSheetPaths: resolve(__dirname, 'public/index.scss'), mappings, diff --git a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx index f34b82d6bb1a3c..d1fcbea2ff5b72 100644 --- a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx +++ b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx @@ -146,7 +146,7 @@ function GuidancePanelComponent(props: GuidancePanelProps) { ); if (noIndexPatterns) { - const managementUrl = chrome.navLinks.get('kibana:management')!.url; + const managementUrl = chrome.navLinks.get('kibana:stack_management')!.url; const indexPatternUrl = `${managementUrl}/kibana/index_patterns`; const sampleDataUrl = `${application.getUrlForApp( 'kibana' diff --git a/x-pack/legacy/plugins/graph/public/services/persistence/deserialize.ts b/x-pack/legacy/plugins/graph/public/services/persistence/deserialize.ts index 43425077cc174d..0bef31e9fb7fe6 100644 --- a/x-pack/legacy/plugins/graph/public/services/persistence/deserialize.ts +++ b/x-pack/legacy/plugins/graph/public/services/persistence/deserialize.ts @@ -24,7 +24,7 @@ import { colorChoices, iconChoicesByClass, } from '../../helpers/style_choices'; -import { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import { IndexPattern, isNestedField } from '../../../../../../../src/plugins/data/public'; const defaultAdvancedSettings: AdvancedSettings = { useSignificance: true, @@ -80,7 +80,7 @@ export function mapFields(indexPattern: IndexPattern): WorkspaceField[] { return indexPattern .getNonScriptedFields() - .filter(field => !blockedFieldNames.includes(field.name)) + .filter(field => !blockedFieldNames.includes(field.name) && !isNestedField(field)) .map((field, index) => ({ name: field.name, hopSize: defaultHopSize, diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js index d57bf759ad7219..475d26bb2e3c04 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js @@ -169,6 +169,30 @@ export class HotPhase extends PureComponent { defaultMessage: 'megabytes', }), }, + { + value: 'b', + text: i18n.translate('xpack.indexLifecycleMgmt.hotPhase.bytesLabel', { + defaultMessage: 'bytes', + }), + }, + { + value: 'kb', + text: i18n.translate('xpack.indexLifecycleMgmt.hotPhase.kilobytesLabel', { + defaultMessage: 'kilobytes', + }), + }, + { + value: 'tb', + text: i18n.translate('xpack.indexLifecycleMgmt.hotPhase.terabytesLabel', { + defaultMessage: 'terabytes', + }), + }, + { + value: 'pb', + text: i18n.translate('xpack.indexLifecycleMgmt.hotPhase.petabytesLabel', { + defaultMessage: 'petabytes', + }), + }, ]} /> @@ -254,6 +278,45 @@ export class HotPhase extends PureComponent { defaultMessage: 'hours', }), }, + { + value: 'm', + text: i18n.translate('xpack.indexLifecycleMgmt.hotPhase.minutesLabel', { + defaultMessage: 'minutes', + }), + }, + { + value: 's', + text: i18n.translate('xpack.indexLifecycleMgmt.hotPhase.secondsLabel', { + defaultMessage: 'seconds', + }), + }, + { + value: 'ms', + text: i18n.translate( + 'xpack.indexLifecycleMgmt.hotPhase.millisecondsLabel', + { + defaultMessage: 'milliseconds', + } + ), + }, + { + value: 'micros', + text: i18n.translate( + 'xpack.indexLifecycleMgmt.hotPhase.microsecondsLabel', + { + defaultMessage: 'microseconds', + } + ), + }, + { + value: 'nanos', + text: i18n.translate( + 'xpack.indexLifecycleMgmt.hotPhase.nanosecondsLabel', + { + defaultMessage: 'nanoseconds', + } + ), + }, ]} /> diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js index b4c9f4e958cd22..23009798513296 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js @@ -73,6 +73,11 @@ export const MinAgeInput = props => { let daysOptionLabel; let hoursOptionLabel; + let minutesOptionLabel; + let secondsOptionLabel; + let millisecondsOptionLabel; + let microsecondsOptionLabel; + let nanosecondsOptionLabel; if (rolloverEnabled) { daysOptionLabel = i18n.translate( @@ -88,6 +93,39 @@ export const MinAgeInput = props => { defaultMessage: 'hours from rollover', } ); + minutesOptionLabel = i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel', + { + defaultMessage: 'minutes from rollover', + } + ); + + secondsOptionLabel = i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel', + { + defaultMessage: 'seconds from rollover', + } + ); + millisecondsOptionLabel = i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel', + { + defaultMessage: 'milliseconds from rollover', + } + ); + + microsecondsOptionLabel = i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel', + { + defaultMessage: 'microseconds from rollover', + } + ); + + nanosecondsOptionLabel = i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel', + { + defaultMessage: 'nanoseconds from rollover', + } + ); } else { daysOptionLabel = i18n.translate( 'xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel', @@ -150,6 +188,26 @@ export const MinAgeInput = props => { value: 'h', text: hoursOptionLabel, }, + { + value: 'm', + text: minutesOptionLabel, + }, + { + value: 's', + text: secondsOptionLabel, + }, + { + value: 'ms', + text: millisecondsOptionLabel, + }, + { + value: 'micros', + text: microsecondsOptionLabel, + }, + { + value: 'nanos', + text: nanosecondsOptionLabel, + }, ]} /> diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_form.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_form.helpers.ts index 48ae51b711f9cc..a7c87723b33fb8 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_form.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_form.helpers.ts @@ -198,7 +198,7 @@ export type TestSubjects = | 'backButton' | 'codeEditorContainer' | 'confirmModalConfirmButton' - | 'createFieldWrapper.addChildButton' + | 'createFieldWrapper.addPropertyButton' | 'createFieldWrapper.addButton' | 'createFieldWrapper.addFieldButton' | 'createFieldWrapper.addMultiFieldButton' diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts new file mode 100644 index 00000000000000..e3313bfba56fd9 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { setup as mappingsEditorSetup } from './mappings_editor.helpers'; + +export { + nextTick, + getRandomString, + findTestSubject, + TestBed, +} from '../../../../../../../../../../test_utils'; + +export const componentHelpers = { + mappingsEditor: { setup: mappingsEditorSetup }, +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts new file mode 100644 index 00000000000000..b8b67a0f36bd2e --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { registerTestBed } from '../../../../../../../../../../test_utils'; +import { MappingsEditor } from '../../../mappings_editor'; + +export const setup = (props: any) => + registerTestBed(MappingsEditor, { + memoryRouter: { + wrapComponent: false, + }, + defaultProps: props, + }); diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx new file mode 100644 index 00000000000000..9e390e785c7d56 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { componentHelpers } from './helpers'; + +const { setup } = componentHelpers.mappingsEditor; +const mockOnUpdate = () => undefined; + +describe('', () => { + describe('multiple mappings detection', () => { + test('should show a warning when multiple mappings are detected', async () => { + const defaultValue = { + type1: { + properties: { + name1: { + type: 'keyword', + }, + }, + }, + type2: { + properties: { + name2: { + type: 'keyword', + }, + }, + }, + }; + const testBed = await setup({ onUpdate: mockOnUpdate, defaultValue })(); + const { exists } = testBed; + + expect(exists('mappingsEditor')).toBe(true); + expect(exists('mappingTypesDetectedCallout')).toBe(true); + expect(exists('documentFields')).toBe(false); + }); + + test('should not show a warning when mappings a single-type', async () => { + const defaultValue = { + properties: { + name1: { + type: 'keyword', + }, + }, + }; + const testBed = await setup({ onUpdate: mockOnUpdate, defaultValue })(); + const { exists } = testBed; + + expect(exists('mappingsEditor')).toBe(true); + expect(exists('mappingTypesDetectedCallout')).toBe(false); + expect(exists('documentFields')).toBe(true); + }); + }); +}); diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx index 71b5966c3295db..378d669dee69cb 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx @@ -48,7 +48,7 @@ export const DocumentFields = React.memo(() => { const searchTerm = search.term.trim(); return ( - <> +
    {searchTerm !== '' ? ( @@ -57,6 +57,6 @@ export const DocumentFields = React.memo(() => { editor )} {renderEditField()} - +
    ); }); diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx index 46b0ece4b325ea..0cf22946bf60a6 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx @@ -46,7 +46,11 @@ export const AnalyzersParameter = ({ field, withSearchQuoteAnalyzer = false }: P }); return ( - + ); }} @@ -74,7 +78,7 @@ export const AnalyzersParameter = ({ field, withSearchQuoteAnalyzer = false }: P @@ -88,7 +92,7 @@ export const AnalyzersParameter = ({ field, withSearchQuoteAnalyzer = false }: P diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx new file mode 100644 index 00000000000000..975a6cd9bba4f5 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; + +import { documentationService } from '../../../../../services/documentation'; +import { UseField, CheckBoxField } from '../../../shared_imports'; +import { getFieldConfig } from '../../../lib'; +import { Field } from '../../../types'; +import { EditFieldFormRow } from '../fields/edit_field'; + +/** + * Export custom serializer to be used when we need to serialize the form data to be sent to ES + * @param field The field to be serialized + */ +export const dynamicSerializer = (field: Field): Field => { + if (field.dynamic_toggle === undefined) { + return field; + } + + const dynamic = + field.dynamic_toggle === true ? true : field.dynamic_strict === true ? 'strict' : false; + const { dynamic_toggle, dynamic_strict, ...rest } = field; + + return { + ...rest, + dynamic, + }; +}; + +/** + * Export custom deserializer to be used when we need to deserialize the data coming from ES + * @param field The field to be serialized + */ +export const dynamicDeserializer = (field: Field): Field => { + if (field.dynamic === undefined) { + return field; + } + + const dynamicToggleValue = field.dynamic === true; + const dynamicStrictValue = field.dynamic === 'strict'; + + return { + ...field, + dynamic_toggle: dynamicToggleValue, + dynamic_strict: dynamicStrictValue, + }; +}; +interface Props { + defaultToggleValue: boolean; +} + +export const DynamicParameter = ({ defaultToggleValue }: Props) => { + return ( + + {isOn => { + return isOn === false ? ( + + ) : null; + }} + + ); +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx index ecd9715ea295db..e6acf288331b52 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx @@ -8,21 +8,31 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; +import { ParameterName } from '../../../types'; import { EditFieldFormRow } from '../fields/edit_field'; import { documentationService } from '../../../../../services/documentation'; -export const EagerGlobalOrdinalsParameter = () => ( +interface Props { + configPath?: ParameterName; + description?: string | JSX.Element; +} + +export const EagerGlobalOrdinalsParameter = ({ + description, + configPath = 'eager_global_ordinals', +}: Props) => ( ( href: documentationService.getEagerGlobalOrdinalsLink(), }} formFieldPath="eager_global_ordinals" + configPath={configPath} /> ); diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx new file mode 100644 index 00000000000000..719dd89d4c05c9 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiCode } from '@elastic/eui'; + +import { documentationService } from '../../../../../services/documentation'; +import { EditFieldFormRow } from '../fields/edit_field'; + +export const EnabledParameter = () => { + return ( + _source, + }} + /> + } + docLink={{ + text: i18n.translate('xpack.idxMgmt.mappingsEditor.enabledDocLinkText', { + defaultMessage: 'Enabled documentation', + }), + href: documentationService.getEnabledLink(), + }} + formFieldPath="enabled" + /> + ); +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index.ts index b248776c884f12..663017e2e47afd 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index.ts @@ -4,6 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import { relationsSerializer, relationsDeserializer } from './relations_parameter'; +import { dynamicSerializer, dynamicDeserializer } from './dynamic_parameter'; + export * from './name_parameter'; export * from './index_parameter'; @@ -52,4 +55,14 @@ export * from './split_queries_on_whitespace_parameter'; export * from './locale_parameter'; +export * from './dynamic_parameter'; + +export * from './enabled_parameter'; + export * from './max_shingle_size_parameter'; + +export * from './relations_parameter'; + +export const PARAMETER_SERIALIZERS = [relationsSerializer, dynamicSerializer]; + +export const PARAMETER_DESERIALIZERS = [relationsDeserializer, dynamicDeserializer]; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx new file mode 100644 index 00000000000000..1fe01968b09832 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx @@ -0,0 +1,268 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { + EuiButtonEmpty, + EuiToolTip, + EuiButtonIcon, + EuiSpacer, + EuiCallOut, + EuiLink, + EuiBasicTable, + EuiBasicTableColumn, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + UseField, + UseArray, + ArrayItem, + FieldConfig, + TextField, + ComboBoxField, +} from '../../../shared_imports'; +import { Field } from '../../../types'; + +import { documentationService } from '../../../../../services/documentation'; +import { EditFieldFormRow } from '../fields/edit_field'; + +// This is the Elasticsearch interface to declare relations +interface RelationsES { + [parent: string]: string | string[]; +} + +// Internally we will use this type for "relations" as it is more UI friendly +// to loop over the relations and its children +type RelationsInternal = Array<{ parent: string; children: string[] }>; + +/** + * Export custom serializer to be used when we need to serialize the form data to be sent to ES + * @param field The field to be serialized + */ +export const relationsSerializer = (field: Field): Field => { + if (field.relations === undefined) { + return field; + } + + const relations = field.relations as RelationsInternal; + const relationsSerialized = relations.reduce( + (acc, item) => ({ + ...acc, + [item.parent]: item.children.length === 1 ? item.children[0] : item.children, + }), + {} as RelationsES + ); + + return { + ...field, + relations: relationsSerialized, + }; +}; + +/** + * Export custom deserializer to be used when we need to deserialize the data coming from ES + * @param field The field to be serialized + */ +export const relationsDeserializer = (field: Field): Field => { + if (field.relations === undefined) { + return field; + } + + const relations = field.relations as RelationsES; + const relationsDeserialized = Object.entries(relations).map(([parent, children]) => ({ + parent, + children: typeof children === 'string' ? [children] : children, + })); + + return { + ...field, + relations: relationsDeserialized, + }; +}; + +const childConfig: FieldConfig = { + defaultValue: [], +}; + +export const RelationsParameter = () => { + const renderWarning = () => ( + + {i18n.translate( + 'xpack.idxMgmt.mappingsEditor.join.multiLevelsPerformanceDocumentationLink', + { + defaultMessage: 'denormalize your data.', + } + )} + + ), + }} + /> + } + /> + ); + + return ( + + + {({ items, addItem, removeItem }) => { + const columns: Array> = [ + // Parent column + { + name: i18n.translate( + 'xpack.idxMgmt.mappingsEditor.joinType.relationshipTable.parentColumnTitle', + { + defaultMessage: 'Parent', + } + ), + render: (item: ArrayItem) => { + // By adding ".parent" to the path, we are saying that we want an **object** + // to be created for each array item. + // This object will have a "parent" property with the field value. + return ( +
    + +
    + ); + }, + }, + // Children column (ComboBox) + { + name: i18n.translate( + 'xpack.idxMgmt.mappingsEditor.joinType.relationshipTable.childrenColumnTitle', + { + defaultMessage: 'Children', + } + ), + render: (item: ArrayItem) => { + return ( +
    + +
    + ); + }, + }, + // Actions column + { + width: '48px', + actions: [ + { + render: ({ id }: ArrayItem) => { + const label = i18n.translate( + 'xpack.idxMgmt.mappingsEditor.joinType.relationshipTable.removeRelationshipTooltipLabel', + { + defaultMessage: 'Remove relationship', + } + ); + return ( + + removeItem(id)} + /> + + ); + }, + }, + ], + }, + ]; + + return ( + <> + {items.length > 1 && ( + <> + {renderWarning()} + + + )} + + + + {/* Add relation button */} + + {i18n.translate( + 'xpack.idxMgmt.mappingsEditor.joinType.addRelationshipButtonLabel', + { + defaultMessage: 'Add relationship', + } + )} + + + ); + }} +
    +
    + ); +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx index 3165f18aff4b3d..0c067d09046d73 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx @@ -48,7 +48,7 @@ export const DateType = ({ field }: Props) => { diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/index.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/index.ts index 5b81c525804c98..6e18e29f827d4c 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/index.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/index.ts @@ -24,6 +24,9 @@ import { SearchAsYouType } from './search_as_you_type'; import { FlattenedType } from './flattened_type'; import { ShapeType } from './shape_type'; import { DenseVectorType } from './dense_vector_type'; +import { ObjectType } from './object_type'; +import { NestedType } from './nested_type'; +import { JoinType } from './join_type'; const typeToParametersFormMap: { [key in DataType]?: ComponentType } = { alias: AliasType, @@ -44,6 +47,9 @@ const typeToParametersFormMap: { [key in DataType]?: ComponentType } = { flattened: FlattenedType, shape: ShapeType, dense_vector: DenseVectorType, + object: ObjectType, + nested: NestedType, + join: JoinType, }; export const getParametersFormForType = ( diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx new file mode 100644 index 00000000000000..688786ae25f8c9 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { i18n } from '@kbn/i18n'; + +import { BasicParametersSection, AdvancedParametersSection } from '../edit_field'; +import { RelationsParameter, EagerGlobalOrdinalsParameter } from '../../field_parameters'; + +const i18nTexts = { + eagerGlobalOrdinalsDescription: i18n.translate( + 'xpack.idxMgmt.mappingsEditor.join.eagerGlobalOrdinalsFieldDescription', + { + defaultMessage: + 'The join field uses global ordinals to speed up joins. By default, if the index has changed, global ordinals for the join field will be rebuilt as part of the refresh. This can add significant time to the refresh, however most of the times this is the right trade-off.', + } + ), +}; + +export const JoinType = () => { + return ( + <> + + + + + + + + + ); +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx new file mode 100644 index 00000000000000..72aa88ed75ffb4 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; + +import { NormalizedField } from '../../../../types'; +import { DynamicParameter } from '../../field_parameters'; +import { BasicParametersSection } from '../edit_field'; + +interface Props { + field: NormalizedField; +} + +export const NestedType = ({ field }: Props) => { + return ( + + + + ); +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx index 367a7002815819..89af480d79a205 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx @@ -50,7 +50,7 @@ export const NumericType = ({ field }: Props) => { {formData => formData.subType === 'scaled_float' ? ( diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx new file mode 100644 index 00000000000000..fef1f9860ca51f --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; + +import { NormalizedField } from '../../../../types'; +import { DynamicParameter, EnabledParameter } from '../../field_parameters'; +import { BasicParametersSection } from '../edit_field'; + +interface Props { + field: NormalizedField; +} + +export const ObjectType = ({ field }: Props) => { + return ( + + + + + + ); +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx index 0be754bcfb966d..a7d2af41c83e68 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx @@ -36,7 +36,7 @@ export const RangeType = ({ field }: Props) => { {formData => formData.subType === 'date_range' ? ( ) : null diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx index a2b429373a3e4e..42854673269aee 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx @@ -60,7 +60,7 @@ export const TokenCountType = ({ field }: Props) => { diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx index 285598fc8c3c13..4c1c8bc1da1143 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx @@ -113,9 +113,12 @@ function FieldListItemComponent( } ); - const addChildButtonLabel = i18n.translate('xpack.idxMgmt.mappingsEditor.addChildButtonLabel', { - defaultMessage: 'Add child', - }); + const addPropertyButtonLabel = i18n.translate( + 'xpack.idxMgmt.mappingsEditor.addPropertyButtonLabel', + { + defaultMessage: 'Add property', + } + ); const editButtonLabel = i18n.translate('xpack.idxMgmt.mappingsEditor.editFieldButtonLabel', { defaultMessage: 'Edit', @@ -145,12 +148,12 @@ function FieldListItemComponent( {canHaveChildFields && ( - + diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts index d5ad51ba358391..2958ecd75910f3 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts @@ -9,3 +9,5 @@ export * from './configuration_form'; export * from './document_fields'; export * from './templates_form'; + +export * from './multiple_mappings_warning'; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx new file mode 100644 index 00000000000000..507e4dac262ff0 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiCallOut, EuiLink } from '@elastic/eui'; + +import { documentationService } from '../../../services/documentation'; + +export const MultipleMappingsWarning = () => ( + +

    + + {i18n.translate( + 'xpack.idxMgmt.mappingsEditor.mappingTypesDetectedCallOutDocumentationLink', + { + defaultMessage: 'Consider these alternatives to mapping types.', + } + )} + + ), + }} + /> +

    +
    +); diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx index ba6a121eb7cdbb..732449f382f93c 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx @@ -17,7 +17,13 @@ import { fieldFormatters, FieldConfig, } from '../shared_imports'; -import { AliasOption, DataType, ComboBoxOption } from '../types'; +import { + AliasOption, + DataType, + ComboBoxOption, + ParameterName, + ParameterDefinition, +} from '../types'; import { documentationService } from '../../../services/documentation'; import { INDEX_DEFAULT } from './default_values'; import { TYPE_DEFINITION } from './data_types_definition'; @@ -124,7 +130,7 @@ const analyzerValidations = [ * * As a consequence, if a parameter is *not* declared here, we won't be able to declare it in the Json editor. */ -export const PARAMETERS_DEFINITION = { +export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinition } = { name: { fieldConfig: { label: i18n.translate('xpack.idxMgmt.mappingsEditor.nameFieldLabel', { @@ -537,20 +543,32 @@ export const PARAMETERS_DEFINITION = { }, dynamic: { fieldConfig: { - label: i18n.translate('xpack.idxMgmt.mappingsEditor.dynamicFieldLabel', { - defaultMessage: 'Dynamic', - }), - type: FIELD_TYPES.CHECKBOX, defaultValue: true, }, - schema: t.boolean, + schema: t.union([t.boolean, t.literal('strict')]), }, - enabled: { + dynamic_toggle: { fieldConfig: { - label: i18n.translate('xpack.idxMgmt.mappingsEditor.enabledFieldLabel', { - defaultMessage: 'Enabled', + defaultValue: true, + }, + }, + dynamic_strict: { + fieldConfig: { + defaultValue: false, + label: i18n.translate('xpack.idxMgmt.mappingsEditor.dynamicStrictParameter.fieldTitle', { + defaultMessage: 'Throw an exception when the object contains an unmapped property', }), - type: FIELD_TYPES.CHECKBOX, + helpText: i18n.translate( + 'xpack.idxMgmt.mappingsEditor.dynamicStrictParameter.fieldHelpText', + { + defaultMessage: + 'By default, unmapped properties will be silently ignored when dynamic mapping is disabled. Optionally, you can choose to throw an exception when an object contains an unmapped property.', + } + ), + }, + }, + enabled: { + fieldConfig: { defaultValue: true, }, schema: t.boolean, @@ -663,6 +681,11 @@ export const PARAMETERS_DEFINITION = { }, schema: t.boolean, }, + eager_global_ordinals_join: { + fieldConfig: { + defaultValue: true, + }, + }, index_phrases: { fieldConfig: { defaultValue: false, @@ -894,6 +917,12 @@ export const PARAMETERS_DEFINITION = { }, schema: t.string, }, + relations: { + fieldConfig: { + defaultValue: [] as any, // Needed for FieldParams typing + }, + schema: t.record(t.string, t.union([t.string, t.array(t.string)])), + }, max_shingle_size: { fieldConfig: { type: FIELD_TYPES.SELECT, diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts new file mode 100644 index 00000000000000..3e38ff5991a8c7 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts @@ -0,0 +1,128 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { extractMappingsDefinition } from './extract_mappings_definition'; + +describe('extractMappingsDefinition', () => { + test('should detect that the mappings has multiple types and return null', () => { + const mappings = { + type1: { + properties: { + name1: { + type: 'keyword', + }, + }, + }, + type2: { + properties: { + name2: { + type: 'keyword', + }, + }, + }, + }; + + expect(extractMappingsDefinition(mappings)).toBe(null); + }); + + test('should detect that the mappings has multiple types even when one of the type has not defined any "properties"', () => { + const mappings = { + type1: { + _source: { + excludes: [], + includes: [], + enabled: true, + }, + _routing: { + required: false, + }, + }, + type2: { + properties: { + name2: { + type: 'keyword', + }, + }, + }, + }; + + expect(extractMappingsDefinition(mappings)).toBe(null); + }); + + test('should detect that one of the mapping type is invalid and filter it out', () => { + const mappings = { + type1: { + invalidSetting: { + excludes: [], + includes: [], + enabled: true, + }, + _routing: { + required: false, + }, + }, + type2: { + properties: { + name2: { + type: 'keyword', + }, + }, + }, + }; + + expect(extractMappingsDefinition(mappings)).toBe(mappings.type2); + }); + + test('should detect that the mappings has one type and return its mapping definition', () => { + const mappings = { + myType: { + _source: { + excludes: [], + includes: [], + enabled: true, + }, + _meta: {}, + _routing: { + required: false, + }, + dynamic: true, + properties: { + title: { + type: 'keyword', + }, + }, + }, + }; + + expect(extractMappingsDefinition(mappings)).toBe(mappings.myType); + }); + + test('should detect that the mappings has one type at root level', () => { + const mappings = { + _source: { + excludes: [], + includes: [], + enabled: true, + }, + _meta: {}, + _routing: { + required: false, + }, + dynamic: true, + numeric_detection: false, + date_detection: true, + dynamic_date_formats: ['strict_date_optional_time'], + dynamic_templates: [], + properties: { + title: { + type: 'keyword', + }, + }, + }; + + expect(extractMappingsDefinition(mappings)).toBe(mappings); + }); +}); diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts new file mode 100644 index 00000000000000..eae3c5b15759ca --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { isPlainObject } from 'lodash'; + +import { GenericObject } from '../types'; +import { + validateMappingsConfiguration, + mappingsConfigurationSchemaKeys, +} from './mappings_validator'; + +const ALLOWED_PARAMETERS = [...mappingsConfigurationSchemaKeys, 'dynamic_templates', 'properties']; + +const isMappingDefinition = (obj: GenericObject): boolean => { + const areAllKeysValid = Object.keys(obj).every(key => ALLOWED_PARAMETERS.includes(key)); + + if (!areAllKeysValid) { + return false; + } + + const { properties, dynamic_templates: dynamicTemplates, ...mappingsConfiguration } = obj; + + const { errors } = validateMappingsConfiguration(mappingsConfiguration); + const isConfigurationValid = errors.length === 0; + const isPropertiesValid = properties === undefined || isPlainObject(properties); + const isDynamicTemplatesValid = dynamicTemplates === undefined || Array.isArray(dynamicTemplates); + + // If the configuration, the properties and the dynamic templates are valid + // we can assume that the mapping is declared at root level (no types) + return isConfigurationValid && isPropertiesValid && isDynamicTemplatesValid; +}; + +/** + * 5.x index templates can be created with multiple types. + * e.g. + ``` + const mappings = { + type1: { + properties: { + name1: { + type: 'keyword', + }, + }, + }, + type2: { + properties: { + name2: { + type: 'keyword', + }, + }, + }, + }; + ``` + * A mappings can also be declared under an explicit "_doc" property. + ``` + const mappings = { + _doc: { + _source: { + "enabled": false + }, + properties: { + name1: { + type: 'keyword', + }, + }, + }, + }; + ``` + * This helpers parse the mappings provided an removes any possible mapping "type" declared + * + * @param mappings The mappings object to validate + */ +export const extractMappingsDefinition = (mappings: GenericObject = {}): GenericObject | null => { + if (isMappingDefinition(mappings)) { + // No need to go any further + return mappings; + } + + // At this point there must be one or more type mappings + const typedMappings = Object.values(mappings).reduce((acc: GenericObject[], value) => { + if (isMappingDefinition(value)) { + acc.push(value as GenericObject); + } + return acc; + }, []); + + // If there are no typed mappings found this means that one of the type must did not pass + // the "isMappingDefinition()" validation. + // In theory this should never happen but let's make sure the UI does not try to load an invalid mapping + if (typedMappings.length === 0) { + return null; + } + + // If there's only one mapping type then we can consume it as if the type doesn't exist. + if (typedMappings.length === 1) { + return typedMappings[0]; + } + + // If there's more than one mapping type, then the mappings object isn't usable. + return null; +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts index 1b1c5cc8dc8d48..8cd1bbf0764ab0 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts @@ -13,3 +13,5 @@ export * from './validators'; export * from './mappings_validator'; export * from './search_fields'; + +export * from './extract_mappings_definition'; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts index c8bb7e5b60fb39..f1e6efb06c6492 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { isPlainObject } from 'lodash'; -import { validateMappings, validateProperties, isObject } from './mappings_validator'; +import { validateMappings, validateProperties } from './mappings_validator'; describe('Mappings configuration validator', () => { it('should convert non object to empty object', () => { @@ -12,7 +13,7 @@ describe('Mappings configuration validator', () => { tests.forEach(testValue => { const { value, errors } = validateMappings(testValue as any); - expect(isObject(value)).toBe(true); + expect(isPlainObject(value)).toBe(true); expect(errors).toBe(undefined); }); }); @@ -76,7 +77,7 @@ describe('Properties validator', () => { tests.forEach(testValue => { const { value, errors } = validateProperties(testValue as any); - expect(isObject(value)).toBe(true); + expect(isPlainObject(value)).toBe(true); expect(errors).toEqual([]); }); }); @@ -280,7 +281,7 @@ describe('Properties validator', () => { orientation: 'ccw', boost: 1.5, scaling_factor: 2.5, - dynamic: true, + dynamic: 'strict', // true | false | 'strict' are allowed enabled: true, format: 'strict_date_optional_time', analyzer: 'standard', @@ -310,14 +311,24 @@ describe('Properties validator', () => { dims: 'abc', max_shingle_size: 2, }, + goodField2: { + type: 'object', + dynamic: true, + }, + goodField3: { + type: 'object', + dynamic: false, + }, }; const { value, errors } = validateProperties(properties as any); - expect(Object.keys(value)).toEqual(['wrongField', 'goodField']); + expect(Object.keys(value)).toEqual(['wrongField', 'goodField', 'goodField2', 'goodField3']); expect(value.wrongField).toEqual({ type: 'text' }); // All parameters have been stripped out but the "type". expect(value.goodField).toEqual(properties.goodField); // All parameters are stil there. + expect(value.goodField2).toEqual(properties.goodField2); + expect(value.goodField3).toEqual(properties.goodField3); const allWrongParameters = Object.keys(properties.wrongField).filter(v => v !== 'type'); expect(errors).toEqual( diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts index fff735da2e7585..6ccbfeb50dcf44 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts @@ -3,15 +3,16 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { pick } from 'lodash'; +import { pick, isPlainObject } from 'lodash'; import * as t from 'io-ts'; import { ordString } from 'fp-ts/lib/Ord'; import { toArray } from 'fp-ts/lib/Set'; import { isLeft, isRight } from 'fp-ts/lib/Either'; + import { errorReporter } from './error_reporter'; import { ALL_DATA_TYPES, PARAMETERS_DEFINITION } from '../constants'; import { FieldMeta } from '../types'; -import { getFieldMeta } from '../lib'; +import { getFieldMeta } from './utils'; const ALLOWED_FIELD_PROPERTIES = [ ...Object.keys(PARAMETERS_DEFINITION), @@ -49,8 +50,6 @@ interface GenericObject { [key: string]: any; } -export const isObject = (obj: any) => obj != null && obj.constructor.name === 'Object'; - const validateFieldType = (type: any): boolean => { if (typeof type !== 'string') { return false; @@ -72,7 +71,7 @@ const validateParameter = (parameter: string, value: any): boolean => { } if (parameter === 'properties' || parameter === 'fields') { - return isObject(value); + return isPlainObject(value); } const parameterSchema = (PARAMETERS_DEFINITION as any)[parameter]!.schema; @@ -100,7 +99,7 @@ const stripUnknownOrInvalidParameter = (field: GenericObject): FieldValidatorRes const parseField = (field: any): FieldValidatorResponse & { meta?: FieldMeta } => { // Sanitize the input to make sure we are working with an object - if (!isObject(field)) { + if (!isPlainObject(field)) { return { parametersRemoved: [] }; } // Make sure the field "type" is valid @@ -186,7 +185,7 @@ const parseFields = ( */ export const validateProperties = (properties = {}): PropertiesValidatorResponse => { // Sanitize the input to make sure we are working with an object - if (!isObject(properties)) { + if (!isPlainObject(properties)) { return { value: {}, errors: [] }; } @@ -213,9 +212,9 @@ export const mappingsConfigurationSchema = t.partial({ }), }); -const mappingsConfigurationSchemaKeys = Object.keys(mappingsConfigurationSchema.props); +export const mappingsConfigurationSchemaKeys = Object.keys(mappingsConfigurationSchema.props); -const validateMappingsConfiguration = ( +export const validateMappingsConfiguration = ( mappingsConfiguration: any ): { value: any; errors: MappingsValidationError[] } => { // Set to keep track of invalid configuration parameters. @@ -249,7 +248,7 @@ const validateMappingsConfiguration = ( }; export const validateMappings = (mappings: any = {}): MappingsValidatorResponse => { - if (!isObject(mappings)) { + if (!isPlainObject(mappings)) { return { value: {} }; } diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.tsx index 807bf233b0da0a..5a277073c5f1a3 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.tsx @@ -125,6 +125,7 @@ const getJSXdisplayFromMeta = ( const charIndex = path.lastIndexOf(stringMatch!); const startString = path.substr(0, charIndex); const endString = path.substr(charIndex + stringMatch!.length); + display = ( {startString} @@ -164,7 +165,7 @@ const getSearchMetadata = (searchData: SearchData, fieldData: FieldData): Search .sort((a, b) => b![0].length - a![0].length); if (arrayMatch.length) { - stringMatch = arrayMatch[0]![0].toLowerCase(); + stringMatch = arrayMatch[0]![0]; } } @@ -244,7 +245,7 @@ export const searchFields = (term: string, fields: NormalizedFields['byId']): Se field, metadata: getSearchMetadata(searchData, { name: field.source.name, - path: field.path.join(' > ').toLowerCase(), + path: field.path.join(' > '), type: field.source.type, }), })) diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/serializers.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/serializers.ts index f57f0bb9d87dec..131d886ff05d95 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/serializers.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/serializers.ts @@ -5,6 +5,10 @@ */ import { SerializerFunc } from '../shared_imports'; +import { + PARAMETER_SERIALIZERS, + PARAMETER_DESERIALIZERS, +} from '../components/document_fields/field_parameters'; import { Field, DataType, MainType, SubType } from '../types'; import { INDEX_DEFAULT, MAIN_DATA_TYPE_DEFINITION } from '../constants'; import { getMainTypeFromSubType } from './utils'; @@ -21,6 +25,25 @@ const sanitizeField = (field: Field): Field => {} as any ); +/** + * Run custom parameter serializers on field. + * Each serializer takes the field as single argument and returns it serialized in an immutable way. + * @param field The field we are serializing + */ +const runParametersSerializers = (field: Field): Field => + PARAMETER_SERIALIZERS.reduce((fieldSerialized, serializer) => serializer(fieldSerialized), field); + +/** + * Run custom parameter deserializers on field. + * Each deserializer takes the field as single argument and returns it deserialized in an immutable way. + * @param field The field we are deserializing + */ +const runParametersDeserializers = (field: Field): Field => + PARAMETER_DESERIALIZERS.reduce( + (fieldDeserialized, serializer) => serializer(fieldDeserialized), + field + ); + export const fieldSerializer: SerializerFunc = (field: Field) => { // If a subType is present, use it as type for ES if ({}.hasOwnProperty.call(field, 'subType')) { @@ -31,7 +54,7 @@ export const fieldSerializer: SerializerFunc = (field: Field) => { // Delete temp fields delete (field as any).useSameAnalyzerForSearch; - return sanitizeField(field); + return sanitizeField(runParametersSerializers(field)); }; export const fieldDeserializer: SerializerFunc = (field: Field): Field => { @@ -50,5 +73,5 @@ export const fieldDeserializer: SerializerFunc = (field: Field): Field => (field as any).useSameAnalyzerForSearch = {}.hasOwnProperty.call(field, 'search_analyzer') === false; - return field; + return runParametersDeserializers(field); }; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.ts index 50e4023c8c7426..337554ab5fa5a1 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.ts @@ -79,10 +79,10 @@ export const getFieldConfig = (param: ParameterName, prop?: string): FieldConfig ) { throw new Error(`No field config found for prop "${prop}" on param "${param}" `); } - return (PARAMETERS_DEFINITION[param] as any).props[prop].fieldConfig || {}; + return (PARAMETERS_DEFINITION[param] as any).props[prop]?.fieldConfig || {}; } - return (PARAMETERS_DEFINITION[param] as any).fieldConfig || {}; + return (PARAMETERS_DEFINITION[param] as any)?.fieldConfig || {}; }; /** diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx index e3fdf42d889e97..d79a023386e8d6 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx @@ -4,14 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useMemo, useState } from 'react'; +import React, { useMemo, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiTabs, EuiTab } from '@elastic/eui'; -import { ConfigurationForm, DocumentFields, TemplatesForm } from './components'; +import { + ConfigurationForm, + DocumentFields, + TemplatesForm, + MultipleMappingsWarning, +} from './components'; import { IndexSettings } from './types'; +import { extractMappingsDefinition } from './lib'; import { State } from './reducer'; -import { MappingsState, Props as MappingsStateProps } from './mappings_state'; +import { MappingsState, Props as MappingsStateProps, Types } from './mappings_state'; import { IndexSettingsProvider } from './index_settings_context'; interface Props { @@ -25,7 +31,13 @@ type TabName = 'fields' | 'advanced' | 'templates'; export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSettings }: Props) => { const [selectedTab, selectTab] = useState('fields'); - const parsedDefaultValue = useMemo(() => { + const { parsedDefaultValue, multipleMappingsDeclared } = useMemo(() => { + const mappingsDefinition = extractMappingsDefinition(defaultValue); + + if (mappingsDefinition === null) { + return { multipleMappingsDeclared: true }; + } + const { _source = {}, _meta = {}, @@ -36,9 +48,9 @@ export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSetting dynamic_date_formats, properties = {}, dynamic_templates, - } = defaultValue ?? {}; + } = mappingsDefinition; - return { + const parsed = { configuration: { _source, _meta, @@ -53,8 +65,21 @@ export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSetting dynamic_templates, }, }; + + return { parsedDefaultValue: parsed, multipleMappingsDeclared: false }; }, [defaultValue]); + useEffect(() => { + if (multipleMappingsDeclared) { + // We set the data getter here as the user won't be able to make any changes + onUpdate({ + getData: () => defaultValue! as Types['Mappings'], + validate: () => Promise.resolve(true), + isValid: true, + }); + } + }, [multipleMappingsDeclared]); + const changeTab = async (tab: TabName, state: State) => { if (selectedTab === 'advanced') { // When we navigate away we need to submit the form to validate if there are any errors. @@ -63,7 +88,6 @@ export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSetting if (!isConfigurationFormValid) { /** * Don't navigate away from the tab if there are errors in the form. - * For now there is no need to display a CallOut as the form can never be invalid. */ return; } @@ -79,51 +103,57 @@ export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSetting }; return ( - - - {({ state }) => { - const tabToContentMap = { - fields: , - templates: , - advanced: , - }; - - return ( -
    - - changeTab('fields', state)} - isSelected={selectedTab === 'fields'} - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.fieldsTabLabel', { - defaultMessage: 'Mapped fields', - })} - - changeTab('templates', state)} - isSelected={selectedTab === 'templates'} - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.templatesTabLabel', { - defaultMessage: 'Dynamic templates', - })} - - changeTab('advanced', state)} - isSelected={selectedTab === 'advanced'} - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.advancedTabLabel', { - defaultMessage: 'Advanced options', - })} - - - - - - {tabToContentMap[selectedTab]} -
    - ); - }} -
    -
    +
    + {multipleMappingsDeclared ? ( + + ) : ( + + + {({ state }) => { + const tabToContentMap = { + fields: , + templates: , + advanced: , + }; + + return ( +
    + + changeTab('fields', state)} + isSelected={selectedTab === 'fields'} + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.fieldsTabLabel', { + defaultMessage: 'Mapped fields', + })} + + changeTab('templates', state)} + isSelected={selectedTab === 'templates'} + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.templatesTabLabel', { + defaultMessage: 'Dynamic templates', + })} + + changeTab('advanced', state)} + isSelected={selectedTab === 'advanced'} + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.advancedTabLabel', { + defaultMessage: 'Advanced options', + })} + + + + + + {tabToContentMap[selectedTab]} +
    + ); + }} +
    +
    + )} +
    ); }); diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/reducer.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/reducer.ts index 26d5b8e1edfa58..1e6733b1632d76 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/reducer.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/reducer.ts @@ -174,7 +174,7 @@ const updateAliasesReferences = ( ); } - const targetId = field.source.path!; + const targetId = field.source.path! as string; if (!updatedAliases[targetId]) { updatedAliases[targetId] = []; @@ -420,7 +420,7 @@ export const reducer = (state: State, action: Action): State => { /** * If we delete an alias field, we need to remove its id from the reference Array */ - const targetId = field.source.path; + const targetId = field.source.path as string; updatedFields.aliases = { ...updatedFields.aliases, [targetId]: updatedFields.aliases[targetId].filter(aliasId => aliasId !== id), @@ -455,7 +455,7 @@ export const reducer = (state: State, action: Action): State => { updatedFields.aliases = updateAliasesReferences( newField, updatedFields, - previousField.source.path + previousField.source.path as string ); } @@ -489,9 +489,9 @@ export const reducer = (state: State, action: Action): State => { // We need to remove its reference from our state.aliases map updatedFields.aliases = { ...updatedFields.aliases, - [previousField.source.path]: updatedFields.aliases[previousField.source.path].filter( - aliasId => aliasId !== fieldToEdit - ), + [previousField.source.path as string]: updatedFields.aliases[ + previousField.source.path as string + ].filter(aliasId => aliasId !== fieldToEdit), }; } else { const nextTypeCanHaveAlias = !PARAMETERS_DEFINITION.path.targetTypesNotAllowed.includes( diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/shared_imports.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/shared_imports.ts index 8ac1c2f8c35d1b..e99d8840d57dfe 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/shared_imports.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/shared_imports.ts @@ -16,6 +16,8 @@ export { OnFormUpdateArg, SerializerFunc, UseField, + UseArray, + ArrayItem, useForm, useFormContext, UseMultiFields, @@ -34,6 +36,7 @@ export { SuperSelectField, TextAreaField, TextField, + ComboBoxField, ToggleField, JsonEditorField, } from '../../../../../../../../src/plugins/es_ui_shared/static/forms/components'; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts index b7bf4e6b112d37..dbbffe5a0bd316 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts @@ -19,6 +19,19 @@ export interface DataTypeDefinition { description?: () => ReactNode; } +export interface ParameterDefinition { + title?: string; + description?: JSX.Element | string; + fieldConfig: FieldConfig; + schema?: any; + props?: { [key: string]: ParameterDefinition }; + documentation?: { + main: string; + [key: string]: string; + }; + [key: string]: any; +} + export type MainType = | 'text' | 'keyword' @@ -88,6 +101,8 @@ export type ParameterName = | 'null_value_ip' | 'copy_to' | 'dynamic' + | 'dynamic_toggle' + | 'dynamic_strict' | 'enabled' | 'boost' | 'locale' @@ -99,6 +114,7 @@ export type ParameterName = | 'index_options_flattened' | 'index_options_keyword' | 'eager_global_ordinals' + | 'eager_global_ordinals_join' | 'index_prefixes' | 'index_phrases' | 'norms' @@ -120,6 +136,7 @@ export type ParameterName = | 'path' | 'dims' | 'depth_limit' + | 'relations' | 'max_shingle_size'; export interface Parameter { @@ -142,10 +159,10 @@ interface FieldBasic { } type FieldParams = { - [K in ParameterName]: typeof PARAMETERS_DEFINITION[K]['fieldConfig']['defaultValue']; + [K in ParameterName]: typeof PARAMETERS_DEFINITION[K]['fieldConfig']['defaultValue'] | unknown; }; -export type Field = FieldBasic & FieldParams; +export type Field = FieldBasic & Partial; export interface FieldMeta { childFieldsName: ChildFieldName | undefined; @@ -270,3 +287,7 @@ export interface SearchMetadata { */ stringMatch: string | null; } + +export interface GenericObject { + [key: string]: any; +} diff --git a/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts b/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts index 036388452f8763..9bf0d983df161f 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts +++ b/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts @@ -40,13 +40,17 @@ class DocumentationService { return `${this.kibanaDocsBase}/managing-indices.html`; } - public getTypeDocLink = (type: DataType, uri = 'main'): string | undefined => { + public getTypeDocLink = (type: DataType, docType = 'main'): string | undefined => { const typeDefinition = TYPE_DEFINITION[type]; - if (!typeDefinition || !typeDefinition.documentation || !typeDefinition.documentation[uri]) { + if ( + !typeDefinition || + !typeDefinition.documentation || + !typeDefinition.documentation[docType] + ) { return undefined; } - return `${this.esDocsBase}${typeDefinition.documentation[uri]}`; + return `${this.esDocsBase}${typeDefinition.documentation[docType]}`; }; public getMappingTypesLink() { @@ -177,6 +181,22 @@ class DocumentationService { return `${this.esDocsBase}/index-options.html`; } + public getAlternativeToMappingTypesLink() { + return `${this.esDocsBase}/removal-of-types.html#_alternatives_to_mapping_types`; + } + + public getJoinMultiLevelsPerformanceLink() { + return `${this.esDocsBase}/parent-join.html#_parent_join_and_performance`; + } + + public getDynamicLink() { + return `${this.esDocsBase}/dynamic.html`; + } + + public getEnabledLink() { + return `${this.esDocsBase}/enabled.html`; + } + public getWellKnownTextLink() { return 'http://docs.opengeospatial.org/is/12-063r5/12-063r5.html'; } diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts index ccfd8cd9851ebc..5f667beebd83b0 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts @@ -13,6 +13,9 @@ export const awsEC2: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModels.awsEC2.displayName', { defaultMessage: 'EC2 Instances', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsEC2.singularDisplayName', { + defaultMessage: 'EC2 Instance', + }), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts index f1182a942ff061..02cef192b59efc 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts @@ -13,6 +13,9 @@ export const awsRDS: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModels.awsRDS.displayName', { defaultMessage: 'RDS Databases', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsRDS.singularDisplayName', { + defaultMessage: 'RDS Database', + }), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts index 3bdf319f49c5f8..a786283a100a98 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts @@ -13,6 +13,9 @@ export const awsS3: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModels.awsS3.displayName', { defaultMessage: 'S3 Buckets', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsS3.singularDisplayName', { + defaultMessage: 'S3 Bucket', + }), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts index 1733e995a824f9..21379ebb1e6045 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts @@ -13,6 +13,9 @@ export const awsSQS: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModels.awsSQS.displayName', { defaultMessage: 'SQS Queues', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsSQS.singularDisplayName', { + defaultMessage: 'SQS Queue', + }), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts index 29b3cfe3af1804..c142f600d1d56a 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts @@ -13,6 +13,9 @@ export const container: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModel.container.displayName', { defaultMessage: 'Docker Containers', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModel.container.singularDisplayName', { + defaultMessage: 'Docker Container', + }), requiredModule: 'docker', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts index 364ef0b4c2c918..538af4f5119b42 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts @@ -17,6 +17,9 @@ export const host: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModel.host.displayName', { defaultMessage: 'Hosts', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.host.singularDisplayName', { + defaultMessage: 'Host', + }), requiredModule: 'system', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts index f76a0304e26c04..961e0248c79da9 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts @@ -14,6 +14,9 @@ export const pod: InventoryModel = { displayName: i18n.translate('xpack.infra.inventoryModel.pod.displayName', { defaultMessage: 'Kubernetes Pods', }), + singularDisplayName: i18n.translate('xpack.infra.inventoryModels.pod.singularDisplayName', { + defaultMessage: 'Kubernetes Pod', + }), requiredModule: 'kubernetes', crosslinkSupport: { details: true, diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts index cc2396547edc4b..2f61b16fb3df85 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts @@ -320,6 +320,7 @@ export interface InventoryMetrics { export interface InventoryModel { id: string; displayName: string; + singularDisplayName: string; requiredModule: string; fields: { id: string; diff --git a/x-pack/legacy/plugins/infra/index.ts b/x-pack/legacy/plugins/infra/index.ts index 196950b51be3ab..d9abadcb5125c5 100644 --- a/x-pack/legacy/plugins/infra/index.ts +++ b/x-pack/legacy/plugins/infra/index.ts @@ -18,6 +18,7 @@ import { PluginSetupContract as FeaturesPluginSetup } from '../../../plugins/fea import { SpacesPluginSetup } from '../../../plugins/spaces/server'; import { VisTypeTimeseriesSetup } from '../../../../src/plugins/vis_type_timeseries/server'; import { APMPluginContract } from '../../../plugins/apm/server'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; export const APP_ID = 'infra'; @@ -55,6 +56,7 @@ export function infra(kibana: any) { defaultMessage: 'Metrics', }), url: `/app/${APP_ID}#/infrastructure`, + category: DEFAULT_APP_CATEGORIES.observability, }, { description: i18n.translate('xpack.infra.linkLogsDescription', { @@ -68,6 +70,7 @@ export function infra(kibana: any) { defaultMessage: 'Logs', }), url: `/app/${APP_ID}#/logs`, + category: DEFAULT_APP_CATEGORIES.observability, }, ], mappings: savedObjectMappings, diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx index ad47d17fe3db9c..75d8c5a47d32dd 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx @@ -215,6 +215,15 @@ export class LogMinimap extends React.Component + + {highlightedInterval ? ( ) : null} - - - { .range([0, height]); return ( - + {buckets.map(bucket => ( )}
    - {series.rows.length > 0 ? ( + {metrics.length && series.rows.length > 0 ? ( {metrics.map((metric, id) => ( { const uiCapabilities = useKibana().services.application?.capabilities; const inventoryModel = findInventoryModel(nodeType); + const nodeDetailFrom = currentTime - inventoryModel.metrics.defaultTimeRangeInSeconds * 1000; // Due to the changing nature of the fields between APM and this UI, // We need to have some exceptions until 7.0 & ECS is finalized. Reference // #26620 for the details for these fields. // TODO: This is tech debt, remove it after 7.0 & ECS migration. const apmField = nodeType === 'host' ? 'host.hostname' : inventoryModel.fields.id; - const nodeLogsMenuItem = { - name: i18n.translate('xpack.infra.nodeContextMenu.viewLogsName', { - defaultMessage: 'View logs', + const showDetail = inventoryModel.crosslinkSupport.details; + const showLogsLink = + inventoryModel.crosslinkSupport.logs && node.id && uiCapabilities?.logs?.show; + const showAPMTraceLink = + inventoryModel.crosslinkSupport.apm && uiCapabilities?.apm && uiCapabilities?.apm.show; + const showUptimeLink = + inventoryModel.crosslinkSupport.uptime && (['pod', 'container'].includes(nodeType) || node.ip); + + const inventoryId = useMemo(() => { + if (nodeType === 'host') { + if (node.ip) { + return { label: host.ip, value: node.ip }; + } + } else { + if (options.fields) { + const { id } = findInventoryFields(nodeType, options.fields); + return { + label: {id}, + value: node.id, + }; + } + } + return { label: '', value: '' }; + }, [nodeType, node.ip, node.id, options.fields]); + + const nodeLogsMenuItem: SectionLinkProps = { + label: i18n.translate('xpack.infra.nodeContextMenu.viewLogsName', { + defaultMessage: '{inventoryName} logs', + values: { inventoryName: inventoryModel.singularDisplayName }, }), href: getNodeLogsUrl({ nodeType, @@ -59,12 +91,13 @@ export const NodeContextMenu = ({ time: currentTime, }), 'data-test-subj': 'viewLogsContextMenuItem', + isDisabled: !showLogsLink, }; - const nodeDetailFrom = currentTime - inventoryModel.metrics.defaultTimeRangeInSeconds * 1000; - const nodeDetailMenuItem = { - name: i18n.translate('xpack.infra.nodeContextMenu.viewMetricsName', { - defaultMessage: 'View metrics', + const nodeDetailMenuItem: SectionLinkProps = { + label: i18n.translate('xpack.infra.nodeContextMenu.viewMetricsName', { + defaultMessage: '{inventoryName} metrics', + values: { inventoryName: inventoryModel.singularDisplayName }, }), href: getNodeDetailUrl({ nodeType, @@ -72,54 +105,82 @@ export const NodeContextMenu = ({ from: nodeDetailFrom, to: currentTime, }), + isDisabled: !showDetail, }; - const apmTracesMenuItem = { - name: i18n.translate('xpack.infra.nodeContextMenu.viewAPMTraces', { - defaultMessage: 'View APM traces', + const apmTracesMenuItem: SectionLinkProps = { + label: i18n.translate('xpack.infra.nodeContextMenu.viewAPMTraces', { + defaultMessage: '{inventoryName} APM traces', + values: { inventoryName: inventoryModel.singularDisplayName }, }), href: `../app/apm#/traces?_g=()&kuery=${apmField}:"${node.id}"`, 'data-test-subj': 'viewApmTracesContextMenuItem', + isDisabled: !showAPMTraceLink, }; - const uptimeMenuItem = { - name: i18n.translate('xpack.infra.nodeContextMenu.viewUptimeLink', { - defaultMessage: 'View in Uptime', + const uptimeMenuItem: SectionLinkProps = { + label: i18n.translate('xpack.infra.nodeContextMenu.viewUptimeLink', { + defaultMessage: '{inventoryName} in Uptime', + values: { inventoryName: inventoryModel.singularDisplayName }, }), href: createUptimeLink(options, nodeType, node), + isDisabled: !showUptimeLink, }; - const showDetail = inventoryModel.crosslinkSupport.details; - const showLogsLink = - inventoryModel.crosslinkSupport.logs && node.id && uiCapabilities?.logs?.show; - const showAPMTraceLink = - inventoryModel.crosslinkSupport.apm && uiCapabilities?.apm && uiCapabilities?.apm.show; - const showUptimeLink = - inventoryModel.crosslinkSupport.uptime && (['pod', 'container'].includes(nodeType) || node.ip); - - const items = [ - ...(showLogsLink ? [nodeLogsMenuItem] : []), - ...(showDetail ? [nodeDetailMenuItem] : []), - ...(showAPMTraceLink ? [apmTracesMenuItem] : []), - ...(showUptimeLink ? [uptimeMenuItem] : []), - ]; - const panels: EuiContextMenuPanelDescriptor[] = [{ id: 0, title: '', items }]; - - // If there is nothing to show then we need to return the child as is - if (items.length === 0) { - return <>{children}; - } - return ( - - - +
    +
    + + + + {inventoryId.label && ( + +
    + +
    +
    + )} + + + + + + +
    +
    + ); }; diff --git a/x-pack/legacy/plugins/infra/public/pages/infrastructure/snapshot/index.tsx b/x-pack/legacy/plugins/infra/public/pages/infrastructure/snapshot/index.tsx index b9651763e43c06..27d276a50c30d0 100644 --- a/x-pack/legacy/plugins/infra/public/pages/infrastructure/snapshot/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/infrastructure/snapshot/index.tsx @@ -6,8 +6,9 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; - +import { identity } from 'fp-ts/lib/function'; import React, { useContext } from 'react'; + import { SnapshotPageContent } from './page_content'; import { SnapshotToolbar } from './toolbar'; @@ -38,10 +39,11 @@ export const SnapshotPage = () => { loadSource, metricIndicesExist, } = useContext(Source.Context); - const basePath = useKibana().services.http?.basePath || ''; useTrackPageview({ app: 'infra_metrics', path: 'inventory' }); useTrackPageview({ app: 'infra_metrics', path: 'inventory', delay: 15000 }); + const prependBasePath = useKibana().services.http?.basePath.prepend ?? identity; + return ( { { - const basePath = useKibana().services.http?.basePath || ''; - const uiCapabilities = useKibana().services.application?.capabilities; + const { + services: { application, http }, + } = useKibana<{}>(); + + const canConfigureSource = application?.capabilities?.logs?.configureSource ? true : false; + const prependBasePath = http?.basePath.prepend ?? identity; + return ( { { })} - {uiCapabilities?.logs?.configureSource ? ( + {canConfigureSource ? ( = ({ nodeName }) => { - const basePath = useKibana().services.http?.basePath || ''; + const prependBasePath = useKibana().services.http?.basePath.prepend ?? identity; + return ( = diff --git a/x-pack/legacy/plugins/infra/server/features.ts b/x-pack/legacy/plugins/infra/server/features.ts index fc20813c777b69..02658002694d27 100644 --- a/x-pack/legacy/plugins/infra/server/features.ts +++ b/x-pack/legacy/plugins/infra/server/features.ts @@ -9,9 +9,9 @@ import { i18n } from '@kbn/i18n'; export const METRICS_FEATURE = { id: 'infrastructure', name: i18n.translate('xpack.infra.featureRegistry.linkInfrastructureTitle', { - defaultMessage: 'Infrastructure', + defaultMessage: 'Metrics', }), - icon: 'infraApp', + icon: 'metricsApp', navLinkId: 'infra:home', app: ['infra', 'kibana'], catalogue: ['infraops'], @@ -40,7 +40,7 @@ export const LOGS_FEATURE = { name: i18n.translate('xpack.infra.featureRegistry.linkLogsTitle', { defaultMessage: 'Logs', }), - icon: 'loggingApp', + icon: 'logsApp', navLinkId: 'infra:logs', app: ['infra', 'kibana'], catalogue: ['infralogging'], diff --git a/x-pack/legacy/plugins/infra/yarn.lock b/x-pack/legacy/plugins/infra/yarn.lock new file mode 120000 index 00000000000000..4b16253de2abe6 --- /dev/null +++ b/x-pack/legacy/plugins/infra/yarn.lock @@ -0,0 +1 @@ +../../../../yarn.lock \ No newline at end of file diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx index 794128832461ba..80a7ceb61c324c 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx @@ -12,7 +12,12 @@ import { EditorFrameInstance } from '../types'; import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; import { Document, SavedObjectStore } from '../persistence'; import { mount } from 'enzyme'; -import { esFilters, IFieldType, IIndexPattern } from '../../../../../../src/plugins/data/public'; +import { + esFilters, + FilterManager, + IFieldType, + IIndexPattern, +} from '../../../../../../src/plugins/data/public'; import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; const dataStartMock = dataPluginMock.createStartContract(); @@ -60,6 +65,10 @@ function createMockFilterManager() { subscriber(); }, getFilters: () => filters, + getGlobalFilters: () => { + // @ts-ignore + return filters.filter(esFilters.isFilterPinned); + }, removeAll: () => { filters = []; subscriber(); @@ -821,7 +830,7 @@ describe('Lens App', () => { ); }); - it('clears all existing filters when the active saved query is cleared', () => { + it('clears all existing unpinned filters when the active saved query is cleared', () => { const args = makeDefaultArgs(); args.editorFrame = frame; @@ -834,8 +843,13 @@ describe('Lens App', () => { const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern; const field = ({ name: 'myfield' } as unknown) as IFieldType; + const pinnedField = ({ name: 'pinnedField' } as unknown) as IFieldType; - args.data.query.filterManager.setFilters([esFilters.buildExistsFilter(field, indexPattern)]); + const unpinned = esFilters.buildExistsFilter(field, indexPattern); + const pinned = esFilters.buildExistsFilter(pinnedField, indexPattern); + FilterManager.setFiltersStore([pinned], esFilters.FilterStateStore.GLOBAL_STATE); + + args.data.query.filterManager.setFilters([pinned, unpinned]); instance.update(); instance.find(TopNavMenu).prop('onClearSavedQuery')!(); @@ -844,7 +858,7 @@ describe('Lens App', () => { expect(frame.mount).toHaveBeenLastCalledWith( expect.any(Element), expect.objectContaining({ - filters: [], + filters: [pinned], }) ); }); diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx index f33cd41f46a115..35e45af6a3d689 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx @@ -239,7 +239,9 @@ export function App({ setState(s => ({ ...s, savedQuery })); }} onSavedQueryUpdated={savedQuery => { - data.query.filterManager.setFilters(savedQuery.attributes.filters || state.filters); + const savedQueryFilters = savedQuery.attributes.filters || []; + const globalFilters = data.query.filterManager.getGlobalFilters(); + data.query.filterManager.setFilters([...globalFilters, ...savedQueryFilters]); setState(s => ({ ...s, savedQuery: { ...savedQuery }, // Shallow query for reference issues @@ -252,11 +254,11 @@ export function App({ })); }} onClearSavedQuery={() => { - data.query.filterManager.removeAll(); + data.query.filterManager.setFilters(data.query.filterManager.getGlobalFilters()); setState(s => ({ ...s, savedQuery: undefined, - filters: [], + filters: data.query.filterManager.getGlobalFilters(), query: { query: '', language: diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx index b04bd3a4e9be9d..e8a23b8e053c29 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx @@ -278,8 +278,8 @@ describe('IndexPattern Data Panel', () => { function testProps() { const setState = jest.fn(); - core.http.get.mockImplementation(async (url: string) => { - const parts = url.split('/'); + core.http.get.mockImplementation(async ({ path }) => { + const parts = path.split('/'); const indexPatternTitle = parts[parts.length - 1]; return { indexPatternTitle: `${indexPatternTitle}_testtitle`, @@ -397,7 +397,8 @@ describe('IndexPattern Data Panel', () => { expect(setState).toHaveBeenCalledTimes(2); expect(core.http.get).toHaveBeenCalledTimes(2); - expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/a', { + expect(core.http.get).toHaveBeenCalledWith({ + path: '/api/lens/existing_fields/a', query: { fromDate: '2019-01-01', toDate: '2020-01-01', @@ -405,7 +406,8 @@ describe('IndexPattern Data Panel', () => { }, }); - expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/a', { + expect(core.http.get).toHaveBeenCalledWith({ + path: '/api/lens/existing_fields/a', query: { fromDate: '2019-01-01', toDate: '2020-01-02', @@ -436,7 +438,8 @@ describe('IndexPattern Data Panel', () => { expect(setState).toHaveBeenCalledTimes(2); - expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/a', { + expect(core.http.get).toHaveBeenCalledWith({ + path: '/api/lens/existing_fields/a', query: { fromDate: '2019-01-01', toDate: '2020-01-01', @@ -444,7 +447,8 @@ describe('IndexPattern Data Panel', () => { }, }); - expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/b', { + expect(core.http.get).toHaveBeenCalledWith({ + path: '/api/lens/existing_fields/b', query: { fromDate: '2019-01-01', toDate: '2020-01-01', @@ -484,13 +488,13 @@ describe('IndexPattern Data Panel', () => { let overlapCount = 0; const props = testProps(); - core.http.get.mockImplementation((url: string) => { + core.http.get.mockImplementation(({ path }) => { if (queryCount) { ++overlapCount; } ++queryCount; - const parts = url.split('/'); + const parts = path.split('/'); const indexPatternTitle = parts[parts.length - 1]; const result = Promise.resolve({ indexPatternTitle, diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts index 6bea13c32830fb..f8961c30d14ee2 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts @@ -537,8 +537,8 @@ describe('loader', () => { describe('syncExistingFields', () => { it('should call once for each index pattern', async () => { const setState = jest.fn(); - const fetchJson = jest.fn(async (url: string) => { - const indexPatternTitle = _.last(url.split('/')); + const fetchJson = jest.fn(({ path }: { path: string }) => { + const indexPatternTitle = _.last(path.split('/')); return { indexPatternTitle, existingFieldNames: ['field_1', 'field_2'].map( diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts index c196cb886e575b..c9473c18698685 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts @@ -21,6 +21,7 @@ import { updateLayerIndexPattern } from './state_helpers'; import { DateRange, ExistingFields } from '../../common/types'; import { BASE_API_URL } from '../../common'; import { documentField } from './document_field'; +import { isNestedField, IFieldType } from '../../../../../../src/plugins/data/public'; interface SavedIndexPatternAttributes extends SavedObjectAttributes { title: string; @@ -234,7 +235,8 @@ export async function syncExistingFields({ query.timeFieldName = pattern.timeFieldName; } - return fetchJson(`${BASE_API_URL}/existing_fields/${pattern.id}`, { + return fetchJson({ + path: `${BASE_API_URL}/existing_fields/${pattern.id}`, query, }) as Promise; }) @@ -270,9 +272,9 @@ function fromSavedObject( id, type, title: attributes.title, - fields: (JSON.parse(attributes.fields) as IndexPatternField[]) - .filter(({ aggregatable, scripted }) => !!aggregatable || !!scripted) - .concat(documentField), + fields: (JSON.parse(attributes.fields) as IFieldType[]) + .filter(field => !isNestedField(field) && (!!field.aggregatable || !!field.scripted)) + .concat(documentField) as IndexPatternField[], typeMeta: attributes.typeMeta ? (JSON.parse(attributes.typeMeta) as SavedRestrictionsInfo) : undefined, diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx index 9220c3ec75fad6..a9a48c46f5bd08 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx +++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx @@ -9,7 +9,7 @@ import { LensMultiTable } from '../types'; import React from 'react'; import { shallow } from 'enzyme'; import { MetricConfig } from './types'; -import { FieldFormat } from '../../../../../../src/plugins/data/public'; +import { fieldFormats } from '../../../../../../src/plugins/data/public'; function sampleArgs() { const data: LensMultiTable = { @@ -54,8 +54,11 @@ describe('metric_expression', () => { test('it renders the title and value', () => { const { data, args } = sampleArgs(); - expect(shallow( x as FieldFormat} />)) - .toMatchInlineSnapshot(` + expect( + shallow( + x as fieldFormats.FieldFormat} /> + ) + ).toMatchInlineSnapshot(` { x as FieldFormat} + formatFactory={x => x as fieldFormats.FieldFormat} /> ) ).toMatchInlineSnapshot(` diff --git a/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts b/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts index fbbcf9973431b8..30ded3572cae70 100644 --- a/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts +++ b/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts @@ -226,17 +226,15 @@ async function fetchIndexPatternStats({ match_all: {}, }; } - const viableFields = fields.filter( - f => !f.isScript && !f.isAlias && !metaFields.includes(f.name) - ); const scriptedFields = fields.filter(f => f.isScript); const result = await client.callAsCurrentUser('search', { index, body: { size: SAMPLE_SIZE, - _source: viableFields.map(f => f.name), query, + // _source is required because we are also providing script fields. + _source: '*', script_fields: scriptedFields.reduce((acc, field) => { acc[field.name] = { script: { diff --git a/x-pack/legacy/plugins/license_management/public/np_ready/application/app.js b/x-pack/legacy/plugins/license_management/public/np_ready/application/app.js index 7122e7269732a2..7c497518b9df50 100644 --- a/x-pack/legacy/plugins/license_management/public/np_ready/application/app.js +++ b/x-pack/legacy/plugins/license_management/public/np_ready/application/app.js @@ -8,7 +8,7 @@ import React, { Component } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { LicenseDashboard, UploadLicense } from './sections'; import { Switch, Route } from 'react-router-dom'; -import { APP_PERMISSION } from '../../../common/constants'; +import { APP_PERMISSION, BASE_PATH } from '../../../common/constants'; import { EuiPageBody, EuiEmptyPrompt, EuiText, EuiLoadingSpinner, EuiCallOut } from '@elastic/eui'; export class App extends Component { @@ -88,10 +88,8 @@ export class App extends Component { return ( - - - {/* Match all */} - + + ); diff --git a/x-pack/legacy/plugins/license_management/public/np_ready/application/boot.tsx b/x-pack/legacy/plugins/license_management/public/np_ready/application/boot.tsx index d0bf5deacfac10..2780b54230eba3 100644 --- a/x-pack/legacy/plugins/license_management/public/np_ready/application/boot.tsx +++ b/x-pack/legacy/plugins/license_management/public/np_ready/application/boot.tsx @@ -63,7 +63,7 @@ export const boot = (deps: AppDependencies) => { render( - + diff --git a/x-pack/legacy/plugins/license_management/public/np_ready/application/sections/license_dashboard/license_dashboard.js b/x-pack/legacy/plugins/license_management/public/np_ready/application/sections/license_dashboard/license_dashboard.js index 3dc44796fd0ef0..e14d392fe6706e 100644 --- a/x-pack/legacy/plugins/license_management/public/np_ready/application/sections/license_dashboard/license_dashboard.js +++ b/x-pack/legacy/plugins/license_management/public/np_ready/application/sections/license_dashboard/license_dashboard.js @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; - +import React, { useEffect } from 'react'; import { LicenseStatus } from './license_status'; import { RevertToBasic } from './revert_to_basic'; import { StartTrial } from './start_trial'; @@ -14,7 +13,10 @@ import { RequestTrialExtension } from './request_trial_extension'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; export const LicenseDashboard = ({ setBreadcrumb } = { setBreadcrumb: () => {} }) => { - setBreadcrumb('dashboard'); + useEffect(() => { + setBreadcrumb('dashboard'); + }); + return (
    diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js index d38a23560fa9f7..4f679905fc352a 100644 --- a/x-pack/legacy/plugins/maps/index.js +++ b/x-pack/legacy/plugins/maps/index.js @@ -4,15 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ +import _ from 'lodash'; +import mappings from './mappings.json'; import { i18n } from '@kbn/i18n'; import { resolve } from 'path'; -import mappings from './mappings.json'; import { migrations } from './migrations'; import { initTelemetryCollection } from './server/maps_telemetry'; import { getAppTitle } from './common/i18n_getters'; -import _ from 'lodash'; import { MapPlugin } from './server/plugin'; import { APP_ID, APP_ICON, createMapPath, MAP_SAVED_OBJECT_TYPE } from './common/constants'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; export function maps(kibana) { return new kibana.Plugin({ @@ -29,6 +30,7 @@ export function maps(kibana) { main: 'plugins/maps/legacy', icon: 'plugins/maps/icon.svg', euiIconType: APP_ICON, + category: DEFAULT_APP_CATEGORIES.analyze, }, injectDefaultVars(server) { const serverConfig = server.config(); diff --git a/x-pack/legacy/plugins/maps/public/actions/map_actions.js b/x-pack/legacy/plugins/maps/public/actions/map_actions.js index f05b7eba9e7e01..59b54c2434d171 100644 --- a/x-pack/legacy/plugins/maps/public/actions/map_actions.js +++ b/x-pack/legacy/plugins/maps/public/actions/map_actions.js @@ -753,9 +753,9 @@ export function clearMissingStyleProperties(layerId) { return; } - const ordinalFields = await targetLayer.getOrdinalFields(); + const nextFields = await targetLayer.getFields(); //take into account all fields, since labels can be driven by any field (source or join) const { hasChanges, nextStyleDescriptor } = style.getDescriptorWithMissingStylePropsRemoved( - ordinalFields + nextFields ); if (hasChanges) { dispatch(updateLayerStyle(layerId, nextStyleDescriptor)); diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 75971d5dfe2a84..ece775f5a7e25a 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -153,7 +153,7 @@ app.controller( delete $scope.savedQuery; delete $state.savedQuery; onQueryChange({ - filters: [], + filters: filterManager.getGlobalFilters(), query: { query: '', language: localStorage.get('kibana.userQueryLanguage'), @@ -162,6 +162,10 @@ app.controller( }; function updateStateFromSavedQuery(savedQuery) { + const savedQueryFilters = savedQuery.attributes.filters || []; + const globalFilters = filterManager.getGlobalFilters(); + const allFilters = [...savedQueryFilters, ...globalFilters]; + if (savedQuery.attributes.timefilter) { if (savedQuery.attributes.timefilter.refreshInterval) { $scope.onRefreshChange({ @@ -170,13 +174,13 @@ app.controller( }); } onQueryChange({ - filters: savedQuery.attributes.filters || [], + filters: allFilters, query: savedQuery.attributes.query, time: savedQuery.attributes.timefilter, }); } else { onQueryChange({ - filters: savedQuery.attributes.filters || [], + filters: allFilters, query: savedQuery.attributes.query, }); } @@ -367,7 +371,9 @@ app.controller( if (prevIndexPatternIds !== nextIndexPatternIds) { return; } - $scope.indexPatterns = indexPatterns; + $scope.$evalAsync(() => { + $scope.indexPatterns = indexPatterns; + }); } $scope.isFullScreen = false; diff --git a/x-pack/legacy/plugins/maps/public/components/metric_editor.js b/x-pack/legacy/plugins/maps/public/components/metric_editor.js index f6f5b23f145967..e60c2ac0dd7ab5 100644 --- a/x-pack/legacy/plugins/maps/public/components/metric_editor.js +++ b/x-pack/legacy/plugins/maps/public/components/metric_editor.js @@ -14,12 +14,41 @@ import { MetricSelect, METRIC_AGGREGATION_VALUES } from './metric_select'; import { SingleFieldSelect } from './single_field_select'; import { METRIC_TYPE } from '../../common/constants'; +function filterFieldsForAgg(fields, aggType) { + if (!fields) { + return []; + } + + if (aggType === METRIC_TYPE.UNIQUE_COUNT) { + return fields.filter(field => { + return field.aggregatable; + }); + } + + return fields.filter(field => { + return field.aggregatable && field.type === 'number'; + }); +} + export function MetricEditor({ fields, metricsFilter, metric, onChange, removeButton }) { const onAggChange = metricAggregationType => { - onChange({ + const newMetricProps = { ...metric, type: metricAggregationType, - }); + }; + + // unset field when new agg type does not support currently selected field. + if (metric.field && metricAggregationType !== METRIC_TYPE.COUNT) { + const fieldsForNewAggType = filterFieldsForAgg(fields, metricAggregationType); + const found = fieldsForNewAggType.find(field => { + return field.name === metric.field; + }); + if (!found) { + newMetricProps.field = undefined; + } + } + + onChange(newMetricProps); }; const onFieldChange = fieldName => { onChange({ @@ -36,12 +65,6 @@ export function MetricEditor({ fields, metricsFilter, metric, onChange, removeBu let fieldSelect; if (metric.type && metric.type !== METRIC_TYPE.COUNT) { - const filterField = - metric.type !== METRIC_TYPE.UNIQUE_COUNT - ? field => { - return field.type === 'number'; - } - : undefined; fieldSelect = ( diff --git a/x-pack/legacy/plugins/maps/public/connected_components/gis_map/view.js b/x-pack/legacy/plugins/maps/public/connected_components/gis_map/view.js index 64342d6b4b51d6..2430ca6503f848 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/gis_map/view.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/gis_map/view.js @@ -15,6 +15,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiCallOut } from '@elastic/eui'; import { ExitFullScreenButton } from 'ui/exit_full_screen'; import { getIndexPatternsFromIds } from '../../index_pattern_util'; import { ES_GEO_FIELD_TYPE } from '../../../common/constants'; +import { isNestedField } from '../../../../../../../src/plugins/data/public'; import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; @@ -80,8 +81,9 @@ export class GisMap extends Component { indexPatterns.forEach(indexPattern => { indexPattern.fields.forEach(field => { if ( - field.type === ES_GEO_FIELD_TYPE.GEO_POINT || - field.type === ES_GEO_FIELD_TYPE.GEO_SHAPE + !isNestedField(field) && + (field.type === ES_GEO_FIELD_TYPE.GEO_POINT || + field.type === ES_GEO_FIELD_TYPE.GEO_SHAPE) ) { geoFields.push({ geoFieldName: field.name, diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/join.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/join.js index f5738856bd8dba..554164bf0e8c4b 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/join.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/join.js @@ -13,6 +13,7 @@ import { MetricsExpression } from './metrics_expression'; import { WhereExpression } from './where_expression'; import { GlobalFilterCheckbox } from '../../../../components/global_filter_checkbox'; +import { isNestedField } from '../../../../../../../../../src/plugins/data/public'; import { indexPatternService } from '../../../../kibana_services'; const getIndexPatternId = props => { @@ -88,7 +89,7 @@ export class Join extends Component { } this.setState({ - rightFields: indexPattern.fields, + rightFields: indexPattern.fields.filter(field => !isNestedField(field)), indexPattern, }); } diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/join_expression.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/join_expression.js index b53a0e737fc3d4..76827e71df9ec8 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/join_expression.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/join_editor/resources/join_expression.js @@ -23,6 +23,7 @@ import { getTermsFields } from '../../../../index_pattern_util'; import { indexPatternService } from '../../../../kibana_services'; import { npStart } from 'ui/new_platform'; +import { isNestedField } from '../../../../../../../../../src/plugins/data/public'; const { IndexPatternSelect } = npStart.plugins.data.ui; export class JoinExpression extends Component { @@ -134,7 +135,7 @@ export class JoinExpression extends Component { } const filterStringOrNumberFields = field => { - return field.type === 'string' || field.type === 'number'; + return (field.type === 'string' && !isNestedField(field)) || field.type === 'number'; }; return ( diff --git a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/__snapshots__/view.test.js.snap b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/__snapshots__/view.test.js.snap index eb30a5c33496ee..560ebad89c50ea 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/__snapshots__/view.test.js.snap +++ b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/__snapshots__/view.test.js.snap @@ -65,6 +65,7 @@ exports[`LayerControl is rendered 1`] = ` data-test-subj="addLayerButton" fill={true} fullWidth={true} + isDisabled={true} onClick={[Function]} > { + showAddLayerWizard: async () => { + await dispatch(setSelectedLayer(null)); dispatch(updateFlyout(FLYOUT_STATE.ADD_LAYER_WIZARD)); }, closeLayerTOC: () => { diff --git a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/view.js b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/view.js index 03b6899824e534..537a676287042f 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/view.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/view.js @@ -57,6 +57,7 @@ export function LayerControl({ closeLayerTOC, openLayerTOC, layerList, + isAddButtonActive, }) { if (!isLayerTOCOpen) { const hasErrors = layerList.some(layer => { @@ -85,6 +86,7 @@ export function LayerControl({ { - return field.aggregatable && ['number', 'boolean', 'date', 'ip', 'string'].includes(field.type); + return ( + field.aggregatable && + !isNestedField(field) && + ['number', 'boolean', 'date', 'ip', 'string'].includes(field.type) + ); }); } @@ -29,6 +34,6 @@ export function getSourceFields(fields) { return fields.filter(field => { // Multi fields are not stored in _source and only exist in index. const isMultiField = field.subType && field.subType.multi; - return !isMultiField; + return !isMultiField && !isNestedField(field); }); } diff --git a/x-pack/legacy/plugins/maps/public/kibana_services.js b/x-pack/legacy/plugins/maps/public/kibana_services.js index 1ec7565df6f26f..dadae7a3fdca93 100644 --- a/x-pack/legacy/plugins/maps/public/kibana_services.js +++ b/x-pack/legacy/plugins/maps/public/kibana_services.js @@ -7,12 +7,12 @@ import { getRequestInspectorStats, getResponseInspectorStats, -} from '../../../../../src/legacy/ui/public/courier'; +} from '../../../../../src/legacy/core_plugins/data/public'; import { esFilters } from '../../../../../src/plugins/data/public'; import { npStart } from 'ui/new_platform'; export const SPATIAL_FILTER_TYPE = esFilters.FILTERS.SPATIAL_FILTER; -export { SearchSource } from '../../../../../src/legacy/ui/public/courier'; +export { SearchSource } from '../../../../../src/plugins/data/public'; export const indexPatternService = npStart.plugins.data.indexPatterns; let licenseId; diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js b/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js index f9baf180dfe5ce..76bcb8da552d1c 100644 --- a/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js +++ b/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js @@ -7,13 +7,15 @@ import { AbstractField } from './field'; import { ESTooltipProperty } from '../tooltips/es_tooltip_property'; import { COLOR_PALETTE_MAX_SIZE } from '../../../common/constants'; +import { isNestedField } from '../../../../../../../src/plugins/data/public'; export class ESDocField extends AbstractField { static type = 'ES_DOC'; async _getField() { const indexPattern = await this._source.getIndexPattern(); - return indexPattern.fields.getByName(this._fieldName); + const field = indexPattern.fields.getByName(this._fieldName); + return isNestedField(field) ? undefined : field; } async createTooltipProperty(value) { diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index 09475e638de554..b76f1ebce15d21 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -340,10 +340,6 @@ export class AbstractLayer { return []; } - async getOrdinalFields() { - return []; - } - async getCategoricalFields() { return []; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js index bf679e766470c5..c32b857b491712 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js @@ -16,6 +16,7 @@ import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiComboBox, EuiSpacer } from '@elastic/eui'; import { ES_GEO_FIELD_TYPE } from '../../../../common/constants'; +import { isNestedField } from '../../../../../../../../src/plugins/data/public'; import { npStart } from 'ui/new_platform'; const { IndexPatternSelect } = npStart.plugins.data.ui; @@ -115,7 +116,9 @@ export class CreateSourceEditor extends Component { }); //make default selection - const geoFields = indexPattern.fields.filter(filterGeoField); + const geoFields = indexPattern.fields + .filter(field => !isNestedField(field)) + .filter(filterGeoField); if (geoFields[0]) { this._onGeoFieldSelect(geoFields[0].name); } @@ -171,7 +174,11 @@ export class CreateSourceEditor extends Component { value={this.state.geoField} onChange={this._onGeoFieldSelect} filterField={filterGeoField} - fields={this.state.indexPattern ? this.state.indexPattern.fields : undefined} + fields={ + this.state.indexPattern + ? this.state.indexPattern.fields.filter(field => !isNestedField(field)) + : undefined + } /> ); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index 8c394e71b3a78f..6adb5dd568e23b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -24,7 +24,12 @@ import { RENDER_AS } from './render_as'; import { CreateSourceEditor } from './create_source_editor'; import { UpdateSourceEditor } from './update_source_editor'; import { GRID_RESOLUTION } from '../../grid_resolution'; -import { SOURCE_DATA_ID_ORIGIN, ES_GEO_GRID, COUNT_PROP_NAME } from '../../../../common/constants'; +import { + SOURCE_DATA_ID_ORIGIN, + ES_GEO_GRID, + COUNT_PROP_NAME, + COLOR_MAP_TYPE, +} from '../../../../common/constants'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { AbstractESAggSource } from '../es_agg_source'; @@ -251,6 +256,7 @@ export class ESGeoGridSource extends AbstractESAggSource { origin: SOURCE_DATA_ID_ORIGIN, }, color: COLOR_GRADIENTS[0].value, + type: COLOR_MAP_TYPE.ORDINAL, }, }, [VECTOR_STYLES.LINE_COLOR]: { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js index 6faed55f24c343..0d9234acd91500 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js @@ -14,6 +14,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { isMetricCountable } from '../../util/is_metric_countable'; +import { isNestedField } from '../../../../../../../../src/plugins/data/public'; export class UpdateSourceEditor extends Component { state = { @@ -51,7 +52,7 @@ export class UpdateSourceEditor extends Component { return; } - this.setState({ fields: indexPattern.fields }); + this.setState({ fields: indexPattern.fields.filter(field => !isNestedField(field)) }); } _onMetricsChange = metrics => { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js index 6180862d01bba6..85d63c9da8a311 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js @@ -15,6 +15,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFormRow, EuiCallOut } from '@elastic/eui'; import { ES_GEO_FIELD_TYPE } from '../../../../common/constants'; +import { isNestedField } from '../../../../../../../../src/plugins/data/public'; import { npStart } from 'ui/new_platform'; const { IndexPatternSelect } = npStart.plugins.data.ui; @@ -91,7 +92,9 @@ export class CreateSourceEditor extends Component { return; } - const geoFields = indexPattern.fields.filter(filterGeoField); + const geoFields = indexPattern.fields + .filter(field => !isNestedField(field)) + .filter(filterGeoField); this.setState({ isLoadingIndexPattern: false, @@ -163,7 +166,11 @@ export class CreateSourceEditor extends Component { value={this.state.destGeoField} onChange={this._onDestGeoSelect} filterField={filterGeoField} - fields={this.state.indexPattern ? this.state.indexPattern.fields : undefined} + fields={ + this.state.indexPattern + ? this.state.indexPattern.fields.filter(field => !isNestedField(field)) + : undefined + } /> diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js index dfc9fca96dd759..e6faf4146435d9 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js @@ -25,6 +25,7 @@ import { AggConfigs } from 'ui/agg_types'; import { AbstractESAggSource } from '../es_agg_source'; import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property'; import { COLOR_GRADIENTS } from '../../styles/color_utils'; +import { isNestedField } from '../../../../../../../../src/plugins/data/public'; const MAX_GEOTILE_LEVEL = 29; @@ -228,7 +229,8 @@ export class ESPewPewSource extends AbstractESAggSource { async _getGeoField() { const indexPattern = await this.getIndexPattern(); - const geoField = indexPattern.fields.getByName(this._descriptor.destGeoField); + const field = indexPattern.fields.getByName(this._descriptor.destGeoField); + const geoField = isNestedField(field) ? undefined : field; if (!geoField) { throw new Error( i18n.translate('xpack.maps.source.esSource.noGeoFieldErrorMessage', { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/update_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/update_source_editor.js index 028bb3ad6c7f21..6e2583bf85bb88 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/update_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/update_source_editor.js @@ -11,6 +11,7 @@ import { indexPatternService } from '../../../kibana_services'; import { i18n } from '@kbn/i18n'; import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { isNestedField } from '../../../../../../../../src/plugins/data/public'; export class UpdateSourceEditor extends Component { state = { @@ -48,7 +49,7 @@ export class UpdateSourceEditor extends Component { return; } - this.setState({ fields: indexPattern.fields }); + this.setState({ fields: indexPattern.fields.filter(field => !isNestedField(field)) }); } _onMetricsChange = metrics => { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/create_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/create_source_editor.js index 28045eeb5e9b52..69e4c09eed1180 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/create_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/create_source_editor.js @@ -21,6 +21,7 @@ import { DEFAULT_MAX_RESULT_WINDOW, } from '../../../../common/constants'; import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; +import { isNestedField } from '../../../../../../../../src/plugins/data/public'; import { npStart } from 'ui/new_platform'; const { IndexPatternSelect } = npStart.plugins.data.ui; @@ -124,7 +125,9 @@ export class CreateSourceEditor extends Component { }); //make default selection - const geoFields = indexPattern.fields.filter(filterGeoField); + const geoFields = indexPattern.fields + .filter(field => !isNestedField(field)) + .filter(filterGeoField); if (geoFields[0]) { this.onGeoFieldSelect(geoFields[0].name); } @@ -178,7 +181,11 @@ export class CreateSourceEditor extends Component { value={this.state.geoField} onChange={this.onGeoFieldSelect} filterField={filterGeoField} - fields={this.state.indexPattern ? this.state.indexPattern.fields : undefined} + fields={ + this.state.indexPattern + ? this.state.indexPattern.fields.filter(field => !isNestedField(field)) + : undefined + } /> ); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js index 4503856829ef25..fdebbe4c819110 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js @@ -26,6 +26,7 @@ import { DEFAULT_MAX_INNER_RESULT_WINDOW, SORT_ORDER } from '../../../../common/ import { ESDocField } from '../../fields/es_doc_field'; import { FormattedMessage } from '@kbn/i18n/react'; import { loadIndexSettings } from './load_index_settings'; +import { isNestedField } from '../../../../../../../../src/plugins/data/public'; export class UpdateSourceEditor extends Component { static propTypes = { @@ -103,7 +104,7 @@ export class UpdateSourceEditor extends Component { this.setState({ sourceFields: sourceFields, termFields: getTermsFields(indexPattern.fields), //todo change term fields to use fields - sortFields: indexPattern.fields.filter(field => field.sortable), //todo change sort fields to use fields + sortFields: indexPattern.fields.filter(field => field.sortable && !isNestedField(field)), //todo change sort fields to use fields }); } _onTooltipPropertiesChange = propertyNames => { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js index df212f23cd8942..b04f8ff56e5ee4 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js @@ -113,7 +113,11 @@ export const COLOR_PALETTES = COLOR_PALETTES_CONFIGS.map(palette => { height: '100%', display: 'inline-block', }; - return
     
    ; + return ( +
    +   +
    + ); }); return { value: palette.id, diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js index 242b71522f9a2b..fde088ab4475e6 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js @@ -14,9 +14,7 @@ import { ColorStopsCategorical } from './color_stops_categorical'; const CUSTOM_COLOR_MAP = 'CUSTOM_COLOR_MAP'; export class ColorMapSelect extends Component { - state = { - selected: '', - }; + state = {}; static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.customColorMap === prevState.prevPropsCustomColorMap) { @@ -41,10 +39,7 @@ export class ColorMapSelect extends Component { _onCustomColorMapChange = ({ colorStops, isInvalid }) => { // Manage invalid custom color map in local state if (isInvalid) { - const newState = { - customColorMap: colorStops, - }; - this.setState(newState); + this.setState({ customColorMap: colorStops }); return; } @@ -56,35 +51,34 @@ export class ColorMapSelect extends Component { }; _renderColorStopsInput() { - let colorStopsInput; - if (this.props.useCustomColorMap) { - if (this.props.colorMapType === COLOR_MAP_TYPE.ORDINAL) { - colorStopsInput = ( - - - - - ); - } else if (this.props.colorMapType === COLOR_MAP_TYPE.CATEGORICAL) { - colorStopsInput = ( - - - - - ); - } + if (!this.props.useCustomColorMap) { + return null; } - return colorStopsInput; + + if (this.props.colorMapType === COLOR_MAP_TYPE.ORDINAL) { + return ( + + + + + ); + } + + return ( + + + + + ); } render() { - const colorStopsInput = this._renderColorStopsInput(); const colorMapOptionsWithCustom = [ { value: CUSTOM_COLOR_MAP, @@ -110,7 +104,7 @@ export class ColorMapSelect extends Component { valueOfSelected={valueOfSelected} hasDividers={true} /> - {colorStopsInput} + {this._renderColorStopsInput()} ); } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js index 7994f84386a8a2..5491d5d567f842 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js @@ -13,87 +13,56 @@ import { CATEGORICAL_DATA_TYPES, COLOR_MAP_TYPE } from '../../../../../../common import { COLOR_GRADIENTS, COLOR_PALETTES } from '../../../color_utils'; import { i18n } from '@kbn/i18n'; -export class DynamicColorForm extends React.Component { - state = { - colorMapType: COLOR_MAP_TYPE.ORDINAL, - }; - - constructor() { - super(); - this._isMounted = false; - } - - componentWillUnmount() { - this._isMounted = false; - } +export function DynamicColorForm({ + fields, + onDynamicStyleChange, + staticDynamicSelect, + styleProperty, +}) { + const styleOptions = styleProperty.getOptions(); - componentDidMount() { - this._isMounted = true; - this._loadColorMapType(); - } - - componentDidUpdate() { - this._loadColorMapType(); - } - - async _loadColorMapType() { - const field = this.props.styleProperty.getField(); - if (!field) { - return; - } - const dataType = await field.getDataType(); - const colorMapType = CATEGORICAL_DATA_TYPES.includes(dataType) - ? COLOR_MAP_TYPE.CATEGORICAL - : COLOR_MAP_TYPE.ORDINAL; - if (this._isMounted && this.state.colorMapType !== colorMapType) { - this.setState({ colorMapType }, () => { - const options = this.props.styleProperty.getOptions(); - this.props.onDynamicStyleChange(this.props.styleProperty.getStyleName(), { - ...options, - type: colorMapType, - }); - }); + const onColorMapSelect = ({ color, customColorMap, type, useCustomColorMap }) => { + const newColorOptions = { + ...styleOptions, + type, + }; + if (type === COLOR_MAP_TYPE.ORDINAL) { + newColorOptions.useCustomColorRamp = useCustomColorMap; + newColorOptions.customColorRamp = customColorMap; + newColorOptions.color = color; + } else { + newColorOptions.useCustomColorPalette = useCustomColorMap; + newColorOptions.customColorPalette = customColorMap; + newColorOptions.colorCategory = color; } - } - _getColorSelector() { - const { onDynamicStyleChange, styleProperty } = this.props; - const styleOptions = styleProperty.getOptions(); + onDynamicStyleChange(styleProperty.getStyleName(), newColorOptions); + }; + const onFieldChange = async ({ field }) => { + const { name, origin, type } = field; + onDynamicStyleChange(styleProperty.getStyleName(), { + ...styleOptions, + field: { name, origin }, + type: CATEGORICAL_DATA_TYPES.includes(type) + ? COLOR_MAP_TYPE.CATEGORICAL + : COLOR_MAP_TYPE.ORDINAL, + }); + }; + + const renderColorMapSelect = () => { if (!styleOptions.field || !styleOptions.field.name) { - return; + return null; } - let colorSelect; - const onColorChange = colorOptions => { - const newColorOptions = { - type: colorOptions.type, - }; - if (colorOptions.type === COLOR_MAP_TYPE.ORDINAL) { - newColorOptions.useCustomColorRamp = colorOptions.useCustomColorMap; - newColorOptions.customColorRamp = colorOptions.customColorMap; - newColorOptions.color = colorOptions.color; - } else { - newColorOptions.useCustomColorPalette = colorOptions.useCustomColorMap; - newColorOptions.customColorPalette = colorOptions.customColorMap; - newColorOptions.colorCategory = colorOptions.color; - } - - onDynamicStyleChange(styleProperty.getStyleName(), { - ...styleOptions, - ...newColorOptions, - }); - }; - - if (this.state.colorMapType === COLOR_MAP_TYPE.ORDINAL) { - const customOptionLabel = i18n.translate('xpack.maps.style.customColorRampLabel', { - defaultMessage: 'Custom color ramp', - }); - colorSelect = ( + if (styleProperty.isOrdinal()) { + return ( onColorChange(options)} + customOptionLabel={i18n.translate('xpack.maps.style.customColorRampLabel', { + defaultMessage: 'Custom color ramp', + })} + onChange={onColorMapSelect} colorMapType={COLOR_MAP_TYPE.ORDINAL} color={styleOptions.color} customColorMap={styleOptions.customColorRamp} @@ -101,52 +70,39 @@ export class DynamicColorForm extends React.Component { compressed /> ); - } else if (this.state.colorMapType === COLOR_MAP_TYPE.CATEGORICAL) { - const customOptionLabel = i18n.translate('xpack.maps.style.customColorPaletteLabel', { - defaultMessage: 'Custom color palette', - }); - colorSelect = ( - onColorChange(options)} - colorMapType={COLOR_MAP_TYPE.CATEGORICAL} - color={styleOptions.colorCategory} - customColorMap={styleOptions.customColorPalette} - useCustomColorMap={_.get(styleOptions, 'useCustomColorPalette', false)} - compressed - /> - ); } - return colorSelect; - } - - render() { - const { fields, onDynamicStyleChange, staticDynamicSelect, styleProperty } = this.props; - const styleOptions = styleProperty.getOptions(); - const onFieldChange = options => { - const field = options.field; - onDynamicStyleChange(styleProperty.getStyleName(), { ...styleOptions, field }); - }; - - const colorSelect = this._getColorSelector(); return ( - - - {staticDynamicSelect} - - - - - - {colorSelect} - + ); - } + }; + + return ( + + + {staticDynamicSelect} + + + + + + {renderColorMapSelect()} + + ); } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_select.js index 1d8f4e13fdd1a5..a32c2ce04d7355 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_select.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_select.js @@ -7,48 +7,73 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { EuiComboBox } from '@elastic/eui'; -import { SOURCE_DATA_ID_ORIGIN } from '../../../../../common/constants'; +import { EuiComboBox, EuiHighlight } from '@elastic/eui'; +import { FIELD_ORIGIN } from '../../../../../common/constants'; import { i18n } from '@kbn/i18n'; +import { FieldIcon } from '../../../../../../../../../src/plugins/kibana_react/public'; -export function FieldSelect({ fields, selectedFieldName, onChange, ...rest }) { - const onFieldChange = selectedFields => { - onChange({ - field: selectedFields.length > 0 ? selectedFields[0].value : null, - }); - }; +function renderOption(option, searchValue, contentClassName) { + return ( + + +   + {option.label} + + ); +} - const groupFieldsByOrigin = () => { - const fieldsByOriginMap = new Map(); - fields.forEach(field => { - if (fieldsByOriginMap.has(field.origin)) { - const fieldsList = fieldsByOriginMap.get(field.origin); - fieldsList.push(field); - fieldsByOriginMap.set(field.origin, fieldsList); - } else { - fieldsByOriginMap.set(field.origin, [field]); - } - }); +function groupFieldsByOrigin(fields) { + const fieldsByOriginMap = new Map(); + fields.forEach(field => { + if (fieldsByOriginMap.has(field.origin)) { + const fieldsList = fieldsByOriginMap.get(field.origin); + fieldsList.push(field); + fieldsByOriginMap.set(field.origin, fieldsList); + } else { + fieldsByOriginMap.set(field.origin, [field]); + } + }); - const optionGroups = []; - fieldsByOriginMap.forEach((fieldsList, fieldOrigin) => { - optionGroups.push({ - label: fieldOrigin, - options: fieldsList - .map(field => { - return { value: field, label: field.label }; - }) - .sort((a, b) => { - return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); - }), + function fieldsListToOptions(fieldsList) { + return fieldsList + .map(field => { + return { value: field, label: field.label }; + }) + .sort((a, b) => { + return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); }); - }); + } + + if (fieldsByOriginMap.size === 1) { + // do not show origin group if all fields are from same origin + const onlyOriginKey = fieldsByOriginMap.keys().next().value; + const fieldsList = fieldsByOriginMap.get(onlyOriginKey); + return fieldsListToOptions(fieldsList); + } - optionGroups.sort((a, b) => { - return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); + const optionGroups = []; + fieldsByOriginMap.forEach((fieldsList, fieldOrigin) => { + optionGroups.push({ + label: i18n.translate('xpack.maps.style.fieldSelect.OriginLabel', { + defaultMessage: 'Fields from {fieldOrigin}', + values: { fieldOrigin }, + }), + options: fieldsListToOptions(fieldsList), }); + }); + + optionGroups.sort((a, b) => { + return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); + }); + + return optionGroups; +} - return optionGroups; +export function FieldSelect({ fields, selectedFieldName, onChange, ...rest }) { + const onFieldChange = selectedFields => { + onChange({ + field: selectedFields.length > 0 ? selectedFields[0].value : null, + }); }; let selectedOption; @@ -61,7 +86,7 @@ export function FieldSelect({ fields, selectedFieldName, onChange, ...rest }) { return ( ); @@ -76,7 +102,8 @@ export function FieldSelect({ fields, selectedFieldName, onChange, ...rest }) { export const fieldShape = PropTypes.shape({ name: PropTypes.string.isRequired, - origin: PropTypes.oneOf(['join', SOURCE_DATA_ID_ORIGIN]).isRequired, + origin: PropTypes.oneOf(Object.values(FIELD_ORIGIN)).isRequired, + type: PropTypes.string.isRequired, }); FieldSelect.propTypes = { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/dynamic_label_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/dynamic_label_form.js index bad13b487cc295..7ad541efe0ab71 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/dynamic_label_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/dynamic_label_form.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { FieldSelect } from '../field_select'; @@ -27,7 +26,7 @@ export function DynamicLabelForm({ diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_form.js index e0b7e7b2865a27..df0ae6513f8ed8 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/orientation/dynamic_orientation_form.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; import React from 'react'; import { FieldSelect } from '../field_select'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; @@ -30,7 +29,7 @@ export function DynamicOrientationForm({ diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/dynamic_size_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/dynamic_size_form.js index 8b069cd53b731a..141a9410177905 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/dynamic_size_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/size/dynamic_size_form.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; import React, { Fragment } from 'react'; import { FieldSelect } from '../field_select'; import { SizeRangeSelector } from './size_range_selector'; @@ -50,7 +49,7 @@ export function DynamicSizeForm({ diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js index 2f3cfa1d8e4bb6..0784e2a8cc355c 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js @@ -61,6 +61,7 @@ export class VectorStyleEditor extends Component { label: await field.getLabel(), name: field.getName(), origin: field.getOrigin(), + type: await field.getDataType(), }; }; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js index 98e87b0305b447..37db54389866d4 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js @@ -32,6 +32,10 @@ export class DynamicStyleProperty extends AbstractStyleProperty { return this._field; } + getFieldName() { + return this._field ? this._field.getName() : ''; + } + getComputedFieldName() { if (!this.isComplete()) { return null; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js index 1584dec9989866..024b4463698517 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js @@ -26,7 +26,8 @@ export class StaticSizeProperty extends StaticStyleProperty { syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId) { const iconPixels = - this._size >= HALF_LARGE_MAKI_ICON_SIZE ? LARGE_MAKI_ICON_SIZE : SMALL_MAKI_ICON_SIZE; + this._options.size >= HALF_LARGE_MAKI_ICON_SIZE ? LARGE_MAKI_ICON_SIZE : SMALL_MAKI_ICON_SIZE; + mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`); const halfIconPixels = iconPixels / 2; mbMap.setLayoutProperty(symbolLayerId, 'icon-size', this._options.size / halfIconPixels); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js index ec0afb6a6a37e7..558df73f74595b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js @@ -175,7 +175,7 @@ export class VectorStyle extends AbstractStyle { * This method does not update its descriptor. It just returns a new descriptor that the caller * can then use to update store state via dispatch. */ - getDescriptorWithMissingStylePropsRemoved(nextOrdinalFields) { + getDescriptorWithMissingStylePropsRemoved(nextFields) { const originalProperties = this.getRawProperties(); const updatedProperties = {}; @@ -192,7 +192,7 @@ export class VectorStyle extends AbstractStyle { return; } - const matchingOrdinalField = nextOrdinalFields.find(ordinalField => { + const matchingOrdinalField = nextFields.find(ordinalField => { return fieldName === ordinalField.getName(); }); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js index b8f5c74139a632..7c35bbeba018b8 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js @@ -66,21 +66,19 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => { it('Should return no changes when next oridinal fields contain existing style property fields', () => { const vectorStyle = new VectorStyle({ properties }, new MockSource()); - const nextOridinalFields = [new MockField({ fieldName })]; - const { hasChanges } = vectorStyle.getDescriptorWithMissingStylePropsRemoved( - nextOridinalFields - ); + const nextFields = [new MockField({ fieldName })]; + const { hasChanges } = vectorStyle.getDescriptorWithMissingStylePropsRemoved(nextFields); expect(hasChanges).toBe(false); }); it('Should clear missing fields when next oridinal fields do not contain existing style property fields', () => { const vectorStyle = new VectorStyle({ properties }, new MockSource()); - const nextOridinalFields = []; + const nextFields = []; const { hasChanges, nextStyleDescriptor, - } = vectorStyle.getDescriptorWithMissingStylePropsRemoved(nextOridinalFields); + } = vectorStyle.getDescriptorWithMissingStylePropsRemoved(nextFields); expect(hasChanges).toBe(true); expect(nextStyleDescriptor.properties).toEqual({ fillColor: { diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 96223aa536170e..31c3831fb612a6 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -209,10 +209,6 @@ export class VectorLayer extends AbstractLayer { return [...numberFieldOptions, ...this._getJoinFields()]; } - async getOrdinalFields() { - return [...(await this.getDateFields()), ...(await this.getNumberFields())]; - } - async getCategoricalFields() { return await this._source.getCategoricalFields(); } diff --git a/x-pack/legacy/plugins/maps/public/reducers/map.js b/x-pack/legacy/plugins/maps/public/reducers/map.js index ac409c685c71af..f933babb6f61b8 100644 --- a/x-pack/legacy/plugins/maps/public/reducers/map.js +++ b/x-pack/legacy/plugins/maps/public/reducers/map.js @@ -447,16 +447,28 @@ function updateWithDataResponse(state, action) { return resetDataRequest(state, action, dataRequest); } -function resetDataRequest(state, action, request) { +export function resetDataRequest(state, action, request) { const dataRequest = request || getValidDataRequest(state, action); if (!dataRequest) { return state; } - dataRequest.dataRequestToken = null; - dataRequest.dataId = action.dataId; - const layerList = [...state.layerList]; - return { ...state, layerList }; + const layer = findLayerById(state, action.layerId); + const dataRequestIndex = layer.__dataRequests.indexOf(dataRequest); + + const newDataRequests = [...layer.__dataRequests]; + newDataRequests[dataRequestIndex] = { + ...dataRequest, + dataRequestToken: null, + }; + + const layerIndex = state.layerList.indexOf(layer); + const newLayerList = [...state.layerList]; + newLayerList[layerIndex] = { + ...layer, + __dataRequests: newDataRequests, + }; + return { ...state, layerList: newLayerList }; } function getValidDataRequest(state, action, checkRequestToken = true) { diff --git a/x-pack/legacy/plugins/maps/public/reducers/map.test.js b/x-pack/legacy/plugins/maps/public/reducers/map.test.js new file mode 100644 index 00000000000000..089dec952fc777 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/reducers/map.test.js @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('../actions/map_actions', () => ({})); + +import { resetDataRequest } from './map'; +import _ from 'lodash'; + +describe('reducers/map', () => { + it('Should clear datarequest without mutation store state', async () => { + const layerId = 'foobar'; + const requestToken = 'tokenId'; + const dataId = 'dataId'; + + const preState = { + layerList: [ + { + id: `not_${layerId}`, + }, + { + id: layerId, + __dataRequests: [ + { + dataRequestToken: `not_${requestToken}`, + dataId: `not_${dataId}`, + }, + { + dataRequestToken: requestToken, + dataId: dataId, + }, + ], + }, + ], + }; + + const preStateCopy = _.cloneDeep(preState); + + const action = { + layerId, + requestToken, + dataId, + }; + + const postState = resetDataRequest(preState, action); + + //Ensure previous state is not mutated. + expect(_.isEqual(preState, preStateCopy)).toEqual(true); + + //Ensure new state is set correctly. + expect(postState.layerList[1].__dataRequests[1].dataId).toEqual(dataId); + expect(postState.layerList[1].__dataRequests[1].dataRequestToken).toEqual(null); + }); +}); diff --git a/x-pack/legacy/plugins/maps/public/reducers/util.test.js b/x-pack/legacy/plugins/maps/public/reducers/util.test.js index b9c6052a2e9e0b..2829c9410724e3 100644 --- a/x-pack/legacy/plugins/maps/public/reducers/util.test.js +++ b/x-pack/legacy/plugins/maps/public/reducers/util.test.js @@ -6,7 +6,7 @@ import { copyPersistentState } from './util'; -describe('store/util', () => { +describe('reducers/util', () => { describe('copyPersistentState', () => { it('should ignore state preceded by double underscores', async () => { const copy = copyPersistentState({ diff --git a/x-pack/legacy/plugins/maps/server/plugin.js b/x-pack/legacy/plugins/maps/server/plugin.js index 6009cea330ab00..d52a9f12ba6310 100644 --- a/x-pack/legacy/plugins/maps/server/plugin.js +++ b/x-pack/legacy/plugins/maps/server/plugin.js @@ -10,6 +10,7 @@ import { getFlightsSavedObjects } from './sample_data/flights_saved_objects.js'; import { getWebLogsSavedObjects } from './sample_data/web_logs_saved_objects.js'; import { LICENSE_CHECK_STATE } from '../../../../plugins/licensing/server'; import { initRoutes } from './routes'; +import { emsBoundariesSpecProvider } from './tutorials/ems'; export class MapPlugin { setup(core, plugins, __LEGACY) { @@ -115,6 +116,13 @@ export class MapPlugin { isLayerTOCOpen: false, }, }); + + home.tutorials.registerTutorial( + emsBoundariesSpecProvider({ + prependBasePath: core.http.basePath.prepend, + emsLandingPageUrl: __LEGACY.mapConfig().emsLandingPageUrl, + }) + ); } __LEGACY.injectUiAppVars(APP_ID, async () => { diff --git a/x-pack/legacy/plugins/maps/server/tutorials/ems/index.ts b/x-pack/legacy/plugins/maps/server/tutorials/ems/index.ts new file mode 100644 index 00000000000000..88c22d01a527ad --- /dev/null +++ b/x-pack/legacy/plugins/maps/server/tutorials/ems/index.ts @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../../../../../../src/plugins/home/server'; + +export function emsBoundariesSpecProvider({ + emsLandingPageUrl, + prependBasePath, +}: { + emsLandingPageUrl: string; + prependBasePath: (path: string) => string; +}) { + return () => ({ + id: 'emsBoundaries', + name: i18n.translate('xpack.maps.tutorials.ems.nameTitle', { + defaultMessage: 'EMS Boundaries', + }), + category: TutorialsCategory.OTHER, + shortDescription: i18n.translate('xpack.maps.tutorials.ems.shortDescription', { + defaultMessage: 'Administrative boundaries from Elastic Maps Service.', + }), + longDescription: i18n.translate('xpack.maps.tutorials.ems.longDescription', { + defaultMessage: + '[Elastic Maps Service (EMS)](https://www.elastic.co/elastic-maps-service) \ +hosts tile layers and vector shapes of administrative boundaries. \ +Indexing EMS administrative boundaries in Elasticsearch allows for search on boundary property fields.', + }), + euiIconType: 'emsApp', + completionTimeMinutes: 1, + previewImagePath: '/plugins/kibana/home/tutorial_resources/ems/boundaries_screenshot.png', + onPrem: { + instructionSets: [ + { + instructionVariants: [ + { + id: 'EMS', + instructions: [ + { + title: i18n.translate('xpack.maps.tutorials.ems.downloadStepTitle', { + defaultMessage: 'Download Elastic Maps Service boundaries', + }), + textPre: i18n.translate('xpack.maps.tutorials.ems.downloadStepText', { + defaultMessage: + '1. Navigate to Elastic Maps Service [landing page]({emsLandingPageUrl}).\n\ +2. In the left sidebar, select an administrative boundary.\n\ +3. Click `Download GeoJSON` button.', + values: { + emsLandingPageUrl, + }, + }), + }, + { + title: i18n.translate('xpack.maps.tutorials.ems.uploadStepTitle', { + defaultMessage: 'Index Elastic Maps Service boundaries', + }), + textPre: i18n.translate('xpack.maps.tutorials.ems.uploadStepText', { + defaultMessage: + '1. Open [Elastic Maps]({newMapUrl}).\n\ +2. Click `Add layer`, then select `Upload GeoJSON`.\n\ +3. Upload the GeoJSON file and click `Import file`.', + values: { + newMapUrl: prependBasePath('/app/maps#/map'), + }, + }), + }, + ], + }, + ], + }, + ], + }, + }); +} diff --git a/x-pack/legacy/plugins/ml/common/constants/new_job.ts b/x-pack/legacy/plugins/ml/common/constants/new_job.ts index 3c98b372afdf73..862fa72d11fdb7 100644 --- a/x-pack/legacy/plugins/ml/common/constants/new_job.ts +++ b/x-pack/legacy/plugins/ml/common/constants/new_job.ts @@ -26,7 +26,14 @@ export const DEFAULT_QUERY_DELAY = '60s'; export const SHARED_RESULTS_INDEX_NAME = 'shared'; +// Categorization export const NUMBER_OF_CATEGORY_EXAMPLES = 5; export const CATEGORY_EXAMPLES_SAMPLE_SIZE = 1000; export const CATEGORY_EXAMPLES_WARNING_LIMIT = 0.75; export const CATEGORY_EXAMPLES_ERROR_LIMIT = 0.02; + +export enum CATEGORY_EXAMPLES_VALIDATION_STATUS { + VALID = 'valid', + PARTIALLY_VALID = 'partially_valid', + INVALID = 'invalid', +} diff --git a/x-pack/legacy/plugins/ml/common/types/categories.ts b/x-pack/legacy/plugins/ml/common/types/categories.ts index 6ccd13ed9a39ec..862ad8e194a0b2 100644 --- a/x-pack/legacy/plugins/ml/common/types/categories.ts +++ b/x-pack/legacy/plugins/ml/common/types/categories.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../constants/new_job'; + export type CategoryId = number; export interface Category { @@ -23,3 +25,31 @@ export interface Token { type: string; position: number; } + +export interface CategorizationAnalyzer { + char_filter?: any[]; + tokenizer?: string; + filter?: any[]; + analyzer?: string; +} + +export interface CategoryFieldExample { + text: string; + tokens: Token[]; +} + +export enum VALIDATION_RESULT { + TOKEN_COUNT, + MEDIAN_LINE_LENGTH, + NULL_VALUES, + NO_EXAMPLES, + TOO_MANY_TOKENS, + FAILED_TO_TOKENIZE, + INSUFFICIENT_PRIVILEGES, +} + +export interface FieldExampleCheck { + id: VALIDATION_RESULT; + valid: CATEGORY_EXAMPLES_VALIDATION_STATUS; + message: string; +} diff --git a/x-pack/legacy/plugins/ml/common/util/string_utils.test.ts b/x-pack/legacy/plugins/ml/common/util/string_utils.test.ts index aba2dbd230ada3..026c8e6110c993 100644 --- a/x-pack/legacy/plugins/ml/common/util/string_utils.test.ts +++ b/x-pack/legacy/plugins/ml/common/util/string_utils.test.ts @@ -4,7 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { renderTemplate } from './string_utils'; +import { renderTemplate, getMedianStringLength } from './string_utils'; + +const strings: string[] = [ + 'foo', + 'foofoofoofoofoo', + 'foofoofoo', + 'f', + 'f', + 'foofoofoofoofoofoofoo', +]; +const noStrings: string[] = []; describe('ML - string utils', () => { describe('renderTemplate', () => { @@ -24,4 +34,16 @@ describe('ML - string utils', () => { expect(result).toBe('string with 1 replacement, and a 2nd one.'); }); }); + + describe('getMedianStringLength', () => { + test('test median for string array', () => { + const result = getMedianStringLength(strings); + expect(result).toBe(9); + }); + + test('test median for no strings', () => { + const result = getMedianStringLength(noStrings); + expect(result).toBe(0); + }); + }); }); diff --git a/x-pack/legacy/plugins/ml/common/util/string_utils.ts b/x-pack/legacy/plugins/ml/common/util/string_utils.ts index 432baabe773cc1..9dd2ce3d74cd5d 100644 --- a/x-pack/legacy/plugins/ml/common/util/string_utils.ts +++ b/x-pack/legacy/plugins/ml/common/util/string_utils.ts @@ -17,3 +17,8 @@ export function renderTemplate(str: string, data?: Record): stri return str; } + +export function getMedianStringLength(strings: string[]) { + const sortedStringLengths = strings.map(s => s.length).sort((a, b) => a - b); + return sortedStringLengths[Math.floor(sortedStringLengths.length / 2)] || 0; +} diff --git a/x-pack/legacy/plugins/ml/index.ts b/x-pack/legacy/plugins/ml/index.ts index c4289389b0d56d..fc1cec7c16208a 100755 --- a/x-pack/legacy/plugins/ml/index.ts +++ b/x-pack/legacy/plugins/ml/index.ts @@ -10,7 +10,7 @@ import KbnServer, { Server } from 'src/legacy/server/kbn_server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { plugin } from './server/new_platform'; import { CloudSetup } from '../../../plugins/cloud/server'; - +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; import { MlInitializerContext, MlCoreSetup, @@ -42,6 +42,7 @@ export const ml = (kibana: any) => { icon: 'plugins/ml/application/ml.svg', euiIconType: 'machineLearningApp', main: 'plugins/ml/legacy', + category: DEFAULT_APP_CATEGORIES.analyze, }, styleSheetPaths: resolve(__dirname, 'public/application/index.scss'), hacks: ['plugins/ml/application/hacks/toggle_app_link_in_nav'], diff --git a/x-pack/legacy/plugins/ml/public/application/components/chart_tooltip/chart_tooltip.tsx b/x-pack/legacy/plugins/ml/public/application/components/chart_tooltip/chart_tooltip.tsx index a28dc41fa1790f..db42c90d49ebbf 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/chart_tooltip/chart_tooltip.tsx +++ b/x-pack/legacy/plugins/ml/public/application/components/chart_tooltip/chart_tooltip.tsx @@ -9,12 +9,11 @@ import React, { useRef, FC } from 'react'; import { TooltipValueFormatter } from '@elastic/charts'; import useObservable from 'react-use/lib/useObservable'; -import { chartTooltip$, ChartTooltipValue } from './chart_tooltip_service'; +import { chartTooltip$, ChartTooltipState, ChartTooltipValue } from './chart_tooltip_service'; type RefValue = HTMLElement | null; -function useRefWithCallback() { - const chartTooltipState = useObservable(chartTooltip$); +function useRefWithCallback(chartTooltipState?: ChartTooltipState) { const ref = useRef(null); return (node: RefValue) => { @@ -66,7 +65,7 @@ const renderHeader = (headerData?: ChartTooltipValue, formatter?: TooltipValueFo export const ChartTooltip: FC = () => { const chartTooltipState = useObservable(chartTooltip$); - const chartTooltipElement = useRefWithCallback(); + const chartTooltipElement = useRefWithCallback(chartTooltipState); if (chartTooltipState === undefined || !chartTooltipState.isTooltipVisible) { return
    ; diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx index 68856eb42973bd..721b8a458efc19 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx @@ -33,6 +33,8 @@ import { NavigationMenu } from '../../components/navigation_menu'; import { ML_JOB_FIELD_TYPES } from '../../../../common/constants/field_types'; import { SEARCH_QUERY_LANGUAGE } from '../../../../common/constants/search'; import { isFullLicense } from '../../license/check_license'; +import { checkPermission } from '../../privilege/check_privilege'; +import { mlNodesAvailable } from '../../ml_nodes_check/check_ml_nodes'; import { FullTimeRangeSelector } from '../../components/full_time_range_selector'; import { mlTimefilterRefresh$ } from '../../services/timefilter_refresh_service'; import { useKibanaContext, SavedSearchQuery } from '../../contexts/kibana'; @@ -130,9 +132,11 @@ export const Page: FC = () => { const defaults = getDefaultPageState(); - const [showActionsPanel] = useState( - isFullLicense() && currentIndexPattern.timeFieldName !== undefined - ); + const showActionsPanel = + isFullLicense() && + checkPermission('canCreateJob') && + mlNodesAvailable() && + currentIndexPattern.timeFieldName !== undefined; const [searchString, setSearchString] = useState(defaults.searchString); const [searchQuery, setSearchQuery] = useState(defaults.searchQuery); @@ -613,7 +617,9 @@ export const Page: FC = () => { )} - + {showActionsPanel === true && ( + + )} diff --git a/x-pack/legacy/plugins/ml/public/application/explorer/actions/load_explorer_data.ts b/x-pack/legacy/plugins/ml/public/application/explorer/actions/load_explorer_data.ts index ed734051342248..819db630c0609d 100644 --- a/x-pack/legacy/plugins/ml/public/application/explorer/actions/load_explorer_data.ts +++ b/x-pack/legacy/plugins/ml/public/application/explorer/actions/load_explorer_data.ts @@ -12,11 +12,11 @@ import { forkJoin, of, Observable, Subject } from 'rxjs'; import { mergeMap, switchMap, tap } from 'rxjs/operators'; import { anomalyDataChange } from '../explorer_charts/explorer_charts_container_service'; -import { VIEW_BY_JOB_LABEL } from '../explorer_constants'; import { explorerService } from '../explorer_dashboard_service'; import { getDateFormatTz, getSelectionInfluencers, + getSelectionJobIds, getSelectionTimeRange, loadAnnotationsTableData, loadAnomaliesTableData, @@ -114,12 +114,7 @@ function loadExplorerData(config: LoadExplorerDataConfig): Observable d.id); - + const jobIds = getSelectionJobIds(selectedCells, selectedJobs); const timerange = getSelectionTimeRange( selectedCells, swimlaneBucketInterval.asSeconds(), diff --git a/x-pack/legacy/plugins/ml/public/application/explorer/explorer.js b/x-pack/legacy/plugins/ml/public/application/explorer/explorer.js index 6a1c5339de1f56..8d26fafe8057c8 100644 --- a/x-pack/legacy/plugins/ml/public/application/explorer/explorer.js +++ b/x-pack/legacy/plugins/ml/public/application/explorer/explorer.js @@ -120,8 +120,12 @@ export class Explorer extends React.Component { this.disableDragSelectOnMouseLeave = true; }, - onDragStart() { - if (ALLOW_CELL_RANGE_SELECTION) { + onDragStart(e) { + let target = e.target; + while (target && target !== document.body && !target.classList.contains('sl-cell')) { + target = target.parentNode; + } + if (ALLOW_CELL_RANGE_SELECTION && target !== document.body) { dragSelect$.next({ action: DRAG_SELECT_ACTION.DRAG_START, }); diff --git a/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.d.ts b/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.d.ts index 0ab75b1db29722..c60b2d55d86862 100644 --- a/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.d.ts @@ -35,10 +35,15 @@ export declare const getDefaultSwimlaneData: () => SwimlaneData; export declare const getInfluencers: (selectedJobs: any[]) => string[]; +export declare const getSelectionJobIds: ( + selectedCells: AppStateSelectedCells | undefined, + selectedJobs: ExplorerJob[] +) => string[]; + export declare const getSelectionInfluencers: ( selectedCells: AppStateSelectedCells | undefined, fieldName: string -) => any[]; +) => string[]; interface SelectionTimeRange { earliestMs: number; diff --git a/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.js b/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.js index 14d356c0d1c81c..4818856b8a8d2e 100644 --- a/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.js +++ b/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.js @@ -222,6 +222,19 @@ export function getSelectionInfluencers(selectedCells, fieldName) { return []; } +export function getSelectionJobIds(selectedCells, selectedJobs) { + if ( + selectedCells !== undefined && + selectedCells.type !== SWIMLANE_TYPE.OVERALL && + selectedCells.viewByFieldName !== undefined && + selectedCells.viewByFieldName === VIEW_BY_JOB_LABEL + ) { + return selectedCells.lanes; + } + + return selectedJobs.map(d => d.id); +} + export function getSwimlaneBucketInterval(selectedJobs, swimlaneContainerWidth) { // Bucketing interval should be the maximum of the chart related interval (i.e. time range related) // and the max bucket span for the jobs shown in the chart. @@ -587,10 +600,7 @@ export async function loadAnomaliesTableData( tableSeverity, influencersFilterQuery ) { - const jobIds = - selectedCells !== undefined && selectedCells.viewByFieldName === VIEW_BY_JOB_LABEL - ? selectedCells.lanes - : selectedJobs.map(d => d.id); + const jobIds = getSelectionJobIds(selectedCells, selectedJobs); const influencers = getSelectionInfluencers(selectedCells, fieldName); const timeRange = getSelectionTimeRange(selectedCells, interval, bounds); diff --git a/x-pack/legacy/plugins/ml/public/application/explorer/reducers/explorer_reducer/set_influencer_filter_settings.ts b/x-pack/legacy/plugins/ml/public/application/explorer/reducers/explorer_reducer/set_influencer_filter_settings.ts index 8d083a396582aa..0d84179c572d2b 100644 --- a/x-pack/legacy/plugins/ml/public/application/explorer/reducers/explorer_reducer/set_influencer_filter_settings.ts +++ b/x-pack/legacy/plugins/ml/public/application/explorer/reducers/explorer_reducer/set_influencer_filter_settings.ts @@ -23,17 +23,20 @@ export function setInfluencerFilterSettings( const { selectedCells, viewBySwimlaneOptions } = state; let selectedViewByFieldName = state.viewBySwimlaneFieldName; + const filteredViewBySwimlaneOptions = viewBySwimlaneOptions.filter(d => + filteredFields.includes(d) + ); // if it's an AND filter set view by swimlane to job ID as the others will have no results - if (isAndOperator && selectedCells === null) { + if (isAndOperator && selectedCells === undefined) { selectedViewByFieldName = VIEW_BY_JOB_LABEL; } else { // Set View by dropdown to first relevant fieldName based on incoming filter if there's no cell selection already // or if selected cell is from overall swimlane as this won't include an additional influencer filter for (let i = 0; i < filteredFields.length; i++) { if ( - viewBySwimlaneOptions.includes(filteredFields[i]) && - (selectedCells === null || (selectedCells && selectedCells.type === 'overall')) + filteredViewBySwimlaneOptions.includes(filteredFields[i]) && + (selectedCells === undefined || (selectedCells && selectedCells.type === 'overall')) ) { selectedViewByFieldName = filteredFields[i]; break; @@ -53,5 +56,6 @@ export function setInfluencerFilterSettings( selectedViewByFieldName === VIEW_BY_JOB_LABEL || filteredFields.includes(selectedViewByFieldName) === false, viewBySwimlaneFieldName: selectedViewByFieldName, + viewBySwimlaneOptions: filteredViewBySwimlaneOptions, }; } diff --git a/x-pack/legacy/plugins/ml/public/application/formatters/round_to_decimal_place.test.ts b/x-pack/legacy/plugins/ml/public/application/formatters/round_to_decimal_place.test.ts index 99b9aceab3696f..663a3f3d8f9556 100644 --- a/x-pack/legacy/plugins/ml/public/application/formatters/round_to_decimal_place.test.ts +++ b/x-pack/legacy/plugins/ml/public/application/formatters/round_to_decimal_place.test.ts @@ -20,6 +20,7 @@ describe('ML - roundToDecimalPlace formatter', () => { expect(roundToDecimalPlace(0.0005)).toBe('5.00e-4'); expect(roundToDecimalPlace(-0.0005)).toBe('-5.00e-4'); expect(roundToDecimalPlace(-12.045)).toBe(-12.04); + expect(roundToDecimalPlace(0)).toBe(0); }); it('returns the correct format using specified decimal place', () => { @@ -31,5 +32,6 @@ describe('ML - roundToDecimalPlace formatter', () => { expect(roundToDecimalPlace(0.0005, 4)).toBe(0.0005); expect(roundToDecimalPlace(0.00005, 4)).toBe('5.00e-5'); expect(roundToDecimalPlace(-0.00005, 4)).toBe('-5.00e-5'); + expect(roundToDecimalPlace(0, 4)).toBe(0); }); }); diff --git a/x-pack/legacy/plugins/ml/public/application/formatters/round_to_decimal_place.ts b/x-pack/legacy/plugins/ml/public/application/formatters/round_to_decimal_place.ts index f863fe6d76e57d..5a030d7619e986 100644 --- a/x-pack/legacy/plugins/ml/public/application/formatters/round_to_decimal_place.ts +++ b/x-pack/legacy/plugins/ml/public/application/formatters/round_to_decimal_place.ts @@ -4,7 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -export function roundToDecimalPlace(num: number, dp: number = 2) { +export function roundToDecimalPlace(num: number, dp: number = 2): number | string { + if (num % 1 === 0) { + // no decimal place + return num; + } + if (Math.abs(num) < Math.pow(10, -dp)) { return Number.parseFloat(String(num)).toExponential(2); } diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_view.js b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_view.js index 0a823726a2d680..7a855301885a92 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_view.js +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/create_watch_view.js @@ -21,7 +21,7 @@ import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; import { parseInterval } from '../../../../../../common/util/parse_interval'; import { ml } from '../../../../services/ml_api_service'; -import { SelectSeverity } from '../../../../components/controls/select_severity/select_severity'; +import { SelectSeverity } from './select_severity'; import { mlCreateWatchService } from './create_watch_service'; const STATUS = mlCreateWatchService.STATUS; @@ -111,19 +111,6 @@ export const CreateWatch = injectI18n( render() { const { intl } = this.props; - const mlSelectSeverityService = { - state: { - set: (name, threshold) => { - this.onThresholdChange(threshold); - return { - changed: () => {}, - }; - }, - get: () => { - return this.config.threshold; - }, - }, - }; const { status } = this.state; if (status === null || status === STATUS.SAVING || status === STATUS.SAVE_FAILED) { @@ -164,10 +151,7 @@ export const CreateWatch = injectI18n(
    - +
    diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/select_severity.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/select_severity.tsx new file mode 100644 index 00000000000000..8b0e7da2a5637d --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/select_severity.tsx @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/* + * React component for rendering a select element with threshold levels. + * This is basically a copy of SelectSeverity in public/application/components/controls/select_severity + * but which stores its state internally rather than in the appState + */ +import React, { Fragment, FC, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { EuiHealth, EuiSpacer, EuiSuperSelect, EuiText } from '@elastic/eui'; + +import { getSeverityColor } from '../../../../../../common/util/anomaly_utils'; + +const warningLabel = i18n.translate('xpack.ml.controls.selectSeverity.warningLabel', { + defaultMessage: 'warning', +}); +const minorLabel = i18n.translate('xpack.ml.controls.selectSeverity.minorLabel', { + defaultMessage: 'minor', +}); +const majorLabel = i18n.translate('xpack.ml.controls.selectSeverity.majorLabel', { + defaultMessage: 'major', +}); +const criticalLabel = i18n.translate('xpack.ml.controls.selectSeverity.criticalLabel', { + defaultMessage: 'critical', +}); + +const optionsMap = { + [warningLabel]: 0, + [minorLabel]: 25, + [majorLabel]: 50, + [criticalLabel]: 75, +}; + +interface TableSeverity { + val: number; + display: string; + color: string; +} + +export const SEVERITY_OPTIONS: TableSeverity[] = [ + { + val: 0, + display: warningLabel, + color: getSeverityColor(0), + }, + { + val: 25, + display: minorLabel, + color: getSeverityColor(25), + }, + { + val: 50, + display: majorLabel, + color: getSeverityColor(50), + }, + { + val: 75, + display: criticalLabel, + color: getSeverityColor(75), + }, +]; + +function optionValueToThreshold(value: number) { + // Get corresponding threshold object with required display and val properties from the specified value. + let threshold = SEVERITY_OPTIONS.find(opt => opt.val === value); + + // Default to warning if supplied value doesn't map to one of the options. + if (threshold === undefined) { + threshold = SEVERITY_OPTIONS[0]; + } + + return threshold; +} + +const TABLE_SEVERITY_DEFAULT = SEVERITY_OPTIONS[0]; + +const getSeverityOptions = () => + SEVERITY_OPTIONS.map(({ color, display, val }) => ({ + value: display, + inputDisplay: ( + + + {display} + + + ), + dropdownDisplay: ( + + + {display} + + + +

    + +

    +
    +
    + ), + })); + +interface Props { + onChange: (sev: TableSeverity) => void; +} + +export const SelectSeverity: FC = ({ onChange }) => { + const [severity, setSeverity] = useState(TABLE_SEVERITY_DEFAULT); + + const onSeverityChange = (valueDisplay: string) => { + const option = optionValueToThreshold(optionsMap[valueDisplay]); + setSeverity(option); + onChange(option); + }; + + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/job_details/format_values.js b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/job_details/format_values.js index eb0a905725d750..9984f3be299ae8 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/job_details/format_values.js +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/job_details/format_values.js @@ -6,6 +6,7 @@ import numeral from '@elastic/numeral'; import { formatDate } from '@elastic/eui/lib/services/format'; +import { roundToDecimalPlace } from '../../../../formatters/round_to_decimal_place'; import { toLocaleString } from '../../../../util/string_utils'; const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; @@ -35,6 +36,8 @@ export function formatValues([key, value]) { case 'established_model_memory': case 'input_bytes': case 'model_bytes': + case 'model_bytes_exceeded': + case 'model_bytes_memory_limit': value = formatData(value); break; @@ -53,9 +56,16 @@ export function formatValues([key, value]) { case 'total_over_field_count': case 'total_partition_field_count': case 'bucket_allocation_failures_count': + case 'search_count': value = toLocaleString(value); break; + // numbers rounded to 3 decimal places + case 'average_search_time_per_bucket_ms': + case 'exponential_average_search_time_per_hour_ms': + value = typeof value === 'number' ? roundToDecimalPlace(value, 3).toLocaleString() : value; + break; + default: break; } diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js index f6d10c36e3ba0a..3ea25fb2f44eb6 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js @@ -42,6 +42,7 @@ export class StartDatafeedModal extends Component { allowCreateWatch: false, initialSpecifiedStartTime: now, now, + timeRangeValid: true, }; this.initialSpecifiedStartTime = now; @@ -77,6 +78,10 @@ export class StartDatafeedModal extends Component { this.setState({ isModalVisible: false }); }; + setTimeRangeValid = timeRangeValid => { + this.setState({ timeRangeValid }); + }; + showModal = (jobs, showCreateWatchFlyout) => { const startTime = undefined; const now = moment(); @@ -116,10 +121,19 @@ export class StartDatafeedModal extends Component { }; render() { - const { jobs, initialSpecifiedStartTime, startTime, endTime, createWatch, now } = this.state; + const { + jobs, + initialSpecifiedStartTime, + startTime, + endTime, + createWatch, + now, + timeRangeValid, + } = this.state; const startableJobs = jobs !== undefined ? jobs.filter(j => j.hasDatafeed) : []; // disable start button if the start and end times are the same - const startDisabled = startTime !== undefined && startTime === endTime; + const startDisabled = + timeRangeValid === false || (startTime !== undefined && startTime === endTime); let modal; if (this.state.isModalVisible) { @@ -151,6 +165,7 @@ export class StartDatafeedModal extends Component { setStartTime={this.setStartTime} setEndTime={this.setEndTime} now={now} + setTimeRangeValid={this.setTimeRangeValid} /> {this.state.endTime === undefined && (
    diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js index caed0f5168c141..f6a41220bf9b52 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js @@ -5,11 +5,12 @@ */ import PropTypes from 'prop-types'; -import React, { Component } from 'react'; +import React, { Component, useState, useEffect } from 'react'; -import { EuiDatePicker } from '@elastic/eui'; +import { EuiDatePicker, EuiFieldText } from '@elastic/eui'; import moment from 'moment'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; @@ -67,7 +68,7 @@ export class TimeRangeSelector extends Component { start: moment.isMoment(this.props.startTime) ? this.props.startTime : this.latestTimestamp, end: moment.isMoment(this.props.endTime) ? this.props.endTime : this.now, }; - const formattedStartTime = this.latestTimestamp.format(TIME_FORMAT); + const formattedLatestStartTime = this.latestTimestamp.format(TIME_FORMAT); // Show different labels for the start time depending on whether // the job has seen any data yet @@ -77,8 +78,8 @@ export class TimeRangeSelector extends Component { ? [ , ), }, @@ -140,12 +141,12 @@ export class TimeRangeSelector extends Component { /> ), body: ( - ), }, @@ -216,6 +217,59 @@ function TabStack({ title, items, switchState, switchFunc }) {
    ); } + +const DatePickerWithInput = ({ date, onChange, minDate, setIsValid, tab }) => { + const [dateString, setDateString] = useState(date.format(TIME_FORMAT)); + const [currentTab, setCurrentTab] = useState(tab); + + useEffect(() => { + if (currentTab !== tab) { + // if the tab has changed, reset the text to be the same as the date prop + setDateString(date.format(TIME_FORMAT)); + setCurrentTab(tab); + } + }, [tab]); + + function onTextChange(e) { + const val = e.target.value; + setDateString(val); + + const newDate = moment(val); + if (newDate.isValid()) { + setIsValid(true); + onChange(newDate); + } else { + setIsValid(false); + } + } + + function onCalendarChange(newDate) { + setDateString(newDate.format(TIME_FORMAT)); + setIsValid(true); + onChange(newDate); + } + + return ( + <> + + + + ); +}; + TimeRangeSelector.propTypes = { startTime: PropTypes.object.isRequired, endTime: PropTypes.object, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts index 71619311c4361d..eb2f0f4e368a34 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts @@ -16,25 +16,31 @@ import { CREATED_BY_LABEL, DEFAULT_BUCKET_SPAN, DEFAULT_RARE_BUCKET_SPAN, + CATEGORY_EXAMPLES_VALIDATION_STATUS, } from '../../../../../../common/constants/new_job'; import { ML_JOB_AGGREGATION } from '../../../../../../common/constants/aggregation_types'; +import { + CategorizationAnalyzer, + CategoryFieldExample, + FieldExampleCheck, +} from '../../../../../../common/types/categories'; import { getRichDetectors } from './util/general'; -import { CategorizationExamplesLoader, CategoryExample } from '../results_loader'; -import { CategorizationAnalyzer, getNewJobDefaults } from '../../../../services/ml_server_info'; - -type CategorizationAnalyzerType = CategorizationAnalyzer | null; +import { CategorizationExamplesLoader } from '../results_loader'; +import { getNewJobDefaults } from '../../../../services/ml_server_info'; export class CategorizationJobCreator extends JobCreator { protected _type: JOB_TYPE = JOB_TYPE.CATEGORIZATION; private _createCountDetector: () => void = () => {}; private _createRareDetector: () => void = () => {}; private _examplesLoader: CategorizationExamplesLoader; - private _categoryFieldExamples: CategoryExample[] = []; - private _categoryFieldValid: number = 0; + private _categoryFieldExamples: CategoryFieldExample[] = []; + private _validationChecks: FieldExampleCheck[] = []; + private _overallValidStatus: CATEGORY_EXAMPLES_VALIDATION_STATUS = + CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID; private _detectorType: ML_JOB_AGGREGATION.COUNT | ML_JOB_AGGREGATION.RARE = ML_JOB_AGGREGATION.COUNT; - private _categorizationAnalyzer: CategorizationAnalyzerType = null; - private _defaultCategorizationAnalyzer: CategorizationAnalyzerType; + private _categorizationAnalyzer: CategorizationAnalyzer = {}; + private _defaultCategorizationAnalyzer: CategorizationAnalyzer; constructor( indexPattern: IndexPattern, @@ -46,7 +52,7 @@ export class CategorizationJobCreator extends JobCreator { this._examplesLoader = new CategorizationExamplesLoader(this, indexPattern, query); const { anomaly_detectors: anomalyDetectors } = getNewJobDefaults(); - this._defaultCategorizationAnalyzer = anomalyDetectors.categorization_analyzer || null; + this._defaultCategorizationAnalyzer = anomalyDetectors.categorization_analyzer || {}; } public setDefaultDetectorProperties( @@ -93,7 +99,8 @@ export class CategorizationJobCreator extends JobCreator { } else { delete this._job_config.analysis_config.categorization_field_name; this._categoryFieldExamples = []; - this._categoryFieldValid = 0; + this._validationChecks = []; + this._overallValidStatus = CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID; } } @@ -102,31 +109,38 @@ export class CategorizationJobCreator extends JobCreator { } public async loadCategorizationFieldExamples() { - const { valid, examples, sampleSize } = await this._examplesLoader.loadExamples(); + const { + examples, + sampleSize, + overallValidStatus, + validationChecks, + } = await this._examplesLoader.loadExamples(); this._categoryFieldExamples = examples; - this._categoryFieldValid = valid; - return { valid, examples, sampleSize }; + this._validationChecks = validationChecks; + this._overallValidStatus = overallValidStatus; + return { examples, sampleSize, overallValidStatus, validationChecks }; } public get categoryFieldExamples() { return this._categoryFieldExamples; } - public get categoryFieldValid() { - return this._categoryFieldValid; + public get validationChecks() { + return this._validationChecks; + } + + public get overallValidStatus() { + return this._overallValidStatus; } public get selectedDetectorType() { return this._detectorType; } - public set categorizationAnalyzer(analyzer: CategorizationAnalyzerType) { + public set categorizationAnalyzer(analyzer: CategorizationAnalyzer) { this._categorizationAnalyzer = analyzer; - if ( - analyzer === null || - isEqual(this._categorizationAnalyzer, this._defaultCategorizationAnalyzer) - ) { + if (isEqual(this._categorizationAnalyzer, this._defaultCategorizationAnalyzer)) { delete this._job_config.analysis_config.categorization_analyzer; } else { this._job_config.analysis_config.categorization_analyzer = analyzer; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/datafeed.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/datafeed.ts index 6c7493c5e52d3b..c0b9a4872c3c47 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/datafeed.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/datafeed.ts @@ -11,6 +11,7 @@ export type DatafeedId = string; export interface Datafeed { datafeed_id: DatafeedId; aggregations?: Aggregation; + aggs?: Aggregation; chunking_config?: ChunkingConfig; frequency?: string; indices: IndexPatternTitle[]; @@ -33,6 +34,7 @@ interface Aggregation { field: string; fixed_interval: string; }; - aggregations: Record; + aggregations?: { [key: string]: any }; + aggs?: { [key: string]: any }; }; } diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts index 90c189c9d61971..5b33aa35569809 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts @@ -623,8 +623,10 @@ export class JobCreator { } this._aggregationFields = []; - if (this._datafeed_config.aggregations?.buckets !== undefined) { - collectAggs(this._datafeed_config.aggregations.buckets, this._aggregationFields); + const buckets = + this._datafeed_config.aggregations?.buckets || this._datafeed_config.aggs?.buckets; + if (buckets !== undefined) { + collectAggs(buckets, this._aggregationFields); } } } diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts index e5b6212a4326e5..0764e276d635ea 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts @@ -325,7 +325,7 @@ export function collectAggs(o: any, aggFields: Field[]) { if (o[i] !== null && typeof o[i] === 'object') { if (i === 'aggregations' || i === 'aggs') { Object.keys(o[i]).forEach(k => { - if (k !== 'aggregations' && i !== 'aggs') { + if (k !== 'aggregations' && k !== 'aggs') { aggFields.push({ id: k, name: k, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_validator/job_validator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_validator/job_validator.ts index 976e94b377ae8b..8f6b16c407fb66 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_validator/job_validator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_validator/job_validator.ts @@ -16,7 +16,7 @@ import { JobCreator, JobCreatorType, isCategorizationJobCreator } from '../job_c import { populateValidationMessages, checkForExistingJobAndGroupIds } from './util'; import { ExistingJobsAndGroups } from '../../../../services/job_service'; import { cardinalityValidator, CardinalityValidatorResult } from './validators'; -import { CATEGORY_EXAMPLES_ERROR_LIMIT } from '../../../../../../common/constants/new_job'; +import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../common/constants/new_job'; // delay start of validation to allow the user to make changes // e.g. if they are typing in a new value, try not to validate @@ -207,7 +207,7 @@ export class JobValidator { private _runAdvancedValidation() { if (isCategorizationJobCreator(this._jobCreator)) { this._advancedValidations.categorizationFieldValid.valid = - this._jobCreator.categoryFieldValid > CATEGORY_EXAMPLES_ERROR_LIMIT; + this._jobCreator.overallValidStatus !== CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID; } } diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts index ce1ea0bdaf181c..62a4d070fec328 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts @@ -6,15 +6,12 @@ import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; import { IndexPatternTitle } from '../../../../../../common/types/kibana'; -import { Token } from '../../../../../../common/types/categories'; import { CategorizationJobCreator } from '../job_creator'; import { ml } from '../../../../services/ml_api_service'; -import { NUMBER_OF_CATEGORY_EXAMPLES } from '../../../../../../common/constants/new_job'; - -export interface CategoryExample { - text: string; - tokens: Token[]; -} +import { + NUMBER_OF_CATEGORY_EXAMPLES, + CATEGORY_EXAMPLES_VALIDATION_STATUS, +} from '../../../../../../common/constants/new_job'; export class CategorizationExamplesLoader { private _jobCreator: CategorizationJobCreator; @@ -36,20 +33,22 @@ export class CategorizationExamplesLoader { const analyzer = this._jobCreator.categorizationAnalyzer; const categorizationFieldName = this._jobCreator.categorizationFieldName; if (categorizationFieldName === null) { - return { valid: 0, examples: [], sampleSize: 0 }; + return { + examples: [], + sampleSize: 0, + overallValidStatus: CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID, + validationChecks: [], + }; } - const start = Math.floor( - this._jobCreator.start + (this._jobCreator.end - this._jobCreator.start) / 2 - ); const resp = await ml.jobs.categorizationFieldExamples( this._indexPatternTitle, this._query, NUMBER_OF_CATEGORY_EXAMPLES, categorizationFieldName, this._timeFieldName, - start, - 0, + this._jobCreator.start, + this._jobCreator.end, analyzer ); return resp; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/results_loader/index.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/results_loader/index.ts index 724c62f22e469f..e15d859f8e6c31 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/results_loader/index.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/results_loader/index.ts @@ -5,4 +5,4 @@ */ export { ResultsLoader, Results, ModelItem, Anomaly } from './results_loader'; -export { CategorizationExamplesLoader, CategoryExample } from './categorization_examples_loader'; +export { CategorizationExamplesLoader } from './categorization_examples_loader'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/examples_valid_callout.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/examples_valid_callout.tsx index 270ba99d938cdc..ac886a3aea61a7 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/examples_valid_callout.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/examples_valid_callout.tsx @@ -9,27 +9,24 @@ import { EuiCallOut, EuiSpacer, EuiCallOutProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { CategorizationAnalyzer } from '../../../../../../../services/ml_server_info'; -import { EditCategorizationAnalyzerFlyout } from '../../../common/edit_categorization_analyzer_flyout'; import { - CATEGORY_EXAMPLES_ERROR_LIMIT, - CATEGORY_EXAMPLES_WARNING_LIMIT, -} from '../../../../../../../../../common/constants/new_job'; - -type CategorizationAnalyzerType = CategorizationAnalyzer | null; + CategorizationAnalyzer, + FieldExampleCheck, +} from '../../../../../../../../../common/types/categories'; +import { EditCategorizationAnalyzerFlyout } from '../../../common/edit_categorization_analyzer_flyout'; +import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../../../../common/constants/new_job'; interface Props { - examplesValid: number; - sampleSize: number; - categorizationAnalyzer: CategorizationAnalyzerType; + validationChecks: FieldExampleCheck[]; + overallValidStatus: CATEGORY_EXAMPLES_VALIDATION_STATUS; + categorizationAnalyzer: CategorizationAnalyzer; } export const ExamplesValidCallout: FC = ({ - examplesValid, + overallValidStatus, + validationChecks, categorizationAnalyzer, - sampleSize, }) => { - const percentageText = ; const analyzerUsed = ; let color: EuiCallOutProps['color'] = 'success'; @@ -40,7 +37,7 @@ export const ExamplesValidCallout: FC = ({ } ); - if (examplesValid < CATEGORY_EXAMPLES_ERROR_LIMIT) { + if (overallValidStatus === CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID) { color = 'danger'; title = i18n.translate( 'xpack.ml.newJob.wizard.pickFieldsStep.categorizationFieldCalloutTitle.invalid', @@ -48,7 +45,7 @@ export const ExamplesValidCallout: FC = ({ defaultMessage: 'Selected category field is invalid', } ); - } else if (examplesValid < CATEGORY_EXAMPLES_WARNING_LIMIT) { + } else if (overallValidStatus === CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID) { color = 'warning'; title = i18n.translate( 'xpack.ml.newJob.wizard.pickFieldsStep.categorizationFieldCalloutTitle.possiblyInvalid', @@ -60,45 +57,24 @@ export const ExamplesValidCallout: FC = ({ return ( - {percentageText} + {validationChecks.map((v, i) => ( +
    {v.message}
    + ))} {analyzerUsed}
    ); }; -const PercentageText: FC<{ examplesValid: number; sampleSize: number }> = ({ - examplesValid, - sampleSize, -}) => ( -
    - -
    -); - -const AnalyzerUsed: FC<{ categorizationAnalyzer: CategorizationAnalyzerType }> = ({ +const AnalyzerUsed: FC<{ categorizationAnalyzer: CategorizationAnalyzer }> = ({ categorizationAnalyzer, }) => { let analyzer = ''; - if (typeof categorizationAnalyzer === null) { - return null; - } - if (typeof categorizationAnalyzer === 'string') { - analyzer = categorizationAnalyzer; - } else { - if (categorizationAnalyzer?.tokenizer !== undefined) { - analyzer = categorizationAnalyzer?.tokenizer!; - } else if (categorizationAnalyzer?.analyzer !== undefined) { - analyzer = categorizationAnalyzer?.analyzer!; - } + if (categorizationAnalyzer?.tokenizer !== undefined) { + analyzer = categorizationAnalyzer.tokenizer; + } else if (categorizationAnalyzer?.analyzer !== undefined) { + analyzer = categorizationAnalyzer.analyzer; } return ( diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/field_examples.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/field_examples.tsx index 7f9b2e43b90050..51cea179a6c0d9 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/field_examples.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/field_examples.tsx @@ -7,10 +7,10 @@ import React, { FC } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiBasicTable, EuiText } from '@elastic/eui'; -import { CategoryExample } from '../../../../../common/results_loader'; +import { CategoryFieldExample } from '../../../../../../../../../common/types/categories'; interface Props { - fieldExamples: CategoryExample[] | null; + fieldExamples: CategoryFieldExample[] | null; } const TOKEN_HIGHLIGHT_COLOR = '#b0ccf7'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/metric_selection.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/metric_selection.tsx index 52b5c61e70fe5e..411f6e898bd486 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/metric_selection.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_view/metric_selection.tsx @@ -14,7 +14,11 @@ import { CategorizationField } from '../categorization_field'; import { CategorizationDetector } from '../categorization_detector'; import { FieldExamples } from './field_examples'; import { ExamplesValidCallout } from './examples_valid_callout'; -import { CategoryExample } from '../../../../../common/results_loader'; +import { + CategoryFieldExample, + FieldExampleCheck, +} from '../../../../../../../../../common/types/categories'; +import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../../../../common/constants/new_job'; import { LoadingWrapper } from '../../../charts/loading_wrapper'; interface Props { @@ -31,9 +35,11 @@ export const CategorizationDetectors: FC = ({ setIsValid }) => { const [categorizationAnalyzerString, setCategorizationAnalyzerString] = useState( JSON.stringify(jobCreator.categorizationAnalyzer) ); - const [fieldExamples, setFieldExamples] = useState(null); - const [examplesValid, setExamplesValid] = useState(0); - const [sampleSize, setSampleSize] = useState(0); + const [fieldExamples, setFieldExamples] = useState(null); + const [overallValidStatus, setOverallValidStatus] = useState( + CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID + ); + const [validationChecks, setValidationChecks] = useState([]); const [categorizationFieldName, setCategorizationFieldName] = useState( jobCreator.categorizationFieldName @@ -73,28 +79,32 @@ export const CategorizationDetectors: FC = ({ setIsValid }) => { setLoadingData(true); try { const { - valid, examples, - sampleSize: tempSampleSize, + overallValidStatus: tempOverallValidStatus, + validationChecks: tempValidationChecks, } = await jobCreator.loadCategorizationFieldExamples(); setFieldExamples(examples); - setExamplesValid(valid); + setOverallValidStatus(tempOverallValidStatus); + setValidationChecks(tempValidationChecks); setLoadingData(false); - setSampleSize(tempSampleSize); } catch (error) { setLoadingData(false); + setFieldExamples(null); + setValidationChecks([]); + setOverallValidStatus(CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID); mlMessageBarService.notify.error(error); } } else { setFieldExamples(null); - setExamplesValid(0); + setValidationChecks([]); + setOverallValidStatus(CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID); } setIsValid(categorizationFieldName !== null); } useEffect(() => { jobCreatorUpdate(); - }, [examplesValid]); + }, [overallValidStatus]); return ( <> @@ -109,8 +119,8 @@ export const CategorizationDetectors: FC = ({ setIsValid }) => { {fieldExamples !== null && loadingData === false && ( <> diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx index 141ed5d1bbb8ff..c4a96d9e373c8d 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx @@ -77,6 +77,7 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => { const [kibanaObjects, setKibanaObjects] = useState({}); const [saveState, setSaveState] = useState(SAVE_STATE.NOT_SAVED); const [resultsUrl, setResultsUrl] = useState(''); + const [existingGroups, setExistingGroups] = useState(existingGroupIds); // #endregion const { @@ -109,6 +110,10 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => { setKibanaObjects(kibanaObjectsResult); setSaveState(SAVE_STATE.NOT_SAVED); + + // mix existing groups from the server with the groups used across all jobs in the module. + const moduleGroups = [...response.jobs.map(j => j.config.groups || [])].flat(); + setExistingGroups([...new Set([...existingGroups, ...moduleGroups])]); } catch (e) { // eslint-disable-next-line no-console console.error(e); @@ -222,6 +227,12 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => { ...jobOverrides, [job.job_id as string]: job, }); + if (job.groups !== undefined) { + // add newly added jobs to the list of existing groups + // for use when editing other jobs in the module + const groups = [...new Set([...existingGroups, ...job.groups])]; + setExistingGroups(groups); + } }; const isFormVisible = [SAVE_STATE.NOT_SAVED, SAVE_STATE.SAVING].includes(saveState); @@ -304,7 +315,7 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => { jobs={jobs} jobPrefix={jobPrefix} saveState={saveState} - existingGroupIds={existingGroupIds} + existingGroupIds={existingGroups} jobOverrides={jobOverrides} onJobOverridesChange={onJobOverridesChange} /> diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx index 633efc2856dac1..adef7055f97480 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import moment from 'moment'; import React, { FC, useEffect, useState } from 'react'; import useObservable from 'react-use/lib/useObservable'; @@ -70,7 +69,7 @@ interface ExplorerUrlStateManagerProps { const ExplorerUrlStateManager: FC = ({ jobsWithTimeRange }) => { const [appState, setAppState] = useUrlState('_a'); - const [globalState] = useUrlState('_g'); + const [globalState, setGlobalState] = useUrlState('_g'); const [lastRefresh, setLastRefresh] = useState(0); const { jobIds } = useJobSelection(jobsWithTimeRange, getDateFormatTz()); @@ -79,13 +78,37 @@ const ExplorerUrlStateManager: FC = ({ jobsWithTim useEffect(() => { if (refresh !== undefined) { setLastRefresh(refresh?.lastRefresh); - const activeBounds = timefilter.getActiveBounds(); - if (activeBounds !== undefined) { - explorerService.setBounds(activeBounds); + + if (refresh.timeRange !== undefined) { + const { start, end } = refresh.timeRange; + setGlobalState('time', { + from: start, + to: end, + }); } } }, [refresh?.lastRefresh]); + // We cannot simply infer bounds from the globalState's `time` attribute + // with `moment` since it can contain custom strings such as `now-15m`. + // So when globalState's `time` changes, we update the timefilter and use + // `timefilter.getBounds()` to update `bounds` in this component's state. + useEffect(() => { + if (globalState?.time !== undefined) { + timefilter.setTime({ + from: globalState.time.from, + to: globalState.time.to, + }); + + const timefilterBounds = timefilter.getBounds(); + // Only if both min/max bounds are valid moment times set the bounds. + // An invalid string restored from globalState might return `undefined`. + if (timefilterBounds?.min !== undefined && timefilterBounds?.max !== undefined) { + explorerService.setBounds(timefilterBounds); + } + } + }, [globalState?.time?.from, globalState?.time?.to]); + useEffect(() => { timefilter.enableTimeRangeSelector(); timefilter.enableAutoRefreshSelector(); @@ -101,19 +124,6 @@ const ExplorerUrlStateManager: FC = ({ jobsWithTim } }, []); - useEffect(() => { - if (globalState?.time !== undefined) { - timefilter.setTime({ - from: globalState.time.from, - to: globalState.time.to, - }); - explorerService.setBounds({ - min: moment(globalState.time.from), - max: moment(globalState.time.to), - }); - } - }, [globalState?.time?.from, globalState?.time?.to]); - useEffect(() => { if (jobIds.length > 0) { explorerService.updateJobSelection(jobIds); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx index f824faf7845c64..bc457f1a3fe89e 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx @@ -72,6 +72,11 @@ const PageWrapper: FC = ({ config, deps }) => { ); }; +interface AppStateZoom { + from: string; + to: string; +} + interface TimeSeriesExplorerUrlStateManager { config: any; jobsWithTimeRange: MlJobWithTimeRange[]; @@ -159,10 +164,9 @@ export const TimeSeriesExplorerUrlStateManager: FC( + appState?.mlTimeSeriesExplorer?.forecastId + ); + useEffect(() => { if ( autoZoomDuration !== undefined && @@ -221,6 +231,9 @@ export const TimeSeriesExplorerUrlStateManager: FC { @@ -231,20 +244,6 @@ export const TimeSeriesExplorerUrlStateManager: FC { // eslint-disable-next-line no-console @@ -282,6 +282,11 @@ export const TimeSeriesExplorerUrlStateManager: FC ); diff --git a/x-pack/legacy/plugins/ml/public/application/services/http_service.ts b/x-pack/legacy/plugins/ml/public/application/services/http_service.ts index 1d68ec5b886eb0..41200759b7c8a1 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/http_service.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/http_service.ts @@ -53,7 +53,10 @@ export function http(options: any) { fetch(url, payload) .then(resp => { - resp.json().then(resp.ok === true ? resolve : reject); + resp + .json() + .then(resp.ok === true ? resolve : reject) + .catch(resp.ok === true ? resolve : reject); }) .catch(resp => { reject(resp); diff --git a/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts b/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts index db9d158c0ead99..6420b60e4c8380 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts @@ -22,6 +22,12 @@ import { PartitionFieldsDefinition } from '../results_service/result_service_rx' import { annotations } from './annotations'; import { Calendar, CalendarId, UpdateCalendar } from '../../../../common/types/calendars'; import { CombinedJob, JobId } from '../../jobs/new_job/common/job_creator/configs'; +import { + CategorizationAnalyzer, + CategoryFieldExample, + FieldExampleCheck, +} from '../../../../common/types/categories'; +import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../common/constants/new_job'; // TODO This is not a complete representation of all methods of `ml.*`. // It just satisfies needs for other parts of the code area which use @@ -184,8 +190,13 @@ declare interface Ml { timeField: string | undefined, start: number, end: number, - analyzer: any - ): Promise<{ valid: number; examples: any[]; sampleSize: number }>; + analyzer: CategorizationAnalyzer + ): Promise<{ + examples: CategoryFieldExample[]; + sampleSize: number; + overallValidStatus: CATEGORY_EXAMPLES_VALIDATION_STATUS; + validationChecks: FieldExampleCheck[]; + }>; topCategories( jobId: string, count: number diff --git a/x-pack/legacy/plugins/ml/public/application/services/ml_server_info.ts b/x-pack/legacy/plugins/ml/public/application/services/ml_server_info.ts index 6bf5a7b0c97433..304778281c2f2f 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/ml_server_info.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/ml_server_info.ts @@ -5,6 +5,7 @@ */ import { ml } from './ml_api_service'; +import { CategorizationAnalyzer } from '../../../common/types/categories'; export interface MlServerDefaults { anomaly_detectors: { @@ -16,13 +17,6 @@ export interface MlServerDefaults { datafeeds: { scroll_size?: number }; } -export interface CategorizationAnalyzer { - char_filter?: any[]; - tokenizer?: string; - filter?: any[]; - analyzer?: string; -} - export interface MlServerLimits { max_model_memory_limit?: string; } diff --git a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/components/entity_control/entity_control.tsx b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/components/entity_control/entity_control.tsx index df5412e609a9c9..6727102f55a52d 100644 --- a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/components/entity_control/entity_control.tsx +++ b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/components/entity_control/entity_control.tsx @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { isEqual } from 'lodash'; import React, { Component } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; @@ -47,8 +48,8 @@ export class EntityControl extends Component void; + selectedForecastId?: string; tableInterval: string; tableSeverity: number; zoom?: { from: string; to: string }; diff --git a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js index f3d8692bfb3e97..75815f8bc48a77 100644 --- a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js @@ -94,6 +94,8 @@ function getEntityControlOptions(fieldValues) { return []; } + fieldValues.sort(); + return fieldValues.map(value => { return { label: value }; }); @@ -163,7 +165,6 @@ export class TimeSeriesExplorer extends React.Component { selectedDetectorIndex: PropTypes.number, selectedEntities: PropTypes.object, selectedForecastId: PropTypes.string, - setGlobalState: PropTypes.func.isRequired, tableInterval: PropTypes.string, tableSeverity: PropTypes.number, zoom: PropTypes.object, @@ -187,6 +188,24 @@ export class TimeSeriesExplorer extends React.Component { */ contextChart$ = new Subject(); + /** + * Returns field names that don't have a selection yet. + */ + getFieldNamesWithEmptyValues = () => { + const latestEntityControls = this.getControlsForDetector(); + return latestEntityControls + .filter(({ fieldValue }) => !fieldValue) + .map(({ fieldName }) => fieldName); + }; + + /** + * Checks if all entity control dropdowns have a selection. + */ + arePartitioningFieldsProvided = () => { + const fieldNamesWithEmptyValues = this.getFieldNamesWithEmptyValues(); + return fieldNamesWithEmptyValues.length === 0; + }; + detectorIndexChangeHandler = e => { const { appStateHandler } = this.props; const id = e.target.value; @@ -295,7 +314,17 @@ export class TimeSeriesExplorer extends React.Component { } contextChartSelected = selection => { + const zoomState = { + from: selection.from.toISOString(), + to: selection.to.toISOString(), + }; + + if (isEqual(this.props.zoom, zoomState) && this.state.focusChartData !== undefined) { + return; + } + this.contextChart$.next(selection); + this.props.appStateHandler(APP_STATE_ACTION.SET_ZOOM, zoomState); }; entityFieldValueChanged = (entity, fieldValue) => { @@ -508,27 +537,38 @@ export class TimeSeriesExplorer extends React.Component { (Array.isArray(stateUpdate.contextForecastData) && stateUpdate.contextForecastData.length > 0); stateUpdate.loading = false; + // Set zoomFrom/zoomTo attributes in scope which will result in the metric chart automatically // selecting the specified range in the context chart, and so loading that date range in the focus chart. - if (stateUpdate.contextChartData.length) { + // Only touch the zoom range if data for the context chart has been loaded and all necessary + // partition fields have a selection. + if ( + stateUpdate.contextChartData.length && + this.arePartitioningFieldsProvided() === true + ) { // Check for a zoom parameter in the appState (URL). let focusRange = calculateInitialFocusRange( zoom, stateUpdate.contextAggregationInterval, bounds ); - - if (focusRange === undefined) { + if ( + focusRange === undefined || + this.previousSelectedForecastId !== this.props.selectedForecastId + ) { focusRange = calculateDefaultFocusRange( autoZoomDuration, stateUpdate.contextAggregationInterval, stateUpdate.contextChartData, stateUpdate.contextForecastData ); + this.previousSelectedForecastId = this.props.selectedForecastId; } - stateUpdate.zoomFrom = focusRange[0]; - stateUpdate.zoomTo = focusRange[1]; + this.contextChartSelected({ + from: focusRange[0], + to: focusRange[1], + }); } this.setState(stateUpdate); @@ -880,11 +920,6 @@ export class TimeSeriesExplorer extends React.Component { ...refreshFocusData, ...tableData, }); - const zoomState = { - from: selection.from.toISOString(), - to: selection.to.toISOString(), - }; - this.props.appStateHandler(APP_STATE_ACTION.SET_ZOOM, zoomState); }) ); @@ -916,6 +951,11 @@ export class TimeSeriesExplorer extends React.Component { if (this.props.selectedForecastId !== undefined) { // Ensure the forecast data will be shown if hidden previously. this.setState({ showForecast: true }); + // Not best practice but we need the previous value for another comparison + // once all the data was loaded. + if (previousProps !== undefined) { + this.previousSelectedForecastId = previousProps.selectedForecastId; + } } } @@ -925,17 +965,15 @@ export class TimeSeriesExplorer extends React.Component { !isEqual(previousProps.lastRefresh, this.props.lastRefresh) || !isEqual(previousProps.selectedDetectorIndex, this.props.selectedDetectorIndex) || !isEqual(previousProps.selectedEntities, this.props.selectedEntities) || - !isEqual(previousProps.selectedForecastId, this.props.selectedForecastId) || - previousProps.selectedJobId !== this.props.selectedJobId || - !isEqual(previousProps.zoom, this.props.zoom) + previousProps.selectedForecastId !== this.props.selectedForecastId || + previousProps.selectedJobId !== this.props.selectedJobId ) { const fullRefresh = previousProps === undefined || !isEqual(previousProps.bounds, this.props.bounds) || - !isEqual(previousProps.lastRefresh, this.props.lastRefresh) || !isEqual(previousProps.selectedDetectorIndex, this.props.selectedDetectorIndex) || !isEqual(previousProps.selectedEntities, this.props.selectedEntities) || - !isEqual(previousProps.selectedForecastId, this.props.selectedForecastId) || + previousProps.selectedForecastId !== this.props.selectedForecastId || previousProps.selectedJobId !== this.props.selectedJobId; this.loadSingleMetricData(fullRefresh); } @@ -960,41 +998,6 @@ export class TimeSeriesExplorer extends React.Component { ) { tableControlsListener(); } - - if ( - this.props.autoZoomDuration === undefined || - this.props.selectedForecastId !== undefined || - this.state.contextAggregationInterval === undefined || - this.state.contextChartData === undefined || - this.state.contextChartData.length === 0 - ) { - return; - } - - const defaultRange = calculateDefaultFocusRange( - this.props.autoZoomDuration, - this.state.contextAggregationInterval, - this.state.contextChartData, - this.state.contextForecastData - ); - - const selection = { - from: this.state.zoomFrom, - to: this.state.zoomTo, - }; - - if ( - (selection.from.getTime() !== defaultRange[0].getTime() || - selection.to.getTime() !== defaultRange[1].getTime()) && - isNaN(Date.parse(selection.from)) === false && - isNaN(Date.parse(selection.to)) === false - ) { - const zoomState = { - from: selection.from.toISOString(), - to: selection.to.toISOString(), - }; - this.props.appStateHandler(APP_STATE_ACTION.SET_ZOOM, zoomState); - } } componentWillUnmount() { @@ -1069,12 +1072,8 @@ export class TimeSeriesExplorer extends React.Component { const selectedJob = mlJobService.getJob(selectedJobId); const entityControls = this.getControlsForDetector(); - - const fieldNamesWithEmptyValues = entityControls - .filter(({ fieldValue }) => !fieldValue) - .map(({ fieldName }) => fieldName); - - const arePartitioningFieldsProvided = fieldNamesWithEmptyValues.length === 0; + const fieldNamesWithEmptyValues = this.getFieldNamesWithEmptyValues(); + const arePartitioningFieldsProvided = this.arePartitioningFieldsProvided(); const detectorSelectOptions = getViewableDetectors(selectedJob).map(d => ({ value: d.index, @@ -1204,7 +1203,7 @@ export class TimeSeriesExplorer extends React.Component { (fullRefresh === false || loading === false) && hasResults === true && (
    - {/* Make sure ChartTooltip is inside this plain wrapping element without padding so positioning can be infered correctly. */} + {/* Make sure ChartTooltip is inside this plain wrapping element without padding so positioning can be inferred correctly. */} diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.js b/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.js index 423141a87d177a..1e7a72ee2750fc 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.js +++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/data_recognizer.js @@ -290,7 +290,6 @@ export class DataRecognizer { request ) { this.savedObjectsClient = request.getSavedObjectsClient(); - this.indexPatterns = await this.loadIndexPatterns(); // load the config from disk const moduleConfig = await this.getModule(moduleId, jobPrefix); @@ -303,7 +302,7 @@ export class DataRecognizer { this.indexPatternName = indexPatternName === undefined ? moduleConfig.defaultIndexPattern : indexPatternName; - this.indexPatternId = this.getIndexPatternId(this.indexPatternName); + this.indexPatternId = await this.getIndexPatternId(this.indexPatternName); // the module's jobs contain custom URLs which require an index patten id // but there is no corresponding index pattern, throw an error @@ -450,12 +449,17 @@ export class DataRecognizer { } // returns a id based on an index pattern name - getIndexPatternId(name) { - if (this.indexPatterns && this.indexPatterns.saved_objects) { - const ip = this.indexPatterns.saved_objects.find(i => i.attributes.title === name); + async getIndexPatternId(name) { + try { + const indexPatterns = await this.loadIndexPatterns(); + if (indexPatterns === undefined || indexPatterns.saved_objects === undefined) { + return; + } + const ip = indexPatterns.saved_objects.find(i => i.attributes.title === name); return ip !== undefined ? ip.id : undefined; - } else { - return undefined; + } catch (error) { + mlLog.warn(`Error loading index patterns, ${error}`); + return; } } diff --git a/x-pack/legacy/plugins/ml/server/models/data_visualizer/data_visualizer.js b/x-pack/legacy/plugins/ml/server/models/data_visualizer/data_visualizer.js index 7c2e3eaf07bccc..f4ee032ee2dbbe 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_visualizer/data_visualizer.js +++ b/x-pack/legacy/plugins/ml/server/models/data_visualizer/data_visualizer.js @@ -261,7 +261,7 @@ export class DataVisualizer { aggregatableFields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field, i); aggs[`${safeFieldName}_count`] = { - value_count: { field }, + filter: { exists: { field } }, }; aggs[`${safeFieldName}_cardinality`] = { cardinality: { field }, @@ -296,7 +296,7 @@ export class DataVisualizer { samplerShardSize > 0 ? _.get(aggregations, ['sample', 'doc_count'], 0) : totalCount; aggregatableFields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field, i); - const count = _.get(aggregations, [...aggsPath, `${safeFieldName}_count`, 'value'], 0); + const count = _.get(aggregations, [...aggsPath, `${safeFieldName}_count`, 'doc_count'], 0); if (count > 0) { const cardinality = _.get( aggregations, @@ -433,7 +433,12 @@ export class DataVisualizer { fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); aggs[`${safeFieldName}_field_stats`] = { - stats: { field: field.fieldName }, + filter: { exists: { field: field.fieldName } }, + aggs: { + actual_stats: { + stats: { field: field.fieldName }, + }, + }, }; aggs[`${safeFieldName}_percentiles`] = { percentiles: { @@ -484,10 +489,19 @@ export class DataVisualizer { const batchStats = []; fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); - const fieldStatsResp = _.get(aggregations, [...aggsPath, `${safeFieldName}_field_stats`], {}); + const docCount = _.get( + aggregations, + [...aggsPath, `${safeFieldName}_field_stats`, 'doc_count'], + 0 + ); + const fieldStatsResp = _.get( + aggregations, + [...aggsPath, `${safeFieldName}_field_stats`, 'actual_stats'], + {} + ); const stats = { fieldName: field.fieldName, - count: _.get(fieldStatsResp, 'count', 0), + count: docCount, min: _.get(fieldStatsResp, 'min', 0), max: _.get(fieldStatsResp, 'max', 0), avg: _.get(fieldStatsResp, 'avg', 0), @@ -632,7 +646,12 @@ export class DataVisualizer { fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); aggs[`${safeFieldName}_field_stats`] = { - stats: { field: field.fieldName }, + filter: { exists: { field: field.fieldName } }, + aggs: { + actual_stats: { + stats: { field: field.fieldName }, + }, + }, }; }); @@ -651,10 +670,19 @@ export class DataVisualizer { const batchStats = []; fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); - const fieldStatsResp = _.get(aggregations, [...aggsPath, `${safeFieldName}_field_stats`], {}); + const docCount = _.get( + aggregations, + [...aggsPath, `${safeFieldName}_field_stats`, 'doc_count'], + 0 + ); + const fieldStatsResp = _.get( + aggregations, + [...aggsPath, `${safeFieldName}_field_stats`, 'actual_stats'], + {} + ); batchStats.push({ fieldName: field.fieldName, - count: _.get(fieldStatsResp, 'count', 0), + count: docCount, earliest: _.get(fieldStatsResp, 'min', 0), latest: _.get(fieldStatsResp, 'max', 0), }); @@ -680,7 +708,7 @@ export class DataVisualizer { fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); aggs[`${safeFieldName}_value_count`] = { - value_count: { field: field.fieldName }, + filter: { exists: { field: field.fieldName } }, }; aggs[`${safeFieldName}_values`] = { terms: { @@ -707,7 +735,7 @@ export class DataVisualizer { const safeFieldName = getSafeAggregationName(field.fieldName, i); const stats = { fieldName: field.fieldName, - count: _.get(aggregations, [...aggsPath, `${safeFieldName}_value_count`, 'value'], 0), + count: _.get(aggregations, [...aggsPath, `${safeFieldName}_value_count`, 'doc_count'], 0), trueCount: 0, falseCount: 0, }; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/index.js b/x-pack/legacy/plugins/ml/server/models/job_service/index.js index 186bcbae84546f..5c0eff3112a53e 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/index.js +++ b/x-pack/legacy/plugins/ml/server/models/job_service/index.js @@ -8,7 +8,11 @@ import { datafeedsProvider } from './datafeeds'; import { jobsProvider } from './jobs'; import { groupsProvider } from './groups'; import { newJobCapsProvider } from './new_job_caps'; -import { newJobChartsProvider, categorizationExamplesProvider } from './new_job'; +import { + newJobChartsProvider, + categorizationExamplesProvider, + topCategoriesProvider, +} from './new_job'; export function jobServiceProvider(callWithRequest, request) { return { @@ -18,5 +22,6 @@ export function jobServiceProvider(callWithRequest, request) { ...newJobCapsProvider(callWithRequest, request), ...newJobChartsProvider(callWithRequest, request), ...categorizationExamplesProvider(callWithRequest, request), + ...topCategoriesProvider(callWithRequest, request), }; } diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization.ts deleted file mode 100644 index b3c70bf589cd04..00000000000000 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization.ts +++ /dev/null @@ -1,314 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { chunk } from 'lodash'; -import { ML_RESULTS_INDEX_PATTERN } from '../../../../common/constants/index_patterns'; -import { CATEGORY_EXAMPLES_SAMPLE_SIZE } from '../../../../common/constants/new_job'; -import { CategoryId, Category, Token } from '../../../../common/types/categories'; -import { callWithRequestType } from '../../../../common/types/kibana'; - -const VALID_TOKEN_COUNT = 3; -const CHUNK_SIZE = 100; - -export function categorizationExamplesProvider(callWithRequest: callWithRequestType) { - async function categorizationExamples( - indexPatternTitle: string, - query: any, - size: number, - categorizationFieldName: string, - timeField: string | undefined, - start: number, - end: number, - analyzer?: any - ) { - if (timeField !== undefined) { - const range = { - range: { - [timeField]: { - gte: start, - format: 'epoch_millis', - }, - }, - }; - - if (query.bool === undefined) { - query.bool = {}; - } - if (query.bool.filter === undefined) { - query.bool.filter = range; - } else { - if (Array.isArray(query.bool.filter)) { - query.bool.filter.push(range); - } else { - query.bool.filter.range = range; - } - } - } - - const results = await callWithRequest('search', { - index: indexPatternTitle, - size, - body: { - _source: categorizationFieldName, - query, - }, - }); - const examples: string[] = results.hits?.hits - ?.map((doc: any) => doc._source[categorizationFieldName]) - .filter((example: string | null | undefined) => example !== undefined && example !== null); - - async function loadTokens(chunkSize: number) { - const exampleChunks = chunk(examples, chunkSize); - const tokensPerChunks = await Promise.all(exampleChunks.map(c => getTokens(c, analyzer))); - const tokensPerExample = tokensPerChunks.flat(); - return examples.map((e, i) => ({ text: e, tokens: tokensPerExample[i] })); - } - try { - return loadTokens(CHUNK_SIZE); - } catch (error) { - // if an error is thrown when loading the tokens, lower the chunk size by half and try again - // the error may have been caused by too many tokens being found. - // the _analyze endpoint has a maximum of 10000 tokens. - return loadTokens(CHUNK_SIZE / 2); - } - } - - async function getTokens(examples: string[], analyzer?: any) { - const { tokens }: { tokens: Token[] } = await callWithRequest('indices.analyze', { - body: { - ...getAnalyzer(analyzer), - text: examples, - }, - }); - - const lengths = examples.map(e => e.length); - const sumLengths = lengths.map((s => (a: number) => (s += a))(0)); - - const tokensPerExample: Token[][] = examples.map(e => []); - - tokens.forEach((t, i) => { - for (let g = 0; g < sumLengths.length; g++) { - if (t.start_offset <= sumLengths[g] + g) { - const offset = g > 0 ? sumLengths[g - 1] + g : 0; - tokensPerExample[g].push({ - ...t, - start_offset: t.start_offset - offset, - end_offset: t.end_offset - offset, - }); - break; - } - } - }); - return tokensPerExample; - } - - function getAnalyzer(analyzer: any) { - if (typeof analyzer === 'object' && analyzer.tokenizer !== undefined) { - return analyzer; - } else { - return { analyzer: 'standard' }; - } - } - - async function validateCategoryExamples( - indexPatternTitle: string, - query: any, - size: number, - categorizationFieldName: string, - timeField: string | undefined, - start: number, - end: number, - analyzer?: any - ) { - const resp = await categorizationExamples( - indexPatternTitle, - query, - CATEGORY_EXAMPLES_SAMPLE_SIZE, - categorizationFieldName, - timeField, - start, - end, - analyzer - ); - - const sortedExamples = resp - .map((e, i) => ({ ...e, origIndex: i })) - .sort((a, b) => b.tokens.length - a.tokens.length); - const validExamples = sortedExamples.filter(e => e.tokens.length >= VALID_TOKEN_COUNT); - const sampleSize = sortedExamples.length; - - const multiple = Math.floor(sampleSize / size) || sampleSize; - const filteredExamples = []; - let i = 0; - while (filteredExamples.length < size && i < sortedExamples.length) { - filteredExamples.push(sortedExamples[i]); - i += multiple; - } - const examples = filteredExamples - .sort((a, b) => a.origIndex - b.origIndex) - .map(e => ({ text: e.text, tokens: e.tokens })); - - return { - sampleSize, - valid: sortedExamples.length === 0 ? 0 : validExamples.length / sortedExamples.length, - examples, - }; - } - - async function getTotalCategories(jobId: string): Promise<{ total: number }> { - const totalResp = await callWithRequest('search', { - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [ - { - term: { - job_id: jobId, - }, - }, - { - exists: { - field: 'category_id', - }, - }, - ], - }, - }, - }, - }); - return totalResp?.hits?.total?.value ?? 0; - } - - async function getTopCategoryCounts(jobId: string, numberOfCategories: number) { - const top = await callWithRequest('search', { - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [ - { - term: { - job_id: jobId, - }, - }, - { - term: { - result_type: 'model_plot', - }, - }, - { - term: { - by_field_name: 'mlcategory', - }, - }, - ], - }, - }, - aggs: { - cat_count: { - terms: { - field: 'by_field_value', - size: numberOfCategories, - }, - }, - }, - }, - }); - - const catCounts: Array<{ - id: CategoryId; - count: number; - }> = top.aggregations?.cat_count?.buckets.map((c: any) => ({ - id: c.key, - count: c.doc_count, - })); - return catCounts || []; - } - - async function getCategories( - jobId: string, - catIds: CategoryId[], - size: number - ): Promise { - const categoryFilter = catIds.length - ? { - terms: { - category_id: catIds, - }, - } - : { - exists: { - field: 'category_id', - }, - }; - const result = await callWithRequest('search', { - index: ML_RESULTS_INDEX_PATTERN, - size, - body: { - query: { - bool: { - filter: [ - { - term: { - job_id: jobId, - }, - }, - categoryFilter, - ], - }, - }, - }, - }); - - return result.hits.hits?.map((c: { _source: Category }) => c._source) || []; - } - - async function topCategories(jobId: string, numberOfCategories: number) { - const catCounts = await getTopCategoryCounts(jobId, numberOfCategories); - const categories = await getCategories( - jobId, - catCounts.map(c => c.id), - catCounts.length || numberOfCategories - ); - - const catsById = categories.reduce((p, c) => { - p[c.category_id] = c; - return p; - }, {} as { [id: number]: Category }); - - const total = await getTotalCategories(jobId); - - if (catCounts.length) { - return { - total, - categories: catCounts.map(({ id, count }) => { - return { - count, - category: catsById[id] ?? null, - }; - }), - }; - } else { - return { - total, - categories: categories.map(category => { - return { - category, - }; - }), - }; - } - } - - return { - categorizationExamples, - validateCategoryExamples, - topCategories, - }; -} diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts new file mode 100644 index 00000000000000..76473bd55db7fb --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts @@ -0,0 +1,206 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { chunk } from 'lodash'; +import { SearchResponse } from 'elasticsearch'; +import { CATEGORY_EXAMPLES_SAMPLE_SIZE } from '../../../../../common/constants/new_job'; +import { + Token, + CategorizationAnalyzer, + CategoryFieldExample, +} from '../../../../../common/types/categories'; +import { callWithRequestType } from '../../../../../common/types/kibana'; +import { ValidationResults } from './validation_results'; + +const CHUNK_SIZE = 100; + +export function categorizationExamplesProvider(callWithRequest: callWithRequestType) { + const validationResults = new ValidationResults(); + + async function categorizationExamples( + indexPatternTitle: string, + query: any, + size: number, + categorizationFieldName: string, + timeField: string | undefined, + start: number, + end: number, + analyzer: CategorizationAnalyzer + ): Promise<{ examples: CategoryFieldExample[]; error?: any }> { + if (timeField !== undefined) { + const range = { + range: { + [timeField]: { + gte: start, + lt: end, + format: 'epoch_millis', + }, + }, + }; + if (query.bool === undefined) { + query.bool = {}; + } + if (query.bool.filter === undefined) { + query.bool.filter = range; + } else { + if (Array.isArray(query.bool.filter)) { + query.bool.filter.push(range); + } else { + query.bool.filter.range = range; + } + } + } + + const results: SearchResponse<{ [id: string]: string }> = await callWithRequest('search', { + index: indexPatternTitle, + size, + body: { + _source: categorizationFieldName, + query, + sort: ['_doc'], + }, + }); + + const tempExamples = results.hits.hits.map(({ _source }) => _source[categorizationFieldName]); + + validationResults.createNullValueResult(tempExamples); + + const allExamples = tempExamples.filter( + (example: string | null | undefined) => example !== undefined && example !== null + ); + + validationResults.createMedianMessageLengthResult(allExamples); + + try { + const examplesWithTokens = await getTokens(CHUNK_SIZE, allExamples, analyzer); + return { examples: examplesWithTokens }; + } catch (err) { + // console.log('dropping to 50 chunk size'); + // if an error is thrown when loading the tokens, lower the chunk size by half and try again + // the error may have been caused by too many tokens being found. + // the _analyze endpoint has a maximum of 10000 tokens. + const halfExamples = allExamples.splice(0, Math.ceil(allExamples.length / 2)); + const halfChunkSize = CHUNK_SIZE / 2; + try { + const examplesWithTokens = await getTokens(halfChunkSize, halfExamples, analyzer); + return { examples: examplesWithTokens }; + } catch (error) { + validationResults.createTooManyTokensResult(error, halfChunkSize); + return { examples: halfExamples.map(e => ({ text: e, tokens: [] })) }; + } + } + } + + async function getTokens( + chunkSize: number, + examples: string[], + analyzer: CategorizationAnalyzer + ): Promise { + const exampleChunks = chunk(examples, chunkSize); + const tokensPerExampleChunks: Token[][][] = []; + for (const c of exampleChunks) { + tokensPerExampleChunks.push(await loadTokens(c, analyzer)); + } + const tokensPerExample = tokensPerExampleChunks.flat(); + return examples.map((e, i) => ({ text: e, tokens: tokensPerExample[i] })); + } + + async function loadTokens(examples: string[], analyzer: CategorizationAnalyzer) { + const { tokens }: { tokens: Token[] } = await callWithRequest('indices.analyze', { + body: { + ...getAnalyzer(analyzer), + text: examples, + }, + }); + + const lengths = examples.map(e => e.length); + const sumLengths = lengths.map((s => (a: number) => (s += a))(0)); + + const tokensPerExample: Token[][] = examples.map(e => []); + + tokens.forEach((t, i) => { + for (let g = 0; g < sumLengths.length; g++) { + if (t.start_offset <= sumLengths[g] + g) { + const offset = g > 0 ? sumLengths[g - 1] + g : 0; + tokensPerExample[g].push({ + ...t, + start_offset: t.start_offset - offset, + end_offset: t.end_offset - offset, + }); + break; + } + } + }); + return tokensPerExample; + } + + function getAnalyzer(analyzer: CategorizationAnalyzer) { + if (typeof analyzer === 'object' && analyzer.tokenizer !== undefined) { + return analyzer; + } else { + return { analyzer: 'standard' }; + } + } + + async function validateCategoryExamples( + indexPatternTitle: string, + query: any, + size: number, + categorizationFieldName: string, + timeField: string | undefined, + start: number, + end: number, + analyzer: CategorizationAnalyzer + ) { + const resp = await categorizationExamples( + indexPatternTitle, + query, + CATEGORY_EXAMPLES_SAMPLE_SIZE, + categorizationFieldName, + timeField, + start, + end, + analyzer + ); + + const { examples } = resp; + const sampleSize = examples.length; + validationResults.createTokenCountResult(examples, sampleSize); + + // sort examples by number of tokens, keeping track of their original order + // with an origIndex property + const sortedExamples = examples + .map((e, i) => ({ ...e, origIndex: i })) + .sort((a, b) => b.tokens.length - a.tokens.length); + + // we only want 'size' (e.g. 5) number of examples, + // so loop through the sorted examples, taking 5 at evenly + // spread intervals + const multiple = Math.floor(sampleSize / size) || sampleSize; + const filteredExamples = []; + let i = 0; + while (filteredExamples.length < size && i < sampleSize) { + filteredExamples.push(sortedExamples[i]); + i += multiple; + } + + // sort back into original order and remove origIndex property + const processedExamples = filteredExamples + .sort((a, b) => a.origIndex - b.origIndex) + .map(e => ({ text: e.text, tokens: e.tokens })); + + return { + overallValidStatus: validationResults.overallResult, + validationChecks: validationResults.results, + sampleSize, + examples: processedExamples, + }; + } + + return { + validateCategoryExamples, + }; +} diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/index.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/index.ts new file mode 100644 index 00000000000000..be32b99b5e527e --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { categorizationExamplesProvider } from './examples'; +export { topCategoriesProvider } from './top_categories'; diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts new file mode 100644 index 00000000000000..3361cc454e2b7b --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts @@ -0,0 +1,164 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SearchResponse } from 'elasticsearch'; +import { ML_RESULTS_INDEX_PATTERN } from '../../../../../common/constants/index_patterns'; +import { CategoryId, Category } from '../../../../../common/types/categories'; +import { callWithRequestType } from '../../../../../common/types/kibana'; + +export function topCategoriesProvider(callWithRequest: callWithRequestType) { + async function getTotalCategories(jobId: string): Promise<{ total: number }> { + const totalResp = await callWithRequest('search', { + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [ + { + term: { + job_id: jobId, + }, + }, + { + exists: { + field: 'category_id', + }, + }, + ], + }, + }, + }, + }); + return totalResp?.hits?.total?.value ?? 0; + } + + async function getTopCategoryCounts(jobId: string, numberOfCategories: number) { + const top: SearchResponse = await callWithRequest('search', { + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [ + { + term: { + job_id: jobId, + }, + }, + { + term: { + result_type: 'model_plot', + }, + }, + { + term: { + by_field_name: 'mlcategory', + }, + }, + ], + }, + }, + aggs: { + cat_count: { + terms: { + field: 'by_field_value', + size: numberOfCategories, + }, + }, + }, + }, + }); + + const catCounts: Array<{ + id: CategoryId; + count: number; + }> = top.aggregations?.cat_count?.buckets.map((c: any) => ({ + id: c.key, + count: c.doc_count, + })); + return catCounts || []; + } + + async function getCategories( + jobId: string, + catIds: CategoryId[], + size: number + ): Promise { + const categoryFilter = catIds.length + ? { + terms: { + category_id: catIds, + }, + } + : { + exists: { + field: 'category_id', + }, + }; + const result: SearchResponse = await callWithRequest('search', { + index: ML_RESULTS_INDEX_PATTERN, + size, + body: { + query: { + bool: { + filter: [ + { + term: { + job_id: jobId, + }, + }, + categoryFilter, + ], + }, + }, + }, + }); + + return result.hits.hits?.map((c: { _source: Category }) => c._source) || []; + } + + async function topCategories(jobId: string, numberOfCategories: number) { + const catCounts = await getTopCategoryCounts(jobId, numberOfCategories); + const categories = await getCategories( + jobId, + catCounts.map(c => c.id), + catCounts.length || numberOfCategories + ); + + const catsById = categories.reduce((p, c) => { + p[c.category_id] = c; + return p; + }, {} as { [id: number]: Category }); + + const total = await getTotalCategories(jobId); + + if (catCounts.length) { + return { + total, + categories: catCounts.map(({ id, count }) => { + return { + count, + category: catsById[id] ?? null, + }; + }), + }; + } else { + return { + total, + categories: categories.map(category => { + return { + category, + }; + }), + }; + } + } + + return { + topCategories, + }; +} diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts new file mode 100644 index 00000000000000..34e63eabb405ef --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/validation_results.ts @@ -0,0 +1,208 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { + CATEGORY_EXAMPLES_VALIDATION_STATUS, + CATEGORY_EXAMPLES_ERROR_LIMIT, + CATEGORY_EXAMPLES_WARNING_LIMIT, +} from '../../../../../common/constants/new_job'; +import { + FieldExampleCheck, + CategoryFieldExample, + VALIDATION_RESULT, +} from '../../../../../common/types/categories'; +import { getMedianStringLength } from '../../../../../common/util/string_utils'; + +const VALID_TOKEN_COUNT = 3; +const MEDIAN_LINE_LENGTH_LIMIT = 400; +const NULL_COUNT_PERCENT_LIMIT = 0.75; + +export class ValidationResults { + private _results: FieldExampleCheck[] = []; + + public get results() { + return this._results; + } + + public get overallResult() { + if (this._results.some(c => c.valid === CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID)) { + return CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID; + } + if (this._results.some(c => c.valid === CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID)) { + return CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID; + } + return CATEGORY_EXAMPLES_VALIDATION_STATUS.VALID; + } + + private _resultExists(id: VALIDATION_RESULT) { + return this._results.some(r => r.id === id); + } + + public createTokenCountResult(examples: CategoryFieldExample[], sampleSize: number) { + if (examples.length === 0) { + this.createNoExamplesResult(); + return; + } + + if (this._resultExists(VALIDATION_RESULT.INSUFFICIENT_PRIVILEGES) === true) { + // if tokenizing has failed due to insufficient privileges, don't show + // the message about token count + return; + } + + const validExamplesSize = examples.filter(e => e.tokens.length >= VALID_TOKEN_COUNT).length; + const percentValid = sampleSize === 0 ? 0 : validExamplesSize / sampleSize; + + let valid = CATEGORY_EXAMPLES_VALIDATION_STATUS.VALID; + if (percentValid < CATEGORY_EXAMPLES_ERROR_LIMIT) { + valid = CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID; + } else if (percentValid < CATEGORY_EXAMPLES_WARNING_LIMIT) { + valid = CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID; + } + + const message = i18n.translate( + 'xpack.ml.models.jobService.categorization.messages.tokenLengthValidation', + { + defaultMessage: + '{number} field {number, plural, zero {value} one {value} other {values}} analyzed, {percentage}% contain {validTokenCount} or more tokens.', + values: { + number: sampleSize, + percentage: Math.floor(percentValid * 100), + validTokenCount: VALID_TOKEN_COUNT, + }, + } + ); + + if ( + this._resultExists(VALIDATION_RESULT.TOO_MANY_TOKENS) === false && + this._resultExists(VALIDATION_RESULT.FAILED_TO_TOKENIZE) === false + ) { + this._results.unshift({ + id: VALIDATION_RESULT.TOKEN_COUNT, + valid, + message, + }); + } + } + + public createMedianMessageLengthResult(examples: string[]) { + const median = getMedianStringLength(examples); + + if (median > MEDIAN_LINE_LENGTH_LIMIT) { + this._results.push({ + id: VALIDATION_RESULT.MEDIAN_LINE_LENGTH, + valid: CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID, + message: i18n.translate( + 'xpack.ml.models.jobService.categorization.messages.medianLineLength', + { + defaultMessage: + 'The median length for the field values analyzed is over {medianLimit} characters.', + values: { medianLimit: MEDIAN_LINE_LENGTH_LIMIT }, + } + ), + }); + } + } + + public createNoExamplesResult() { + this._results.push({ + id: VALIDATION_RESULT.NO_EXAMPLES, + valid: CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID, + message: i18n.translate('xpack.ml.models.jobService.categorization.messages.noDataFound', { + defaultMessage: + 'No examples for this field could be found. Please ensure the selected date range contains data.', + }), + }); + } + + public createNullValueResult(examples: Array) { + const nullCount = examples.filter(e => e === null).length; + + if (nullCount / examples.length >= NULL_COUNT_PERCENT_LIMIT) { + this._results.push({ + id: VALIDATION_RESULT.NULL_VALUES, + valid: CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID, + message: i18n.translate('xpack.ml.models.jobService.categorization.messages.nullValues', { + defaultMessage: 'More than {percent}% of field values are null.', + values: { percent: NULL_COUNT_PERCENT_LIMIT * 100 }, + }), + }); + } + } + + public createTooManyTokensResult(error: any, sampleSize: number) { + // expecting error message: + // The number of tokens produced by calling _analyze has exceeded the allowed maximum of [10000]. + // This limit can be set by changing the [index.analyze.max_token_count] index level setting. + + if (error.statusCode === 403) { + this.createPrivilegesErrorResult(error); + return; + } + const message: string = error.message; + if (message) { + const rxp = /exceeded the allowed maximum of \[(\d+?)\]/; + const match = rxp.exec(message); + if (match?.length === 2) { + const tokenLimit = match[1]; + this._results.push({ + id: VALIDATION_RESULT.TOO_MANY_TOKENS, + valid: CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID, + message: i18n.translate( + 'xpack.ml.models.jobService.categorization.messages.tooManyTokens', + { + defaultMessage: + 'Tokenization of field value examples has failed due to more than {tokenLimit} tokens being found in a sample of {sampleSize} values.', + values: { sampleSize, tokenLimit }, + } + ), + }); + return; + } + return; + } + this.createFailureToTokenize(message); + } + + public createPrivilegesErrorResult(error: any) { + const message: string = error.message; + if (message) { + this._results.push({ + id: VALIDATION_RESULT.INSUFFICIENT_PRIVILEGES, + valid: CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID, + message: i18n.translate( + 'xpack.ml.models.jobService.categorization.messages.insufficientPrivileges', + { + defaultMessage: + 'Tokenization of field value examples could not be performed due to insufficient privileges. Field values cannot therefore be checked to see if they are appropriate for use in a categorization job.', + } + ), + }); + this._results.push({ + id: VALIDATION_RESULT.INSUFFICIENT_PRIVILEGES, + valid: CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID, + message, + }); + return; + } + } + + public createFailureToTokenize(message: string | undefined) { + this._results.push({ + id: VALIDATION_RESULT.FAILED_TO_TOKENIZE, + valid: CATEGORY_EXAMPLES_VALIDATION_STATUS.INVALID, + message: i18n.translate( + 'xpack.ml.models.jobService.categorization.messages.failureToGetTokens', + { + defaultMessage: + 'It was not possible to tokenize a sample of example field values. {message}', + values: { message: message || '' }, + } + ), + }); + } +} diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/index.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/index.ts index da23efa67d0b5c..da60a90f4bfbc1 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/index.ts +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/index.ts @@ -5,4 +5,4 @@ */ export { newJobChartsProvider } from './charts'; -export { categorizationExamplesProvider } from './categorization'; +export { categorizationExamplesProvider, topCategoriesProvider } from './categorization'; diff --git a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json b/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json index 9dcfc11575abb8..8d408ff0310c91 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json +++ b/x-pack/legacy/plugins/ml/server/models/job_validation/__tests__/mock_farequote_cardinality.json @@ -1 +1,7 @@ -{"took":0,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":86274,"max_score":0,"hits":[]},"aggregations":{"airline_cardinality":{"value":19},"airline_count":{"value":86274}}} +{ + "took": 0, + "timed_out": false, + "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, + "hits": { "total": 86274, "max_score": 0, "hits": [] }, + "aggregations": { "airline_cardinality": { "value": 19 }, "airline_count": { "doc_count": 86274 } } +} diff --git a/x-pack/legacy/plugins/monitoring/__tests__/deprecations.js b/x-pack/legacy/plugins/monitoring/__tests__/deprecations.js index aaaf3d6ad40cf1..3df93bdb24f328 100644 --- a/x-pack/legacy/plugins/monitoring/__tests__/deprecations.js +++ b/x-pack/legacy/plugins/monitoring/__tests__/deprecations.js @@ -80,4 +80,54 @@ describe('monitoring plugin deprecations', function() { expect(log.called).to.be(true); }); }); + + describe('elasticsearch.username', function() { + it('logs a warning if elasticsearch.username is set to "elastic"', () => { + const settings = { elasticsearch: { username: 'elastic' } }; + + const log = sinon.spy(); + transformDeprecations(settings, log); + expect(log.called).to.be(true); + }); + + it('does not log a warning if elasticsearch.username is set to something besides "elastic"', () => { + const settings = { elasticsearch: { username: 'otheruser' } }; + + const log = sinon.spy(); + transformDeprecations(settings, log); + expect(log.called).to.be(false); + }); + + it('does not log a warning if elasticsearch.username is unset', () => { + const settings = { elasticsearch: { username: undefined } }; + + const log = sinon.spy(); + transformDeprecations(settings, log); + expect(log.called).to.be(false); + }); + + it('logs a warning if ssl.key is set and ssl.certificate is not', () => { + const settings = { elasticsearch: { ssl: { key: '' } } }; + + const log = sinon.spy(); + transformDeprecations(settings, log); + expect(log.called).to.be(true); + }); + + it('logs a warning if ssl.certificate is set and ssl.key is not', () => { + const settings = { elasticsearch: { ssl: { certificate: '' } } }; + + const log = sinon.spy(); + transformDeprecations(settings, log); + expect(log.called).to.be(true); + }); + + it('does not log a warning if both ssl.key and ssl.certificate are set', () => { + const settings = { elasticsearch: { ssl: { key: '', certificate: '' } } }; + + const log = sinon.spy(); + transformDeprecations(settings, log); + expect(log.called).to.be(false); + }); + }); }); diff --git a/x-pack/legacy/plugins/monitoring/config.js b/x-pack/legacy/plugins/monitoring/config.js index c33b0b28e830ad..91c1ee99a0b2e4 100644 --- a/x-pack/legacy/plugins/monitoring/config.js +++ b/x-pack/legacy/plugins/monitoring/config.js @@ -83,6 +83,14 @@ export const config = Joi => { certificate: Joi.string(), key: Joi.string(), keyPassphrase: Joi.string(), + keystore: Joi.object({ + path: Joi.string(), + password: Joi.string(), + }).default(), + truststore: Joi.object({ + path: Joi.string(), + password: Joi.string(), + }).default(), alwaysPresentCertificate: Joi.boolean().default(false), }).default(), apiVersion: Joi.string().default('master'), diff --git a/x-pack/legacy/plugins/monitoring/deprecations.js b/x-pack/legacy/plugins/monitoring/deprecations.js index 13a6a58fa8752f..c3b2b70690f33b 100644 --- a/x-pack/legacy/plugins/monitoring/deprecations.js +++ b/x-pack/legacy/plugins/monitoring/deprecations.js @@ -27,5 +27,31 @@ export const deprecations = () => { ); } }, + (settings, log) => { + const fromPath = 'xpack.monitoring.elasticsearch'; + const es = get(settings, 'elasticsearch'); + if (es) { + if (es.username === 'elastic') { + log( + `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana" user instead.` + ); + } + } + }, + (settings, log) => { + const fromPath = 'xpack.monitoring.elasticsearch.ssl'; + const ssl = get(settings, 'elasticsearch.ssl'); + if (ssl) { + if (ssl.key !== undefined && ssl.certificate === undefined) { + log( + `Setting [${fromPath}.key] without [${fromPath}.certificate] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.` + ); + } else if (ssl.certificate !== undefined && ssl.key === undefined) { + log( + `Setting [${fromPath}.certificate] without [${fromPath}.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.` + ); + } + } + }, ]; }; diff --git a/x-pack/legacy/plugins/monitoring/server/es_client/__tests__/instantiate_client.js b/x-pack/legacy/plugins/monitoring/server/es_client/__tests__/instantiate_client.js index 8797f92e489bb1..6844bd5febf8ee 100644 --- a/x-pack/legacy/plugins/monitoring/server/es_client/__tests__/instantiate_client.js +++ b/x-pack/legacy/plugins/monitoring/server/es_client/__tests__/instantiate_client.js @@ -6,7 +6,7 @@ import expect from '@kbn/expect'; import sinon from 'sinon'; -import { get, noop } from 'lodash'; +import { noop } from 'lodash'; import { exposeClient, hasMonitoringCluster } from '../instantiate_client'; function getMockServerFromConnectionUrl(monitoringClusterUrl) { @@ -26,15 +26,8 @@ function getMockServerFromConnectionUrl(monitoringClusterUrl) { }, }; - const config = { - get: path => { - return get(server, path); - }, - set: noop, - }; - return { - config, + elasticsearchConfig: server.xpack.monitoring.elasticsearch, elasticsearchPlugin: { getCluster: sinon .stub() @@ -141,12 +134,12 @@ describe('Instantiate Client', () => { describe('hasMonitoringCluster', () => { it('returns true if monitoring is configured', () => { const server = getMockServerFromConnectionUrl('http://monitoring-cluster.test:9200'); // pass null for URL to create the client using prod config - expect(hasMonitoringCluster(server.config)).to.be(true); + expect(hasMonitoringCluster(server.elasticsearchConfig)).to.be(true); }); it('returns false if monitoring is not configured', () => { const server = getMockServerFromConnectionUrl(null); - expect(hasMonitoringCluster(server.config)).to.be(false); + expect(hasMonitoringCluster(server.elasticsearchConfig)).to.be(false); }); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/es_client/instantiate_client.js b/x-pack/legacy/plugins/monitoring/server/es_client/instantiate_client.js index 87a2e5349cf1b7..9aed1ac1456174 100644 --- a/x-pack/legacy/plugins/monitoring/server/es_client/instantiate_client.js +++ b/x-pack/legacy/plugins/monitoring/server/es_client/instantiate_client.js @@ -14,24 +14,21 @@ import { LOGGING_TAG } from '../../common/constants'; * Kibana itself is connected to a production cluster. */ -export function exposeClient({ config, events, log, elasticsearchPlugin }) { - const elasticsearchConfig = hasMonitoringCluster(config) - ? config.get('xpack.monitoring.elasticsearch') - : {}; +export function exposeClient({ elasticsearchConfig, events, log, elasticsearchPlugin }) { + const isMonitoringCluster = hasMonitoringCluster(elasticsearchConfig); const cluster = elasticsearchPlugin.createCluster('monitoring', { - ...elasticsearchConfig, + ...(isMonitoringCluster ? elasticsearchConfig : {}), plugins: [monitoringBulk], logQueries: Boolean(elasticsearchConfig.logQueries), }); events.on('stop', bindKey(cluster, 'close')); - const configSource = hasMonitoringCluster(config) ? 'monitoring' : 'production'; + const configSource = isMonitoringCluster ? 'monitoring' : 'production'; log([LOGGING_TAG, 'es-client'], `config sourced from: ${configSource} cluster`); } export function hasMonitoringCluster(config) { - const hosts = config.get('xpack.monitoring.elasticsearch.hosts'); - return Boolean(hosts && hosts.length); + return Boolean(config.hosts && config.hosts.length); } export const instantiateClient = once(exposeClient); diff --git a/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.test.mocks.ts b/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.test.mocks.ts new file mode 100644 index 00000000000000..42141313ceea2a --- /dev/null +++ b/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.test.mocks.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const mockReadFileSync = jest.fn(); +jest.mock('fs', () => ({ readFileSync: mockReadFileSync })); + +export const mockReadPkcs12Keystore = jest.fn(); +export const mockReadPkcs12Truststore = jest.fn(); +jest.mock('../../../../../../src/core/utils', () => ({ + readPkcs12Keystore: mockReadPkcs12Keystore, + readPkcs12Truststore: mockReadPkcs12Truststore, +})); diff --git a/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.test.ts b/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.test.ts new file mode 100644 index 00000000000000..c6f4e0fa685045 --- /dev/null +++ b/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.test.ts @@ -0,0 +1,181 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + mockReadFileSync, + mockReadPkcs12Keystore, + mockReadPkcs12Truststore, +} from './parse_elasticsearch_config.test.mocks'; + +import { parseElasticsearchConfig } from './parse_elasticsearch_config'; + +const parse = (config: any) => { + return parseElasticsearchConfig({ + get: () => config, + }); +}; + +describe('reads files', () => { + beforeEach(() => { + mockReadFileSync.mockReset(); + mockReadFileSync.mockImplementation((path: string) => `content-of-${path}`); + mockReadPkcs12Keystore.mockReset(); + mockReadPkcs12Keystore.mockImplementation((path: string) => ({ + key: `content-of-${path}.key`, + cert: `content-of-${path}.cert`, + ca: [`content-of-${path}.ca`], + })); + mockReadPkcs12Truststore.mockReset(); + mockReadPkcs12Truststore.mockImplementation((path: string) => [`content-of-${path}`]); + }); + + it('reads certificate authorities when ssl.keystore.path is specified', () => { + const configValue = parse({ ssl: { keystore: { path: 'some-path' } } }); + expect(mockReadPkcs12Keystore).toHaveBeenCalledTimes(1); + expect(configValue.ssl.certificateAuthorities).toEqual(['content-of-some-path.ca']); + }); + + it('reads certificate authorities when ssl.truststore.path is specified', () => { + const configValue = parse({ ssl: { truststore: { path: 'some-path' } } }); + expect(mockReadPkcs12Truststore).toHaveBeenCalledTimes(1); + expect(configValue.ssl.certificateAuthorities).toEqual(['content-of-some-path']); + }); + + it('reads certificate authorities when ssl.certificateAuthorities is specified', () => { + let configValue = parse({ ssl: { certificateAuthorities: 'some-path' } }); + expect(mockReadFileSync).toHaveBeenCalledTimes(1); + expect(configValue.ssl.certificateAuthorities).toEqual(['content-of-some-path']); + + mockReadFileSync.mockClear(); + configValue = parse({ ssl: { certificateAuthorities: ['some-path'] } }); + expect(mockReadFileSync).toHaveBeenCalledTimes(1); + expect(configValue.ssl.certificateAuthorities).toEqual(['content-of-some-path']); + + mockReadFileSync.mockClear(); + configValue = parse({ ssl: { certificateAuthorities: ['some-path', 'another-path'] } }); + expect(mockReadFileSync).toHaveBeenCalledTimes(2); + expect(configValue.ssl.certificateAuthorities).toEqual([ + 'content-of-some-path', + 'content-of-another-path', + ]); + }); + + it('reads certificate authorities when ssl.keystore.path, ssl.truststore.path, and ssl.certificateAuthorities are specified', () => { + const configValue = parse({ + ssl: { + keystore: { path: 'some-path' }, + truststore: { path: 'another-path' }, + certificateAuthorities: 'yet-another-path', + }, + }); + expect(mockReadPkcs12Keystore).toHaveBeenCalledTimes(1); + expect(mockReadPkcs12Truststore).toHaveBeenCalledTimes(1); + expect(mockReadFileSync).toHaveBeenCalledTimes(1); + expect(configValue.ssl.certificateAuthorities).toEqual([ + 'content-of-some-path.ca', + 'content-of-another-path', + 'content-of-yet-another-path', + ]); + }); + + it('reads a private key and certificate when ssl.keystore.path is specified', () => { + const configValue = parse({ ssl: { keystore: { path: 'some-path' } } }); + expect(mockReadPkcs12Keystore).toHaveBeenCalledTimes(1); + expect(configValue.ssl.key).toEqual('content-of-some-path.key'); + expect(configValue.ssl.certificate).toEqual('content-of-some-path.cert'); + }); + + it('reads a private key when ssl.key is specified', () => { + const configValue = parse({ ssl: { key: 'some-path' } }); + expect(mockReadFileSync).toHaveBeenCalledTimes(1); + expect(configValue.ssl.key).toEqual('content-of-some-path'); + }); + + it('reads a certificate when ssl.certificate is specified', () => { + const configValue = parse({ ssl: { certificate: 'some-path' } }); + expect(mockReadFileSync).toHaveBeenCalledTimes(1); + expect(configValue.ssl.certificate).toEqual('content-of-some-path'); + }); +}); + +describe('throws when config is invalid', () => { + beforeAll(() => { + const realFs = jest.requireActual('fs'); + mockReadFileSync.mockImplementation((path: string) => realFs.readFileSync(path)); + const utils = jest.requireActual('../../../../../../src/core/utils'); + mockReadPkcs12Keystore.mockImplementation((path: string, password?: string) => + utils.readPkcs12Keystore(path, password) + ); + mockReadPkcs12Truststore.mockImplementation((path: string, password?: string) => + utils.readPkcs12Truststore(path, password) + ); + }); + + it('throws if key is invalid', () => { + const value = { ssl: { key: '/invalid/key' } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"ENOENT: no such file or directory, open '/invalid/key'"` + ); + }); + + it('throws if certificate is invalid', () => { + const value = { ssl: { certificate: '/invalid/cert' } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"ENOENT: no such file or directory, open '/invalid/cert'"` + ); + }); + + it('throws if certificateAuthorities is invalid', () => { + const value = { ssl: { certificateAuthorities: '/invalid/ca' } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"ENOENT: no such file or directory, open '/invalid/ca'"` + ); + }); + + it('throws if keystore path is invalid', () => { + const value = { ssl: { keystore: { path: '/invalid/keystore' } } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"ENOENT: no such file or directory, open '/invalid/keystore'"` + ); + }); + + it('throws if keystore does not contain a key', () => { + mockReadPkcs12Keystore.mockReturnValueOnce({}); + const value = { ssl: { keystore: { path: 'some-path' } } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"Did not find key in Elasticsearch keystore."` + ); + }); + + it('throws if keystore does not contain a certificate', () => { + mockReadPkcs12Keystore.mockReturnValueOnce({ key: 'foo' }); + const value = { ssl: { keystore: { path: 'some-path' } } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"Did not find certificate in Elasticsearch keystore."` + ); + }); + + it('throws if truststore path is invalid', () => { + const value = { ssl: { keystore: { path: '/invalid/truststore' } } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"ENOENT: no such file or directory, open '/invalid/truststore'"` + ); + }); + + it('throws if key and keystore.path are both specified', () => { + const value = { ssl: { key: 'foo', keystore: { path: 'bar' } } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"[config validation of [xpack.monitoring.elasticsearch].ssl]: cannot use [key] when [keystore.path] is specified"` + ); + }); + + it('throws if certificate and keystore.path are both specified', () => { + const value = { ssl: { certificate: 'foo', keystore: { path: 'bar' } } }; + expect(() => parse(value)).toThrowErrorMatchingInlineSnapshot( + `"[config validation of [xpack.monitoring.elasticsearch].ssl]: cannot use [certificate] when [keystore.path] is specified"` + ); + }); +}); diff --git a/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.ts b/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.ts new file mode 100644 index 00000000000000..70e6235602b5b9 --- /dev/null +++ b/x-pack/legacy/plugins/monitoring/server/es_client/parse_elasticsearch_config.ts @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { readFileSync } from 'fs'; +import { readPkcs12Truststore, readPkcs12Keystore } from '../../../../../../src/core/utils'; + +const KEY = 'xpack.monitoring.elasticsearch'; + +/* + * Parse a config object's Elasticsearch configuration, reading any + * certificates/keys from the filesystem + * + * TODO: this code can be removed when this plugin is migrated to the Kibana Platform, + * at that point the ElasticsearchClient and ElasticsearchConfig should be used instead + */ +export const parseElasticsearchConfig = (config: any) => { + const es = config.get(KEY); + + const errorPrefix = `[config validation of [${KEY}].ssl]`; + if (es.ssl?.key && es.ssl?.keystore?.path) { + throw new Error(`${errorPrefix}: cannot use [key] when [keystore.path] is specified`); + } + if (es.ssl?.certificate && es.ssl?.keystore?.path) { + throw new Error(`${errorPrefix}: cannot use [certificate] when [keystore.path] is specified`); + } + + const { alwaysPresentCertificate, verificationMode } = es.ssl; + const { key, keyPassphrase, certificate, certificateAuthorities } = readKeyAndCerts(es); + + return { + ...es, + ssl: { + alwaysPresentCertificate, + key, + keyPassphrase, + certificate, + certificateAuthorities, + verificationMode, + }, + }; +}; + +const readKeyAndCerts = (rawConfig: any) => { + let key: string | undefined; + let keyPassphrase: string | undefined; + let certificate: string | undefined; + let certificateAuthorities: string[] | undefined; + + const addCAs = (ca: string[] | undefined) => { + if (ca && ca.length) { + certificateAuthorities = [...(certificateAuthorities || []), ...ca]; + } + }; + + if (rawConfig.ssl.keystore?.path) { + const keystore = readPkcs12Keystore( + rawConfig.ssl.keystore.path, + rawConfig.ssl.keystore.password + ); + if (!keystore.key) { + throw new Error(`Did not find key in Elasticsearch keystore.`); + } else if (!keystore.cert) { + throw new Error(`Did not find certificate in Elasticsearch keystore.`); + } + key = keystore.key; + certificate = keystore.cert; + addCAs(keystore.ca); + } else { + if (rawConfig.ssl.key) { + key = readFile(rawConfig.ssl.key); + keyPassphrase = rawConfig.ssl.keyPassphrase; + } + if (rawConfig.ssl.certificate) { + certificate = readFile(rawConfig.ssl.certificate); + } + } + + if (rawConfig.ssl.truststore?.path) { + const ca = readPkcs12Truststore( + rawConfig.ssl.truststore.path, + rawConfig.ssl.truststore.password + ); + addCAs(ca); + } + + const ca = rawConfig.ssl.certificateAuthorities; + if (ca) { + const parsed: string[] = []; + const paths = Array.isArray(ca) ? ca : [ca]; + if (paths.length > 0) { + for (const path of paths) { + parsed.push(readFile(path)); + } + addCAs(parsed); + } + } + + return { + key, + keyPassphrase, + certificate, + certificateAuthorities, + }; +}; + +const readFile = (file: string) => { + return readFileSync(file, 'utf8'); +}; diff --git a/x-pack/legacy/plugins/monitoring/server/plugin.js b/x-pack/legacy/plugins/monitoring/server/plugin.js index e26dd96dde1bf7..163bc43945be1c 100644 --- a/x-pack/legacy/plugins/monitoring/server/plugin.js +++ b/x-pack/legacy/plugins/monitoring/server/plugin.js @@ -11,6 +11,7 @@ import { instantiateClient } from './es_client/instantiate_client'; import { initMonitoringXpackInfo } from './init_monitoring_xpack_info'; import { initBulkUploader, registerCollectors } from './kibana_monitoring'; import { registerMonitoringCollection } from './telemetry_collection'; +import { parseElasticsearchConfig } from './es_client/parse_elasticsearch_config'; export class Plugin { setup(core, plugins) { @@ -36,6 +37,12 @@ export class Plugin { * fetch methods and uploads to the ES monitoring bulk endpoint */ const xpackMainPlugin = plugins.xpack_main; + + /* + * Parse the Elasticsearch config and read any certificates/keys if necessary + */ + const elasticsearchConfig = parseElasticsearchConfig(config); + xpackMainPlugin.status.once('green', async () => { // first time xpack_main turns green /* @@ -47,7 +54,7 @@ export class Plugin { await instantiateClient({ log: core.log, events: core.events, - config, + elasticsearchConfig, elasticsearchPlugin: plugins.elasticsearch, }); // Instantiate the dedicated ES client await initMonitoringXpackInfo({ diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_kibana_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_kibana_stats.js index dfcdf605ba11c0..98e0afa28fba34 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_kibana_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_kibana_stats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getUsageStats, combineStats, rollUpTotals } from '../get_kibana_stats'; +import { getUsageStats, combineStats, rollUpTotals, ensureTimeSpan } from '../get_kibana_stats'; import expect from '@kbn/expect'; describe('Get Kibana Stats', () => { @@ -542,4 +542,50 @@ describe('Get Kibana Stats', () => { expect(rollUpTotals(rollUp, addOn, 'my_field')).to.eql({ total: 4 }); }); }); + + describe('Ensure minimum time difference', () => { + it('should return start and end as is when none are provided', () => { + const { start, end } = ensureTimeSpan(undefined, undefined); + expect(start).to.be.undefined; + expect(end).to.be.undefined; + }); + + it('should return start and end as is when only end is provided', () => { + const initialEnd = '2020-01-01T00:00:00Z'; + const { start, end } = ensureTimeSpan(undefined, initialEnd); + expect(start).to.be.undefined; + expect(end).to.be.equal(initialEnd); + }); + + it('should return start and end as is because they are already 24h away', () => { + const initialStart = '2019-12-31T00:00:00Z'; + const initialEnd = '2020-01-01T00:00:00Z'; + const { start, end } = ensureTimeSpan(initialStart, initialEnd); + expect(start).to.be.equal(initialStart); + expect(end).to.be.equal(initialEnd); + }); + + it('should return start and end as is because they are already 24h+ away', () => { + const initialStart = '2019-12-31T00:00:00Z'; + const initialEnd = '2020-01-01T01:00:00Z'; + const { start, end } = ensureTimeSpan(initialStart, initialEnd); + expect(start).to.be.equal(initialStart); + expect(end).to.be.equal(initialEnd); + }); + + it('should modify start to a date 24h before end', () => { + const initialStart = '2020-01-01T00:00:00.000Z'; + const initialEnd = '2020-01-01T01:00:00.000Z'; + const { start, end } = ensureTimeSpan(initialStart, initialEnd); + expect(start).to.be.equal('2019-12-31T01:00:00.000Z'); + expect(end).to.be.equal(initialEnd); + }); + + it('should modify start to a date 24h before now', () => { + const initialStart = new Date().toISOString(); + const { start, end } = ensureTimeSpan(initialStart, undefined); + expect(start).to.not.be.equal(initialStart); + expect(end).to.be.undefined; + }); + }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.js index 57dba1796aa5ea..1e22507c5baf43 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.js @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import moment from 'moment'; import { get, isEmpty, omit } from 'lodash'; -import { KIBANA_SYSTEM_ID } from '../../common/constants'; +import { KIBANA_SYSTEM_ID, TELEMETRY_COLLECTION_INTERVAL } from '../../common/constants'; import { fetchHighLevelStats, handleHighLevelStatsResponse } from './get_high_level_stats'; export function rollUpTotals(rolledUp, addOn, field) { @@ -88,17 +89,42 @@ export function combineStats(highLevelStats, usageStats = {}) { }, {}); } +/** + * Ensure the start and end dates are, at least, TELEMETRY_COLLECTION_INTERVAL apart + * because, otherwise, we are sending telemetry with empty Kibana usage data. + * + * @param {date} [start] The start time from which to get the telemetry data + * @param {date} [end] The end time from which to get the telemetry data + */ +export function ensureTimeSpan(start, end) { + // We only care if we have a start date, because that's the limit that might make us lose the document + if (start) { + const duration = moment.duration(TELEMETRY_COLLECTION_INTERVAL, 'milliseconds'); + // If end exists, we need to ensure they are, at least, TELEMETRY_COLLECTION_INTERVAL apart. + // Otherwise start should be, at least, TELEMETRY_COLLECTION_INTERVAL apart from now + let safeStart = moment().subtract(duration); + if (end) { + safeStart = moment(end).subtract(duration); + } + if (safeStart.isBefore(start)) { + return { start: safeStart.toISOString(), end }; + } + } + return { start, end }; +} + /* * Monkey-patch the modules from get_high_level_stats and add in the * specialized usage data that comes with kibana stats (kibana_stats.usage). */ export async function getKibanaStats(server, callCluster, clusterUuids, start, end) { + const { start: safeStart, end: safeEnd } = ensureTimeSpan(start, end); const rawStats = await fetchHighLevelStats( server, callCluster, clusterUuids, - start, - end, + safeStart, + safeEnd, KIBANA_SYSTEM_ID ); const highLevelStats = handleHighLevelStatsResponse(rawStats, KIBANA_SYSTEM_ID); diff --git a/x-pack/legacy/plugins/monitoring/ui_exports.js b/x-pack/legacy/plugins/monitoring/ui_exports.js index ba659aa74f10ca..2b5ea21a2bb452 100644 --- a/x-pack/legacy/plugins/monitoring/ui_exports.js +++ b/x-pack/legacy/plugins/monitoring/ui_exports.js @@ -6,6 +6,7 @@ import { i18n } from '@kbn/i18n'; import { resolve } from 'path'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; /** * Configuration of dependency objects for the UI, which are needed for the @@ -26,6 +27,7 @@ export const getUiExports = () => ({ euiIconType: 'monitoringApp', linkToLastSubUrl: false, main: 'plugins/monitoring/monitoring', + category: DEFAULT_APP_CATEGORIES.management, }, injectDefaultVars(server) { const config = server.config(); diff --git a/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts b/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts index eac9b6a1a7f35f..5f820f460753ed 100644 --- a/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts +++ b/x-pack/legacy/plugins/reporting/common/cancellation_token.test.ts @@ -46,13 +46,4 @@ describe('Cancellation Token', () => { expect(onCancelled).toBeCalled(); }); - - it('throws an error when the callback is not a function', () => { - const cancellationToken = new CancellationToken(); - - expect(() => { - // @ts-ignore - cancellationToken.on('cool!'); - }).toThrowError('Expected callback to be a function'); - }); }); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/__tests__/execute_job.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/__tests__/execute_job.js deleted file mode 100644 index 83be303191badb..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/__tests__/execute_job.js +++ /dev/null @@ -1,1048 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import Puid from 'puid'; -import sinon from 'sinon'; -import nodeCrypto from '@elastic/node-crypto'; - -import { CancellationToken } from '../../../../common/cancellation_token'; -import { FieldFormatsService } from '../../../../../../../../src/legacy/ui/field_formats/mixin/field_formats_service'; -// Reporting uses an unconventional directory structure so the linter marks this as a violation -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { StringFormat } from '../../../../../../../../src/plugins/data/server'; - -import { executeJobFactory } from '../execute_job'; - -const delay = ms => new Promise(resolve => setTimeout(() => resolve(), ms)); - -const expectRejectedPromise = async promise => { - let error = null; - try { - await promise; - } catch (err) { - error = err; - } finally { - expect(error).to.not.be(null); - expect(error).to.be.an(Error); - } -}; - -const puid = new Puid(); -const getRandomScrollId = () => { - return puid.generate(); -}; - -describe('CSV Execute Job', function() { - const encryptionKey = 'testEncryptionKey'; - const headers = { - sid: 'test', - }; - let defaultElasticsearchResponse; - let encryptedHeaders; - - let cancellationToken; - let mockServer; - let clusterStub; - let callWithRequestStub; - let uiSettingsGetStub; - - before(async function() { - const crypto = nodeCrypto({ encryptionKey }); - encryptedHeaders = await crypto.encrypt(headers); - }); - - beforeEach(async function() { - cancellationToken = new CancellationToken(); - - defaultElasticsearchResponse = { - hits: { - hits: [], - }, - _scroll_id: 'defaultScrollId', - }; - clusterStub = { - callWithRequest: function() {}, - }; - - callWithRequestStub = sinon - .stub(clusterStub, 'callWithRequest') - .resolves(defaultElasticsearchResponse); - - const configGetStub = sinon.stub(); - uiSettingsGetStub = sinon.stub(); - uiSettingsGetStub.withArgs('csv:separator').returns(','); - uiSettingsGetStub.withArgs('csv:quoteValues').returns(true); - - mockServer = { - expose: function() {}, - fieldFormatServiceFactory: function() { - const uiConfigMock = {}; - uiConfigMock['format:defaultTypeMap'] = { - _default_: { id: 'string', params: {} }, - }; - const getConfig = key => uiConfigMock[key]; - return new FieldFormatsService([StringFormat], getConfig); - }, - plugins: { - elasticsearch: { - getCluster: function() { - return clusterStub; - }, - }, - }, - config: function() { - return { - get: configGetStub, - }; - }, - savedObjects: { - getScopedSavedObjectsClient: sinon.stub(), - }, - uiSettingsServiceFactory: sinon.stub().returns({ - get: uiSettingsGetStub, - }), - log: function() {}, - }; - mockServer - .config() - .get.withArgs('xpack.reporting.encryptionKey') - .returns(encryptionKey); - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(1024 * 1000); // 1mB - mockServer - .config() - .get.withArgs('xpack.reporting.csv.scroll') - .returns({}); - }); - - describe('calls getScopedSavedObjectsClient with request', function() { - it('containing decrypted headers', async function() { - const executeJob = executeJobFactory(mockServer); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).to.be(true); - expect( - mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].headers - ).to.be.eql(headers); - }); - - it(`containing getBasePath() returning server's basePath if the job doesn't have one`, async function() { - const serverBasePath = '/foo-server/basePath/'; - mockServer - .config() - .get.withArgs('server.basePath') - .returns(serverBasePath); - const executeJob = executeJobFactory(mockServer); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).to.be(true); - expect( - mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].getBasePath() - ).to.be.eql(serverBasePath); - }); - - it(`containing getBasePath() returning job's basePath if the job has one`, async function() { - const serverBasePath = '/foo-server/basePath/'; - mockServer - .config() - .get.withArgs('server.basePath') - .returns(serverBasePath); - const executeJob = executeJobFactory(mockServer); - const jobBasePath = 'foo-job/basePath/'; - await executeJob( - 'job789', - { - headers: encryptedHeaders, - fields: [], - searchRequest: { index: null, body: null }, - basePath: jobBasePath, - }, - cancellationToken - ); - expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).to.be(true); - expect( - mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].getBasePath() - ).to.be.eql(jobBasePath); - }); - }); - - describe('uiSettings', function() { - it('passed scoped SavedObjectsClient to uiSettingsServiceFactory', async function() { - const returnValue = Symbol(); - mockServer.savedObjects.getScopedSavedObjectsClient.returns(returnValue); - const executeJob = executeJobFactory(mockServer); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - expect(mockServer.uiSettingsServiceFactory.calledOnce).to.be(true); - expect(mockServer.uiSettingsServiceFactory.firstCall.args[0].savedObjectsClient).to.be( - returnValue - ); - }); - }); - - describe('basic Elasticsearch call behavior', function() { - it('should decrypt encrypted headers and pass to callWithRequest', async function() { - const executeJob = executeJobFactory(mockServer); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - expect(callWithRequestStub.called).to.be(true); - expect(callWithRequestStub.firstCall.args[0].headers).to.be.eql(headers); - }); - - it('should pass the index and body to execute the initial search', async function() { - const index = 'index'; - const body = { - testBody: true, - }; - - const executeJob = executeJobFactory(mockServer); - const job = { - headers: encryptedHeaders, - fields: [], - searchRequest: { - index, - body, - }, - }; - - await executeJob('job777', job, cancellationToken); - - const searchCall = callWithRequestStub.firstCall; - expect(searchCall.args[1]).to.be('search'); - expect(searchCall.args[2].index).to.be(index); - expect(searchCall.args[2].body).to.be(body); - }); - - it('should pass the scrollId from the initial search to the subsequent scroll', async function() { - const scrollId = getRandomScrollId(); - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: scrollId, - }); - callWithRequestStub.onSecondCall().resolves(defaultElasticsearchResponse); - const executeJob = executeJobFactory(mockServer); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - - const scrollCall = callWithRequestStub.secondCall; - - expect(scrollCall.args[1]).to.be('scroll'); - expect(scrollCall.args[2].scrollId).to.be(scrollId); - }); - - it('should not execute scroll if there are no hits from the search', async function() { - const executeJob = executeJobFactory(mockServer); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - - expect(callWithRequestStub.callCount).to.be(2); - - const searchCall = callWithRequestStub.firstCall; - expect(searchCall.args[1]).to.be('search'); - - const clearScrollCall = callWithRequestStub.secondCall; - expect(clearScrollCall.args[1]).to.be('clearScroll'); - }); - - it('should stop executing scroll if there are no hits', async function() { - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: 'scrollId', - }); - callWithRequestStub.onSecondCall().resolves({ - hits: { - hits: [], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - - expect(callWithRequestStub.callCount).to.be(3); - - const searchCall = callWithRequestStub.firstCall; - expect(searchCall.args[1]).to.be('search'); - - const scrollCall = callWithRequestStub.secondCall; - expect(scrollCall.args[1]).to.be('scroll'); - - const clearScroll = callWithRequestStub.thirdCall; - expect(clearScroll.args[1]).to.be('clearScroll'); - }); - - it('should call clearScroll with scrollId when there are no more hits', async function() { - const lastScrollId = getRandomScrollId(); - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: 'scrollId', - }); - - callWithRequestStub.onSecondCall().resolves({ - hits: { - hits: [], - }, - _scroll_id: lastScrollId, - }); - - const executeJob = executeJobFactory(mockServer); - await executeJob( - 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - - const lastCall = callWithRequestStub.getCall(callWithRequestStub.callCount - 1); - expect(lastCall.args[1]).to.be('clearScroll'); - expect(lastCall.args[2].scrollId).to.eql([lastScrollId]); - }); - - it('calls clearScroll when there is an error iterating the hits', async function() { - const lastScrollId = getRandomScrollId(); - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [ - { - _source: { - one: 'foo', - two: 'bar', - }, - }, - ], - }, - _scroll_id: lastScrollId, - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: undefined, - searchRequest: { index: null, body: null }, - }; - await expectRejectedPromise(executeJob('job123', jobParams, cancellationToken)); - - const lastCall = callWithRequestStub.getCall(callWithRequestStub.callCount - 1); - expect(lastCall.args[1]).to.be('clearScroll'); - expect(lastCall.args[2].scrollId).to.eql([lastScrollId]); - }); - }); - - describe('Cells with formula values', () => { - it('returns `csv_contains_formulas` when cells contain formulas', async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') - .returns(true); - callWithRequestStub.onFirstCall().returns({ - hits: { - hits: [{ _source: { one: '=SUM(A1:A2)', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - const { csv_contains_formulas: csvContainsFormulas } = await executeJob( - 'job123', - jobParams, - cancellationToken - ); - - expect(csvContainsFormulas).to.equal(true); - }); - - it('returns warnings when headings contain formulas', async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') - .returns(true); - callWithRequestStub.onFirstCall().returns({ - hits: { - hits: [{ _source: { '=SUM(A1:A2)': 'foo', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['=SUM(A1:A2)', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - const { csv_contains_formulas: csvContainsFormulas } = await executeJob( - 'job123', - jobParams, - cancellationToken - ); - - expect(csvContainsFormulas).to.equal(true); - }); - - it('returns no warnings when cells have no formulas', async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') - .returns(true); - callWithRequestStub.onFirstCall().returns({ - hits: { - hits: [{ _source: { one: 'foo', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - const { csv_contains_formulas: csvContainsFormulas } = await executeJob( - 'job123', - jobParams, - cancellationToken - ); - - expect(csvContainsFormulas).to.equal(false); - }); - - it('returns no warnings when configured not to', async () => { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.checkForFormulas') - .returns(false); - callWithRequestStub.onFirstCall().returns({ - hits: { - hits: [{ _source: { one: '=SUM(A1:A2)', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - const { csv_contains_formulas: csvContainsFormulas } = await executeJob( - 'job123', - jobParams, - cancellationToken - ); - - expect(csvContainsFormulas).to.equal(false); - }); - }); - - describe('Elasticsearch call errors', function() { - it('should reject Promise if search call errors out', async function() { - callWithRequestStub.rejects(new Error()); - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: [], - searchRequest: { index: null, body: null }, - }; - await expectRejectedPromise(executeJob('job123', jobParams, cancellationToken)); - }); - - it('should reject Promise if scroll call errors out', async function() { - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: 'scrollId', - }); - callWithRequestStub.onSecondCall().rejects(new Error()); - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: [], - searchRequest: { index: null, body: null }, - }; - await expectRejectedPromise(executeJob('job123', jobParams, cancellationToken)); - }); - }); - - describe('invalid responses', function() { - it('should reject Promise if search returns hits but no _scroll_id', async function() { - callWithRequestStub.resolves({ - hits: { - hits: [{}], - }, - _scroll_id: undefined, - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: [], - searchRequest: { index: null, body: null }, - }; - await expectRejectedPromise(executeJob('job123', jobParams, cancellationToken)); - }); - - it('should reject Promise if search returns no hits and no _scroll_id', async function() { - callWithRequestStub.resolves({ - hits: { - hits: [], - }, - _scroll_id: undefined, - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: [], - searchRequest: { index: null, body: null }, - }; - await expectRejectedPromise(executeJob('job123', jobParams, cancellationToken)); - }); - - it('should reject Promise if scroll returns hits but no _scroll_id', async function() { - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: 'scrollId', - }); - - callWithRequestStub.onSecondCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: undefined, - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: [], - searchRequest: { index: null, body: null }, - }; - await expectRejectedPromise(executeJob('job123', jobParams, cancellationToken)); - }); - - it('should reject Promise if scroll returns no hits and no _scroll_id', async function() { - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: 'scrollId', - }); - - callWithRequestStub.onSecondCall().resolves({ - hits: { - hits: [], - }, - _scroll_id: undefined, - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: [], - searchRequest: { index: null, body: null }, - }; - await expectRejectedPromise(executeJob('job123', jobParams, cancellationToken)); - }); - }); - - describe('cancellation', function() { - const scrollId = getRandomScrollId(); - - beforeEach(function() { - // We have to "re-stub" the callWithRequest stub here so that we can use the fakeFunction - // that delays the Promise resolution so we have a chance to call cancellationToken.cancel(). - // Otherwise, we get into an endless loop, and don't have a chance to call cancel - callWithRequestStub.restore(); - callWithRequestStub = sinon.stub(clusterStub, 'callWithRequest').callsFake(async function() { - await delay(1); - return { - hits: { - hits: [{}], - }, - _scroll_id: scrollId, - }; - }); - }); - - it('should stop calling Elasticsearch when cancellationToken.cancel is called', async function() { - const executeJob = executeJobFactory(mockServer); - executeJob( - 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - - await delay(250); - const callCount = callWithRequestStub.callCount; - cancellationToken.cancel(); - await delay(250); - expect(callWithRequestStub.callCount).to.be(callCount + 1); // last call is to clear the scroll - }); - - it(`shouldn't call clearScroll if it never got a scrollId`, async function() { - const executeJob = executeJobFactory(mockServer); - executeJob( - 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - cancellationToken.cancel(); - - for (let i = 0; i < callWithRequestStub.callCount; ++i) { - expect(callWithRequestStub.getCall(i).args[1]).to.not.be('clearScroll'); - } - }); - - it('should call clearScroll if it got a scrollId', async function() { - const executeJob = executeJobFactory(mockServer); - executeJob( - 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, - cancellationToken - ); - await delay(100); - cancellationToken.cancel(); - await delay(100); - - const lastCall = callWithRequestStub.getCall(callWithRequestStub.callCount - 1); - expect(lastCall.args[1]).to.be('clearScroll'); - expect(lastCall.args[2].scrollId).to.eql([scrollId]); - }); - }); - - describe('csv content', function() { - it('should write column headers to output, even if there are no results', async function() { - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - searchRequest: { index: null, body: null }, - }; - const { content } = await executeJob('job123', jobParams, cancellationToken); - expect(content).to.be(`one,two\n`); - }); - - it('should use custom uiSettings csv:separator for header', async function() { - uiSettingsGetStub.withArgs('csv:separator').returns(';'); - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - searchRequest: { index: null, body: null }, - }; - const { content } = await executeJob('job123', jobParams, cancellationToken); - expect(content).to.be(`one;two\n`); - }); - - it('should escape column headers if uiSettings csv:quoteValues is true', async function() { - uiSettingsGetStub.withArgs('csv:quoteValues').returns(true); - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one and a half', 'two', 'three-and-four', 'five & six'], - searchRequest: { index: null, body: null }, - }; - const { content } = await executeJob('job123', jobParams, cancellationToken); - expect(content).to.be(`"one and a half",two,"three-and-four","five & six"\n`); - }); - - it(`shouldn't escape column headers if uiSettings csv:quoteValues is false`, async function() { - uiSettingsGetStub.withArgs('csv:quoteValues').returns(false); - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one and a half', 'two', 'three-and-four', 'five & six'], - searchRequest: { index: null, body: null }, - }; - const { content } = await executeJob('job123', jobParams, cancellationToken); - expect(content).to.be(`one and a half,two,three-and-four,five & six\n`); - }); - - it('should write column headers to output, when there are results', async function() { - const executeJob = executeJobFactory(mockServer); - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{ one: '1', two: '2' }], - }, - _scroll_id: 'scrollId', - }); - - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - searchRequest: { index: null, body: null }, - }; - const { content } = await executeJob('job123', jobParams, cancellationToken); - const lines = content.split('\n'); - const headerLine = lines[0]; - expect(headerLine).to.be('one,two'); - }); - - it('should use comma separated values of non-nested fields from _source', async function() { - const executeJob = executeJobFactory(mockServer); - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{ _source: { one: 'foo', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - const { content } = await executeJob('job123', jobParams, cancellationToken); - const lines = content.split('\n'); - const valuesLine = lines[1]; - expect(valuesLine).to.be('foo,bar'); - }); - - it('should concatenate the hits from multiple responses', async function() { - const executeJob = executeJobFactory(mockServer); - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{ _source: { one: 'foo', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - callWithRequestStub.onSecondCall().resolves({ - hits: { - hits: [{ _source: { one: 'baz', two: 'qux' } }], - }, - _scroll_id: 'scrollId', - }); - - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - const { content } = await executeJob('job123', jobParams, cancellationToken); - const lines = content.split('\n'); - - expect(lines[1]).to.be('foo,bar'); - expect(lines[2]).to.be('baz,qux'); - }); - - it('should use field formatters to format fields', async function() { - const executeJob = executeJobFactory(mockServer); - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{ _source: { one: 'foo', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - - const jobParams = { - headers: encryptedHeaders, - 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"}}}', - }, - }, - }; - const { content } = await executeJob('job123', jobParams, cancellationToken); - const lines = content.split('\n'); - - expect(lines[1]).to.be('FOO,bar'); - }); - }); - - describe('maxSizeBytes', function() { - // The following tests use explicitly specified lengths. UTF-8 uses between one and four 8-bit bytes for each - // code-point. However, any character that can be represented by ASCII requires one-byte, so a majority of the - // tests use these 'simple' characters to make the math easier - - describe('when only the headers exceed the maxSizeBytes', function() { - let content; - let maxSizeReached; - - beforeEach(async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(1); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - searchRequest: { index: null, body: null }, - }; - - ({ content, max_size_reached: maxSizeReached } = await executeJob( - 'job123', - jobParams, - cancellationToken - )); - }); - - it('should return max_size_reached', function() { - expect(maxSizeReached).to.be(true); - }); - - it('should return empty content', function() { - expect(content).to.be(''); - }); - }); - - describe('when headers are equal to maxSizeBytes', function() { - let content; - let maxSizeReached; - - beforeEach(async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(9); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - searchRequest: { index: null, body: null }, - }; - - ({ content, max_size_reached: maxSizeReached } = await executeJob( - 'job123', - jobParams, - cancellationToken - )); - }); - - it(`shouldn't return max_size_reached`, function() { - expect(maxSizeReached).to.be(false); - }); - - it(`should return content`, function() { - expect(content).to.be('one,two\n'); - }); - }); - - describe('when the data exceeds the maxSizeBytes', function() { - let content; - let maxSizeReached; - - beforeEach(async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(9); - - callWithRequestStub.onFirstCall().returns({ - hits: { - hits: [{ _source: { one: 'foo', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - - ({ content, max_size_reached: maxSizeReached } = await executeJob( - 'job123', - jobParams, - cancellationToken - )); - }); - - it(`should return max_size_reached`, function() { - expect(maxSizeReached).to.be(true); - }); - - it(`should return the headers in the content`, function() { - expect(content).to.be('one,two\n'); - }); - }); - - describe('when headers and data equal the maxSizeBytes', function() { - let content; - let maxSizeReached; - - beforeEach(async function() { - mockServer - .config() - .get.withArgs('xpack.reporting.csv.maxSizeBytes') - .returns(18); - - callWithRequestStub.onFirstCall().returns({ - hits: { - hits: [{ _source: { one: 'foo', two: 'bar' } }], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - - ({ content, max_size_reached: maxSizeReached } = await executeJob( - 'job123', - jobParams, - cancellationToken - )); - }); - - it(`shouldn't return max_size_reached`, async function() { - expect(maxSizeReached).to.be(false); - }); - - it('should return headers and data in content', function() { - expect(content).to.be('one,two\nfoo,bar\n'); - }); - }); - }); - - describe('scroll settings', function() { - it('passes scroll duration to initial search call', async function() { - const scrollDuration = 'test'; - mockServer - .config() - .get.withArgs('xpack.reporting.csv.scroll') - .returns({ duration: scrollDuration }); - - callWithRequestStub.onFirstCall().returns({ - hits: { - hits: [{}], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - - await executeJob('job123', jobParams, cancellationToken); - - const searchCall = callWithRequestStub.firstCall; - expect(searchCall.args[1]).to.be('search'); - expect(searchCall.args[2].scroll).to.be(scrollDuration); - }); - - it('passes scroll size to initial search call', async function() { - const scrollSize = 100; - mockServer - .config() - .get.withArgs('xpack.reporting.csv.scroll') - .returns({ size: scrollSize }); - - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - - await executeJob('job123', jobParams, cancellationToken); - - const searchCall = callWithRequestStub.firstCall; - expect(searchCall.args[1]).to.be('search'); - expect(searchCall.args[2].size).to.be(scrollSize); - }); - - it('passes scroll duration to subsequent scroll call', async function() { - const scrollDuration = 'test'; - mockServer - .config() - .get.withArgs('xpack.reporting.csv.scroll') - .returns({ duration: scrollDuration }); - - callWithRequestStub.onFirstCall().resolves({ - hits: { - hits: [{}], - }, - _scroll_id: 'scrollId', - }); - - const executeJob = executeJobFactory(mockServer); - const jobParams = { - headers: encryptedHeaders, - fields: ['one', 'two'], - conflictedTypesFields: [], - searchRequest: { index: null, body: null }, - }; - - await executeJob('job123', jobParams, cancellationToken); - - const scrollCall = callWithRequestStub.secondCall; - expect(scrollCall.args[1]).to.be('scroll'); - expect(scrollCall.args[2].scroll).to.be(scrollDuration); - }); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js new file mode 100644 index 00000000000000..1abc923d340e60 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js @@ -0,0 +1,1064 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import Puid from 'puid'; +import sinon from 'sinon'; +import nodeCrypto from '@elastic/node-crypto'; +import { CancellationToken } from '../../../common/cancellation_token'; +import { fieldFormats } from '../../../../../../../src/plugins/data/server'; +import { LevelLogger } from '../../../server/lib/level_logger'; +import { executeJobFactory } from './execute_job'; + +const delay = ms => new Promise(resolve => setTimeout(() => resolve(), ms)); + +const puid = new Puid(); +const getRandomScrollId = () => { + return puid.generate(); +}; + +describe('CSV Execute Job', function() { + const encryptionKey = 'testEncryptionKey'; + const headers = { + sid: 'test', + }; + const mockLogger = new LevelLogger({ + get: () => ({ + debug: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }), + }); + let defaultElasticsearchResponse; + let encryptedHeaders; + + let cancellationToken; + let mockServer; + let clusterStub; + let callWithRequestStub; + let uiSettingsGetStub; + + beforeAll(async function() { + const crypto = nodeCrypto({ encryptionKey }); + encryptedHeaders = await crypto.encrypt(headers); + }); + + beforeEach(async function() { + cancellationToken = new CancellationToken(); + + defaultElasticsearchResponse = { + hits: { + hits: [], + }, + _scroll_id: 'defaultScrollId', + }; + clusterStub = { + callWithRequest: function() {}, + }; + + callWithRequestStub = sinon + .stub(clusterStub, 'callWithRequest') + .resolves(defaultElasticsearchResponse); + + const configGetStub = sinon.stub(); + uiSettingsGetStub = sinon.stub(); + uiSettingsGetStub.withArgs('csv:separator').returns(','); + uiSettingsGetStub.withArgs('csv:quoteValues').returns(true); + + mockServer = { + expose: function() {}, + fieldFormatServiceFactory: function() { + const uiConfigMock = {}; + uiConfigMock['format:defaultTypeMap'] = { + _default_: { id: 'string', params: {} }, + }; + + const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry(); + + fieldFormatsRegistry.init(key => uiConfigMock[key], {}, [fieldFormats.StringFormat]); + + return fieldFormatsRegistry; + }, + plugins: { + elasticsearch: { + getCluster: function() { + return clusterStub; + }, + }, + }, + config: function() { + return { + get: configGetStub, + }; + }, + savedObjects: { + getScopedSavedObjectsClient: sinon.stub(), + }, + uiSettingsServiceFactory: sinon.stub().returns({ + get: uiSettingsGetStub, + }), + log: function() {}, + }; + mockServer + .config() + .get.withArgs('xpack.reporting.encryptionKey') + .returns(encryptionKey); + mockServer + .config() + .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .returns(1024 * 1000); // 1mB + mockServer + .config() + .get.withArgs('xpack.reporting.csv.scroll') + .returns({}); + }); + + describe('calls getScopedSavedObjectsClient with request', function() { + it('containing decrypted headers', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + await executeJob( + 'job456', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).toBe(true); + expect(mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].headers).toEqual( + headers + ); + }); + + it(`containing getBasePath() returning server's basePath if the job doesn't have one`, async function() { + const serverBasePath = '/foo-server/basePath/'; + mockServer + .config() + .get.withArgs('server.basePath') + .returns(serverBasePath); + const executeJob = executeJobFactory(mockServer, mockLogger); + await executeJob( + 'job456', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).toBe(true); + expect( + mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].getBasePath() + ).toEqual(serverBasePath); + }); + + it(`containing getBasePath() returning job's basePath if the job has one`, async function() { + const serverBasePath = '/foo-server/basePath/'; + mockServer + .config() + .get.withArgs('server.basePath') + .returns(serverBasePath); + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobBasePath = 'foo-job/basePath/'; + await executeJob( + 'job789', + { + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + basePath: jobBasePath, + }, + cancellationToken + ); + expect(mockServer.savedObjects.getScopedSavedObjectsClient.calledOnce).toBe(true); + expect( + mockServer.savedObjects.getScopedSavedObjectsClient.firstCall.args[0].getBasePath() + ).toEqual(jobBasePath); + }); + }); + + describe('uiSettings', function() { + it('passed scoped SavedObjectsClient to uiSettingsServiceFactory', async function() { + const returnValue = Symbol(); + mockServer.savedObjects.getScopedSavedObjectsClient.returns(returnValue); + const executeJob = executeJobFactory(mockServer, mockLogger); + await executeJob( + 'job456', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + expect(mockServer.uiSettingsServiceFactory.calledOnce).toBe(true); + expect(mockServer.uiSettingsServiceFactory.firstCall.args[0].savedObjectsClient).toBe( + returnValue + ); + }); + }); + + describe('basic Elasticsearch call behavior', function() { + it('should decrypt encrypted headers and pass to callWithRequest', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + await executeJob( + 'job456', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + expect(callWithRequestStub.called).toBe(true); + expect(callWithRequestStub.firstCall.args[0].headers).toEqual(headers); + }); + + it('should pass the index and body to execute the initial search', async function() { + const index = 'index'; + const body = { + testBody: true, + }; + + const executeJob = executeJobFactory(mockServer, mockLogger); + const job = { + headers: encryptedHeaders, + fields: [], + searchRequest: { + index, + body, + }, + }; + + await executeJob('job777', job, cancellationToken); + + const searchCall = callWithRequestStub.firstCall; + expect(searchCall.args[1]).toBe('search'); + expect(searchCall.args[2].index).toBe(index); + expect(searchCall.args[2].body).toBe(body); + }); + + it('should pass the scrollId from the initial search to the subsequent scroll', async function() { + const scrollId = getRandomScrollId(); + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: scrollId, + }); + callWithRequestStub.onSecondCall().resolves(defaultElasticsearchResponse); + const executeJob = executeJobFactory(mockServer, mockLogger); + await executeJob( + 'job456', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + + const scrollCall = callWithRequestStub.secondCall; + + expect(scrollCall.args[1]).toBe('scroll'); + expect(scrollCall.args[2].scrollId).toBe(scrollId); + }); + + it('should not execute scroll if there are no hits from the search', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + await executeJob( + 'job456', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + + expect(callWithRequestStub.callCount).toBe(2); + + const searchCall = callWithRequestStub.firstCall; + expect(searchCall.args[1]).toBe('search'); + + const clearScrollCall = callWithRequestStub.secondCall; + expect(clearScrollCall.args[1]).toBe('clearScroll'); + }); + + it('should stop executing scroll if there are no hits', async function() { + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: 'scrollId', + }); + callWithRequestStub.onSecondCall().resolves({ + hits: { + hits: [], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + await executeJob( + 'job456', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + + expect(callWithRequestStub.callCount).toBe(3); + + const searchCall = callWithRequestStub.firstCall; + expect(searchCall.args[1]).toBe('search'); + + const scrollCall = callWithRequestStub.secondCall; + expect(scrollCall.args[1]).toBe('scroll'); + + const clearScroll = callWithRequestStub.thirdCall; + expect(clearScroll.args[1]).toBe('clearScroll'); + }); + + it('should call clearScroll with scrollId when there are no more hits', async function() { + const lastScrollId = getRandomScrollId(); + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: 'scrollId', + }); + + callWithRequestStub.onSecondCall().resolves({ + hits: { + hits: [], + }, + _scroll_id: lastScrollId, + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + await executeJob( + 'job456', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + + const lastCall = callWithRequestStub.getCall(callWithRequestStub.callCount - 1); + expect(lastCall.args[1]).toBe('clearScroll'); + expect(lastCall.args[2].scrollId).toEqual([lastScrollId]); + }); + + it('calls clearScroll when there is an error iterating the hits', async function() { + const lastScrollId = getRandomScrollId(); + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [ + { + _source: { + one: 'foo', + two: 'bar', + }, + }, + ], + }, + _scroll_id: lastScrollId, + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: undefined, + searchRequest: { index: null, body: null }, + }; + await expect( + executeJob('job123', jobParams, cancellationToken) + ).rejects.toMatchInlineSnapshot(`[TypeError: Cannot read property 'indexOf' of undefined]`); + + const lastCall = callWithRequestStub.getCall(callWithRequestStub.callCount - 1); + expect(lastCall.args[1]).toBe('clearScroll'); + expect(lastCall.args[2].scrollId).toEqual([lastScrollId]); + }); + }); + + describe('Cells with formula values', () => { + it('returns `csv_contains_formulas` when cells contain formulas', async function() { + mockServer + .config() + .get.withArgs('xpack.reporting.csv.checkForFormulas') + .returns(true); + callWithRequestStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: '=SUM(A1:A2)', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + const { csv_contains_formulas: csvContainsFormulas } = await executeJob( + 'job123', + jobParams, + cancellationToken + ); + + expect(csvContainsFormulas).toEqual(true); + }); + + it('returns warnings when headings contain formulas', async function() { + mockServer + .config() + .get.withArgs('xpack.reporting.csv.checkForFormulas') + .returns(true); + callWithRequestStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { '=SUM(A1:A2)': 'foo', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['=SUM(A1:A2)', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + const { csv_contains_formulas: csvContainsFormulas } = await executeJob( + 'job123', + jobParams, + cancellationToken + ); + + expect(csvContainsFormulas).toEqual(true); + }); + + it('returns no warnings when cells have no formulas', async function() { + mockServer + .config() + .get.withArgs('xpack.reporting.csv.checkForFormulas') + .returns(true); + callWithRequestStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: 'foo', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + const { csv_contains_formulas: csvContainsFormulas } = await executeJob( + 'job123', + jobParams, + cancellationToken + ); + + expect(csvContainsFormulas).toEqual(false); + }); + + it('returns no warnings when configured not to', async () => { + mockServer + .config() + .get.withArgs('xpack.reporting.csv.checkForFormulas') + .returns(false); + callWithRequestStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: '=SUM(A1:A2)', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + const { csv_contains_formulas: csvContainsFormulas } = await executeJob( + 'job123', + jobParams, + cancellationToken + ); + + expect(csvContainsFormulas).toEqual(false); + }); + }); + + describe('Elasticsearch call errors', function() { + it('should reject Promise if search call errors out', async function() { + callWithRequestStub.rejects(new Error()); + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }; + await expect( + executeJob('job123', jobParams, cancellationToken) + ).rejects.toMatchInlineSnapshot(`[Error]`); + }); + + it('should reject Promise if scroll call errors out', async function() { + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: 'scrollId', + }); + callWithRequestStub.onSecondCall().rejects(new Error()); + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }; + await expect( + executeJob('job123', jobParams, cancellationToken) + ).rejects.toMatchInlineSnapshot(`[Error]`); + }); + }); + + describe('invalid responses', function() { + it('should reject Promise if search returns hits but no _scroll_id', async function() { + callWithRequestStub.resolves({ + hits: { + hits: [{}], + }, + _scroll_id: undefined, + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }; + await expect( + executeJob('job123', jobParams, cancellationToken) + ).rejects.toMatchInlineSnapshot( + `[Error: Expected _scroll_id in the following Elasticsearch response: {"hits":{"hits":[{}]}}]` + ); + }); + + it('should reject Promise if search returns no hits and no _scroll_id', async function() { + callWithRequestStub.resolves({ + hits: { + hits: [], + }, + _scroll_id: undefined, + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }; + await expect( + executeJob('job123', jobParams, cancellationToken) + ).rejects.toMatchInlineSnapshot( + `[Error: Expected _scroll_id in the following Elasticsearch response: {"hits":{"hits":[]}}]` + ); + }); + + it('should reject Promise if scroll returns hits but no _scroll_id', async function() { + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: 'scrollId', + }); + + callWithRequestStub.onSecondCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: undefined, + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }; + await expect( + executeJob('job123', jobParams, cancellationToken) + ).rejects.toMatchInlineSnapshot( + `[Error: Expected _scroll_id in the following Elasticsearch response: {"hits":{"hits":[{}]}}]` + ); + }); + + it('should reject Promise if scroll returns no hits and no _scroll_id', async function() { + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: 'scrollId', + }); + + callWithRequestStub.onSecondCall().resolves({ + hits: { + hits: [], + }, + _scroll_id: undefined, + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }; + await expect( + executeJob('job123', jobParams, cancellationToken) + ).rejects.toMatchInlineSnapshot( + `[Error: Expected _scroll_id in the following Elasticsearch response: {"hits":{"hits":[]}}]` + ); + }); + }); + + describe('cancellation', function() { + const scrollId = getRandomScrollId(); + + beforeEach(function() { + // We have to "re-stub" the callWithRequest stub here so that we can use the fakeFunction + // that delays the Promise resolution so we have a chance to call cancellationToken.cancel(). + // Otherwise, we get into an endless loop, and don't have a chance to call cancel + callWithRequestStub.restore(); + callWithRequestStub = sinon.stub(clusterStub, 'callWithRequest').callsFake(async function() { + await delay(1); + return { + hits: { + hits: [{}], + }, + _scroll_id: scrollId, + }; + }); + }); + + it('should stop calling Elasticsearch when cancellationToken.cancel is called', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + executeJob( + 'job345', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + + await delay(250); + const callCount = callWithRequestStub.callCount; + cancellationToken.cancel(); + await delay(250); + expect(callWithRequestStub.callCount).toBe(callCount + 1); // last call is to clear the scroll + }); + + it(`shouldn't call clearScroll if it never got a scrollId`, async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + executeJob( + 'job345', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + cancellationToken.cancel(); + + for (let i = 0; i < callWithRequestStub.callCount; ++i) { + expect(callWithRequestStub.getCall(i).args[1]).to.not.be('clearScroll'); + } + }); + + it('should call clearScroll if it got a scrollId', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + executeJob( + 'job345', + { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + cancellationToken + ); + await delay(100); + cancellationToken.cancel(); + await delay(100); + + const lastCall = callWithRequestStub.getCall(callWithRequestStub.callCount - 1); + expect(lastCall.args[1]).toBe('clearScroll'); + expect(lastCall.args[2].scrollId).toEqual([scrollId]); + }); + }); + + describe('csv content', function() { + it('should write column headers to output, even if there are no results', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + expect(content).toBe(`one,two\n`); + }); + + it('should use custom uiSettings csv:separator for header', async function() { + uiSettingsGetStub.withArgs('csv:separator').returns(';'); + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + expect(content).toBe(`one;two\n`); + }); + + it('should escape column headers if uiSettings csv:quoteValues is true', async function() { + uiSettingsGetStub.withArgs('csv:quoteValues').returns(true); + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one and a half', 'two', 'three-and-four', 'five & six'], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + expect(content).toBe(`"one and a half",two,"three-and-four","five & six"\n`); + }); + + it(`shouldn't escape column headers if uiSettings csv:quoteValues is false`, async function() { + uiSettingsGetStub.withArgs('csv:quoteValues').returns(false); + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one and a half', 'two', 'three-and-four', 'five & six'], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + expect(content).toBe(`one and a half,two,three-and-four,five & six\n`); + }); + + it('should write column headers to output, when there are results', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{ one: '1', two: '2' }], + }, + _scroll_id: 'scrollId', + }); + + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + const lines = content.split('\n'); + const headerLine = lines[0]; + expect(headerLine).toBe('one,two'); + }); + + it('should use comma separated values of non-nested fields from _source', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{ _source: { one: 'foo', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + const lines = content.split('\n'); + const valuesLine = lines[1]; + expect(valuesLine).toBe('foo,bar'); + }); + + it('should concatenate the hits from multiple responses', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{ _source: { one: 'foo', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + callWithRequestStub.onSecondCall().resolves({ + hits: { + hits: [{ _source: { one: 'baz', two: 'qux' } }], + }, + _scroll_id: 'scrollId', + }); + + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + const lines = content.split('\n'); + + expect(lines[1]).toBe('foo,bar'); + expect(lines[2]).toBe('baz,qux'); + }); + + it('should use field formatters to format fields', async function() { + const executeJob = executeJobFactory(mockServer, mockLogger); + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{ _source: { one: 'foo', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const jobParams = { + headers: encryptedHeaders, + 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"}}}', + }, + }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + const lines = content.split('\n'); + + expect(lines[1]).toBe('FOO,bar'); + }); + }); + + describe('maxSizeBytes', function() { + // The following tests use explicitly specified lengths. UTF-8 uses between one and four 8-bit bytes for each + // code-point. However, any character that can be represented by ASCII requires one-byte, so a majority of the + // tests use these 'simple' characters to make the math easier + + describe('when only the headers exceed the maxSizeBytes', function() { + let content; + let maxSizeReached; + + beforeEach(async function() { + mockServer + .config() + .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .returns(1); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + searchRequest: { index: null, body: null }, + }; + + ({ content, max_size_reached: maxSizeReached } = await executeJob( + 'job123', + jobParams, + cancellationToken + )); + }); + + it('should return max_size_reached', function() { + expect(maxSizeReached).toBe(true); + }); + + it('should return empty content', function() { + expect(content).toBe(''); + }); + }); + + describe('when headers are equal to maxSizeBytes', function() { + let content; + let maxSizeReached; + + beforeEach(async function() { + mockServer + .config() + .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .returns(9); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + searchRequest: { index: null, body: null }, + }; + + ({ content, max_size_reached: maxSizeReached } = await executeJob( + 'job123', + jobParams, + cancellationToken + )); + }); + + it(`shouldn't return max_size_reached`, function() { + expect(maxSizeReached).toBe(false); + }); + + it(`should return content`, function() { + expect(content).toBe('one,two\n'); + }); + }); + + describe('when the data exceeds the maxSizeBytes', function() { + let content; + let maxSizeReached; + + beforeEach(async function() { + mockServer + .config() + .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .returns(9); + + callWithRequestStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: 'foo', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + + ({ content, max_size_reached: maxSizeReached } = await executeJob( + 'job123', + jobParams, + cancellationToken + )); + }); + + it(`should return max_size_reached`, function() { + expect(maxSizeReached).toBe(true); + }); + + it(`should return the headers in the content`, function() { + expect(content).toBe('one,two\n'); + }); + }); + + describe('when headers and data equal the maxSizeBytes', function() { + let content; + let maxSizeReached; + + beforeEach(async function() { + mockServer + .config() + .get.withArgs('xpack.reporting.csv.maxSizeBytes') + .returns(18); + + callWithRequestStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: 'foo', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + + ({ content, max_size_reached: maxSizeReached } = await executeJob( + 'job123', + jobParams, + cancellationToken + )); + }); + + it(`shouldn't return max_size_reached`, async function() { + expect(maxSizeReached).toBe(false); + }); + + it('should return headers and data in content', function() { + expect(content).toBe('one,two\nfoo,bar\n'); + }); + }); + }); + + describe('scroll settings', function() { + it('passes scroll duration to initial search call', async function() { + const scrollDuration = 'test'; + mockServer + .config() + .get.withArgs('xpack.reporting.csv.scroll') + .returns({ duration: scrollDuration }); + + callWithRequestStub.onFirstCall().returns({ + hits: { + hits: [{}], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + + await executeJob('job123', jobParams, cancellationToken); + + const searchCall = callWithRequestStub.firstCall; + expect(searchCall.args[1]).toBe('search'); + expect(searchCall.args[2].scroll).toBe(scrollDuration); + }); + + it('passes scroll size to initial search call', async function() { + const scrollSize = 100; + mockServer + .config() + .get.withArgs('xpack.reporting.csv.scroll') + .returns({ size: scrollSize }); + + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + + await executeJob('job123', jobParams, cancellationToken); + + const searchCall = callWithRequestStub.firstCall; + expect(searchCall.args[1]).toBe('search'); + expect(searchCall.args[2].size).toBe(scrollSize); + }); + + it('passes scroll duration to subsequent scroll call', async function() { + const scrollDuration = 'test'; + mockServer + .config() + .get.withArgs('xpack.reporting.csv.scroll') + .returns({ duration: scrollDuration }); + + callWithRequestStub.onFirstCall().resolves({ + hits: { + hits: [{}], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = executeJobFactory(mockServer, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + + await executeJob('job123', jobParams, cancellationToken); + + const scrollCall = callWithRequestStub.secondCall; + expect(scrollCall.args[1]).toBe('scroll'); + expect(scrollCall.args[2].scroll).toBe(scrollDuration); + }); + }); +}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index ae603d93245a32..fe64fdc96d9043 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -5,22 +5,21 @@ */ import { i18n } from '@kbn/i18n'; -import { ExecuteJobFactory, ESQueueWorkerExecuteFn, ServerFacade } from '../../../types'; -import { CSV_JOB_TYPE, PLUGIN_ID } from '../../../common/constants'; -import { cryptoFactory, LevelLogger } from '../../../server/lib'; +import { KibanaRequest } from '../../../../../../../src/core/server'; +import { CSV_JOB_TYPE } from '../../../common/constants'; +import { cryptoFactory } from '../../../server/lib'; +import { ESQueueWorkerExecuteFn, ExecuteJobFactory, Logger, ServerFacade } from '../../../types'; import { JobDocPayloadDiscoverCsv } from '../types'; -// @ts-ignore untyped module TODO -import { createGenerateCsv } from './lib/generate_csv'; -// @ts-ignore untyped module TODO import { fieldFormatMapFactory } from './lib/field_format_map'; +import { createGenerateCsv } from './lib/generate_csv'; export const executeJobFactory: ExecuteJobFactory> = function executeJobFactoryFn(server: ServerFacade) { +>> = function executeJobFactoryFn(server: ServerFacade, parentLogger: Logger) { const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); const crypto = cryptoFactory(server); const config = server.config(); - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, CSV_JOB_TYPE, 'execute-job']); + const logger = parentLogger.clone([CSV_JOB_TYPE, 'execute-job']); const serverBasePath = config.get('server.basePath'); return async function executeJob( @@ -79,7 +78,9 @@ export const executeJobFactory: ExecuteJobFactory configMock[key]; - const testValue = '4000'; - - const fieldFormats = new FieldFormatsService([BytesFormat, NumberFormat], getConfig); - - const formatMap = fieldFormatMapFactory(indexPatternSavedObject, fieldFormats); - - it('should build field format map with entry per index pattern 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); - }); - - it('should create custom FieldFormat for fields with configured field formatter', function() { - expect(formatMap.get('field1').convert(testValue)).to.be('3.9KB'); - }); - - it('should create default FieldFormat for fields with no field formatter', function() { - expect(formatMap.get('field2').convert(testValue)).to.be('4,000'); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js deleted file mode 100644 index 2169c7cab12362..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js +++ /dev/null @@ -1,150 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { createFlattenHit } from '../flatten_hit'; - -describe('flattenHit', function() { - let flattenHit; - let hit; - let metaFields; - - beforeEach(function() { - const fields = [ - 'tags.text', - 'tags.label', - 'message', - 'geo.coordinates', - 'geo.dest', - 'geo.src', - 'bytes', - '@timestamp', - 'team', - 'team.name', - 'team.role', - 'user', - 'user.name', - 'user.id', - 'delta', - ]; - - const conflictedFieldTypes = ['user', 'user.id']; - - metaFields = []; - - flattenHit = createFlattenHit(fields, metaFields, conflictedFieldTypes); - - hit = { - _source: { - message: 'Hello World', - geo: { - coordinates: { lat: 33.45, lon: 112.0667 }, - dest: 'US', - src: 'IN', - }, - bytes: 10039103, - '@timestamp': new Date().toString(), - tags: [ - { text: 'foo', label: ['FOO1', 'FOO2'] }, - { text: 'bar', label: 'BAR' }, - ], - groups: ['loners'], - noMapping: true, - team: [ - { name: 'foo', role: 'leader' }, - { name: 'bar', role: 'follower' }, - { name: 'baz', role: 'party boy' }, - ], - user: { name: 'smith', id: 123 }, - }, - fields: { - delta: [42], - random: [0.12345], - }, - }; - }); - - it('flattens keys as far down as the mapping goes', function() { - const flat = flattenHit(hit); - - expect(flat).to.have.property('geo.coordinates', hit._source.geo.coordinates); - expect(flat).to.not.have.property('geo.coordinates.lat'); - expect(flat).to.not.have.property('geo.coordinates.lon'); - expect(flat).to.have.property('geo.dest', 'US'); - expect(flat).to.have.property('geo.src', 'IN'); - expect(flat).to.have.property('@timestamp', hit._source['@timestamp']); - expect(flat).to.have.property('message', 'Hello World'); - expect(flat).to.have.property('bytes', 10039103); - }); - - it('flattens keys not in the mapping', function() { - const flat = flattenHit(hit); - - expect(flat).to.have.property('noMapping', true); - expect(flat).to.have.property('groups'); - expect(flat.groups).to.eql(['loners']); - }); - - it('flattens conflicting types in the mapping', function() { - const flat = flattenHit(hit); - - expect(flat).to.not.have.property('user'); - expect(flat).to.have.property('user.name', hit._source.user.name); - expect(flat).to.have.property('user.id', hit._source.user.id); - }); - - it('should preserve objects in arrays', function() { - const flat = flattenHit(hit); - - expect(flat).to.have.property('tags', hit._source.tags); - }); - - it('does not enter into nested fields', function() { - const flat = flattenHit(hit); - - expect(flat).to.have.property('team', hit._source.team); - expect(flat).to.not.have.property('team.name'); - expect(flat).to.not.have.property('team.role'); - expect(flat).to.not.have.property('team[0]'); - expect(flat).to.not.have.property('team.0'); - }); - - it('unwraps script fields', function() { - const flat = flattenHit(hit); - - expect(flat).to.have.property('delta', 42); - }); - - it('assumes that all fields are "computed fields"', function() { - const flat = flattenHit(hit); - - expect(flat).to.have.property('random', 0.12345); - }); - - describe('metaFields', function() { - beforeEach(function() { - metaFields.push('_metaKey'); - }); - - it('ignores fields that start with an _ and are not in the metaFields', function() { - hit.fields._notMetaKey = [100]; - const flat = flattenHit(hit); - expect(flat).to.not.have.property('_notMetaKey'); - }); - - it('includes underscore-prefixed keys that are in the metaFields', function() { - hit.fields._metaKey = [100]; - const flat = flattenHit(hit); - expect(flat).to.have.property('_metaKey', 100); - }); - - it('handles fields that are not arrays, like _timestamp', function() { - hit.fields._metaKey = 20000; - const flat = flattenHit(hit); - expect(flat).to.have.property('_metaKey', 20000); - }); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js deleted file mode 100644 index 7401109ae80301..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js +++ /dev/null @@ -1,87 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { createFormatCsvValues } from '../format_csv_values'; - -describe('formatCsvValues', function() { - const separator = ','; - const fields = ['foo', 'bar']; - const mockEscapeValue = val => val; - describe('with _source as one of the fields', function() { - const formatsMap = new Map(); - const formatCsvValues = createFormatCsvValues( - mockEscapeValue, - separator, - ['foo', '_source'], - formatsMap - ); - it('should return full _source for _source field', function() { - const values = { - foo: 'baz', - }; - expect(formatCsvValues(values)).to.be('baz,{"foo":"baz"}'); - }); - }); - describe('without field formats', function() { - const formatsMap = new Map(); - const formatCsvValues = createFormatCsvValues(mockEscapeValue, separator, fields, formatsMap); - - it('should use the specified separator', function() { - expect(formatCsvValues({})).to.be(separator); - }); - - it('should replace null and undefined with empty strings', function() { - const values = { - foo: undefined, - bar: null, - }; - expect(formatCsvValues(values)).to.be(','); - }); - - it('should JSON.stringify objects', function() { - const values = { - foo: { - baz: 'qux', - }, - }; - expect(formatCsvValues(values)).to.be('{"baz":"qux"},'); - }); - - it('should concatenate strings', function() { - const values = { - foo: 'baz', - bar: 'qux', - }; - expect(formatCsvValues(values)).to.be('baz,qux'); - }); - }); - - describe('with field formats', function() { - const mockFieldFormat = { - convert: val => String(val).toUpperCase(), - }; - const formatsMap = new Map(); - formatsMap.set('bar', mockFieldFormat); - const formatCsvValues = createFormatCsvValues(mockEscapeValue, separator, fields, formatsMap); - - it('should replace null and undefined with empty strings', function() { - const values = { - foo: undefined, - bar: null, - }; - expect(formatCsvValues(values)).to.be(','); - }); - - it('should format value with appropriate FieldFormat', function() { - const values = { - foo: 'baz', - bar: 'qux', - }; - expect(formatCsvValues(values)).to.be('baz,QUX'); - }); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts deleted file mode 100644 index 20e373a4168af9..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts +++ /dev/null @@ -1,136 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import { CancellationToken } from '../../../../../common/cancellation_token'; -import { Logger, ScrollConfig } from '../../../../../types'; -import { createHitIterator } from '../hit_iterator'; - -const mockLogger = { - error: new Function(), - debug: new Function(), - warning: new Function(), -} as Logger; -const debugLogStub = sinon.stub(mockLogger, 'debug'); -const warnLogStub = sinon.stub(mockLogger, 'warning'); -const errorLogStub = sinon.stub(mockLogger, 'error'); -const mockCallEndpoint = sinon.stub(); -const mockSearchRequest = {}; -const mockConfig: ScrollConfig = { duration: '2s', size: 123 }; -let realCancellationToken = new CancellationToken(); -let isCancelledStub: sinon.SinonStub<[], boolean>; - -describe('hitIterator', function() { - beforeEach(() => { - debugLogStub.resetHistory(); - warnLogStub.resetHistory(); - errorLogStub.resetHistory(); - mockCallEndpoint.resetHistory(); - mockCallEndpoint.resetBehavior(); - mockCallEndpoint.resolves({ _scroll_id: '123blah', hits: { hits: ['you found me'] } }); - mockCallEndpoint.onCall(11).resolves({ _scroll_id: '123blah', hits: {} }); - - isCancelledStub = sinon.stub(realCancellationToken, 'isCancelled'); - isCancelledStub.returns(false); - }); - - afterEach(() => { - realCancellationToken = new CancellationToken(); - }); - - it('iterates hits', async () => { - // Begin - const hitIterator = createHitIterator(mockLogger); - const iterator = hitIterator( - mockConfig, - mockCallEndpoint, - mockSearchRequest, - realCancellationToken - ); - - while (true) { - const { done: iterationDone, value: hit } = await iterator.next(); - if (iterationDone) { - break; - } - expect(hit).to.be('you found me'); - } - - expect(mockCallEndpoint.callCount).to.be(13); - expect(debugLogStub.callCount).to.be(13); - expect(warnLogStub.callCount).to.be(0); - expect(errorLogStub.callCount).to.be(0); - }); - - it('stops searches after cancellation', async () => { - // Setup - isCancelledStub.onFirstCall().returns(false); - isCancelledStub.returns(true); - - // Begin - const hitIterator = createHitIterator(mockLogger); - const iterator = hitIterator( - mockConfig, - mockCallEndpoint, - mockSearchRequest, - realCancellationToken - ); - - while (true) { - const { done: iterationDone, value: hit } = await iterator.next(); - if (iterationDone) { - break; - } - expect(hit).to.be('you found me'); - } - - expect(mockCallEndpoint.callCount).to.be(3); - expect(debugLogStub.callCount).to.be(3); - expect(warnLogStub.callCount).to.be(1); - expect(errorLogStub.callCount).to.be(0); - - expect(warnLogStub.firstCall.lastArg).to.be( - 'Any remaining scrolling searches have been cancelled by the cancellation token.' - ); - }); - - it('handles time out', async () => { - // Setup - mockCallEndpoint.onCall(2).resolves({ status: 404 }); - - // Begin - const hitIterator = createHitIterator(mockLogger); - const iterator = hitIterator( - mockConfig, - mockCallEndpoint, - mockSearchRequest, - realCancellationToken - ); - - let errorThrown = false; - try { - while (true) { - const { done: iterationDone, value: hit } = await iterator.next(); - if (iterationDone) { - break; - } - expect(hit).to.be('you found me'); - } - } catch (err) { - expect(err).to.eql( - new Error('Expected _scroll_id in the following Elasticsearch response: {"status":404}') - ); - errorThrown = true; - } - - expect(mockCallEndpoint.callCount).to.be(4); - expect(debugLogStub.callCount).to.be(4); - expect(warnLogStub.callCount).to.be(0); - expect(errorLogStub.callCount).to.be(1); - expect(errorThrown).to.be(true); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js deleted file mode 100644 index ddc4299ebcb455..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { MaxSizeStringBuilder } from '../max_size_string_builder'; - -describe('MaxSizeStringBuilder', function() { - describe('tryAppend', function() { - it(`should return true if appended string is under maxSize`, function() { - const builder = new MaxSizeStringBuilder(100); - const result = builder.tryAppend('aa'); - expect(result).to.be(true); - }); - - it(`should return false if appended string is over the maxSize`, function() { - const builder = new MaxSizeStringBuilder(1); - const result = builder.tryAppend('aa'); - expect(result).to.be(false); - }); - - it(`should return true then false if second appended string puts total size over the maxSize`, function() { - const builder = new MaxSizeStringBuilder(1); - expect(builder.tryAppend('a')).to.be(true); - expect(builder.tryAppend('a')).to.be(false); - }); - }); - - describe('getBuffer', function() { - it(`should return an empty string when we don't call tryAppend`, function() { - const builder = new MaxSizeStringBuilder(100); - expect(builder.getString()).to.be(''); - }); - - it('should return equivalent string if tryAppend called once and less than maxSize', function() { - const str = 'foo'; - const builder = new MaxSizeStringBuilder(100); - builder.tryAppend(str); - expect(builder.getString()).to.be(str); - }); - - it('should return equivalent string if tryAppend called multiple times and total size less than maxSize', function() { - const strs = ['foo', 'bar', 'baz']; - const builder = new MaxSizeStringBuilder(100); - strs.forEach(str => builder.tryAppend(str)); - expect(builder.getString()).to.be(strs.join('')); - }); - - it('should return empty string if tryAppend called one time with size greater than maxSize', function() { - const str = 'aa'; // each a is one byte - const builder = new MaxSizeStringBuilder(1); - builder.tryAppend(str); - expect(builder.getString()).to.be(''); - }); - - it('should return partial string if tryAppend called multiple times with total size greater than maxSize', function() { - const str = 'a'; // each a is one byte - const builder = new MaxSizeStringBuilder(1); - builder.tryAppend(str); - builder.tryAppend(str); - expect(builder.getString()).to.be('a'); - }); - }); - - describe('getSizeInBytes', function() { - it(`should return 0 when no strings have been appended`, function() { - const builder = new MaxSizeStringBuilder(100); - expect(builder.getSizeInBytes()).to.be(0); - }); - - it(`should the size in bytes`, function() { - const builder = new MaxSizeStringBuilder(100); - const stringValue = 'foobar'; - builder.tryAppend(stringValue); - expect(builder.getSizeInBytes()).to.be(stringValue.length); - }); - }); -}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.test.ts index 31f5a91e5a57b4..972ca1777bd731 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.test.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import { checkIfRowsHaveFormulas } from './check_cells_for_formulas'; const formulaValues = ['=', '+', '-', '@']; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.js deleted file mode 100644 index 4031191c2f8123..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.js +++ /dev/null @@ -1,17 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -const nonAlphaNumRE = /[^a-zA-Z0-9]/; -const allDoubleQuoteRE = /"/g; - -export function createEscapeValue(quoteValues) { - return function escapeValue(val) { - if (quoteValues && nonAlphaNumRE.test(val)) { - return `"${val.replace(allDoubleQuoteRE, '""')}"`; - } - return val; - }; -} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts new file mode 100644 index 00000000000000..64b021a2aeea84 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { createEscapeValue } from './escape_value'; + +describe('escapeValue', function() { + describe('quoteValues is true', function() { + let escapeValue: (val: string) => string; + beforeEach(function() { + escapeValue = createEscapeValue(true); + }); + + it('should escape value with spaces', function() { + expect(escapeValue('baz qux')).to.be('"baz qux"'); + }); + + it('should escape values with hyphens', function() { + expect(escapeValue('baz-qux')).to.be('"baz-qux"'); + }); + + it('should not escape small integers', function() { + expect(escapeValue((1).toString())).to.be('1'); + }); + + it('should not escape small whole numbers', function() { + expect(escapeValue((1.0).toString())).to.be('1'); + }); + + it('should escape decimal numbers', function() { + expect(escapeValue((1.1).toString())).to.be('"1.1"'); + }); + + it('should not comma-separate large integers', function() { + expect(escapeValue((1000000).toString())).to.be('1000000'); + }); + + it('should treat booleans like strings', function() { + expect(escapeValue(true.toString())).to.be('true'); + }); + }); + + describe('quoteValues is false', function() { + let escapeValue: (val: string) => string; + beforeEach(function() { + escapeValue = createEscapeValue(false); + }); + + it('should return the value unescaped', function() { + const value = '"foo, bar & baz-qux"'; + expect(escapeValue(value)).to.be(value); + }); + }); +}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts new file mode 100644 index 00000000000000..563de563350e9e --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { RawValue } from './types'; + +const nonAlphaNumRE = /[^a-zA-Z0-9]/; +const allDoubleQuoteRE = /"/g; + +export function createEscapeValue(quoteValues: boolean): (val: RawValue) => string { + return function escapeValue(val: RawValue) { + if (val && typeof val === 'string') { + if (quoteValues && nonAlphaNumRE.test(val)) { + return `"${val.replace(allDoubleQuoteRE, '""')}"`; + } + } + + return val == null ? '' : val.toString(); + }; +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.js deleted file mode 100644 index 17b7361ca07b0c..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.js +++ /dev/null @@ -1,40 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import _ from 'lodash'; - -/** - * Create a map of FieldFormat instances for index pattern fields - * - * @param {Object} indexPatternSavedObject - * @param {FieldFormatsService} fieldFormats - * @return {Map} key: field name, value: FieldFormat instance - */ -export function fieldFormatMapFactory(indexPatternSavedObject, fieldFormats) { - const formatsMap = new Map(); - - //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 = fieldFormatMap[fieldName]; - - if (!_.isEmpty(formatConfig)) { - formatsMap.set(fieldName, fieldFormats.getInstance(formatConfig)); - } - }); - } - - //Add default FieldFormat instances for all other fields - const indexFields = JSON.parse(_.get(indexPatternSavedObject, 'attributes.fields', '[]')); - indexFields.forEach(field => { - if (!formatsMap.has(field.name)) { - formatsMap.set(field.name, fieldFormats.getDefaultInstance(field.type)); - } - }); - - return formatsMap; -} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.test.ts new file mode 100644 index 00000000000000..d1fa44773972f9 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.test.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; + +import { fieldFormats } from '../../../../../../../../src/plugins/data/server'; +import { fieldFormatMapFactory } from './field_format_map'; + +type ConfigValue = { number: { id: string; params: {} } } | string; + +describe('field format map', function() { + const indexPatternSavedObject = { + id: 'logstash-*', + type: 'index-pattern', + version: 'abc', + attributes: { + title: 'logstash-*', + timeFieldName: '@timestamp', + notExpandable: true, + fields: '[{"name":"field1","type":"number"}, {"name":"field2","type":"number"}]', + fieldFormatMap: '{"field1":{"id":"bytes","params":{"pattern":"0,0.[0]b"}}}', + }, + }; + const configMock: Record = {}; + configMock['format:defaultTypeMap'] = { + number: { id: 'number', params: {} }, + }; + configMock['format:number:defaultPattern'] = '0,0.[000]'; + const getConfig = ((key: string) => configMock[key]) as fieldFormats.GetConfigFn; + const testValue = '4000'; + + const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry(); + fieldFormatsRegistry.init(getConfig, {}, [fieldFormats.BytesFormat, fieldFormats.NumberFormat]); + + const formatMap = fieldFormatMapFactory(indexPatternSavedObject, fieldFormatsRegistry); + + it('should build field format map with entry per index pattern 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); + }); + + it('should create custom FieldFormat for fields with configured field formatter', function() { + expect(formatMap.get('field1').convert(testValue)).to.be('3.9KB'); + }); + + it('should create default FieldFormat for fields with no field formatter', function() { + expect(formatMap.get('field2').convert(testValue)).to.be('4,000'); + }); +}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.ts new file mode 100644 index 00000000000000..dba97b508f93e0 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/field_format_map.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { fieldFormats } from '../../../../../../../../src/plugins/data/server'; + +interface IndexPatternSavedObject { + attributes: { + fieldFormatMap: string; + }; + id: string; + type: string; + version: string; +} + +/** + * Create a map of FieldFormat instances for index pattern fields + * + * @param {Object} indexPatternSavedObject + * @param {FieldFormatsService} fieldFormats + * @return {Map} key: field name, value: FieldFormat instance + */ +export function fieldFormatMapFactory( + indexPatternSavedObject: IndexPatternSavedObject, + fieldFormatsRegistry: fieldFormats.FieldFormatsRegistry +) { + const formatsMap = new Map(); + + // 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: fieldFormats.IFieldFormatConfig = fieldFormatMap[fieldName]; + + if (!_.isEmpty(formatConfig)) { + formatsMap.set( + fieldName, + fieldFormatsRegistry.getInstance(formatConfig.id, formatConfig.params) + ); + } + }); + } + + // Add default FieldFormat instances for all other fields + const indexFields = JSON.parse(_.get(indexPatternSavedObject, 'attributes.fields', '[]')); + indexFields.forEach((field: any) => { + if (!formatsMap.has(field.name)) { + formatsMap.set(field.name, fieldFormatsRegistry.getDefaultInstance(field.type)); + } + }); + + return formatsMap; +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.js deleted file mode 100644 index b1387a3ef310c5..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import _ from 'lodash'; - -// TODO this logic should be re-used with Discover -export function createFlattenHit(fields, metaFields, conflictedTypesFields) { - const flattenSource = (flat, obj, keyPrefix) => { - keyPrefix = keyPrefix ? keyPrefix + '.' : ''; - _.forOwn(obj, (val, key) => { - key = keyPrefix + key; - - const hasValidMapping = fields.indexOf(key) >= 0 && conflictedTypesFields.indexOf(key) === -1; - const isValue = !_.isPlainObject(val); - - if (hasValidMapping || isValue) { - if (!flat[key]) { - flat[key] = val; - } else if (_.isArray(flat[key])) { - flat[key].push(val); - } else { - flat[key] = [flat[key], val]; - } - return; - } - - flattenSource(flat, val, key); - }); - }; - - const flattenMetaFields = (flat, hit) => { - _.each(metaFields, meta => { - if (meta === '_source') return; - flat[meta] = hit[meta]; - }); - }; - - const flattenFields = (flat, hitFields) => { - _.forOwn(hitFields, (val, key) => { - if (key[0] === '_' && !_.contains(metaFields, key)) return; - flat[key] = _.isArray(val) && val.length === 1 ? val[0] : val; - }); - }; - - return function flattenHit(hit) { - const flat = {}; - flattenSource(flat, hit._source); - flattenMetaFields(flat, hit); - flattenFields(flat, hit.fields); - return flat; - }; -} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.test.ts new file mode 100644 index 00000000000000..1e06e78357399c --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.test.ts @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { createFlattenHit } from './flatten_hit'; + +type Hit = Record; + +describe('flattenHit', function() { + let flattenHit: (hit: Hit) => Record; + let hit: Hit; + let metaFields: string[]; + + beforeEach(function() { + const fields = [ + 'tags.text', + 'tags.label', + 'message', + 'geo.coordinates', + 'geo.dest', + 'geo.src', + 'bytes', + '@timestamp', + 'team', + 'team.name', + 'team.role', + 'user', + 'user.name', + 'user.id', + 'delta', + ]; + + const conflictedFieldTypes = ['user', 'user.id']; + + metaFields = []; + + flattenHit = createFlattenHit(fields, metaFields, conflictedFieldTypes); + + hit = { + _source: { + message: 'Hello World', + geo: { + coordinates: { lat: 33.45, lon: 112.0667 }, + dest: 'US', + src: 'IN', + }, + bytes: 10039103, + '@timestamp': new Date().toString(), + tags: [ + { text: 'foo', label: ['FOO1', 'FOO2'] }, + { text: 'bar', label: 'BAR' }, + ], + groups: ['loners'], + noMapping: true, + team: [ + { name: 'foo', role: 'leader' }, + { name: 'bar', role: 'follower' }, + { name: 'baz', role: 'party boy' }, + ], + user: { name: 'smith', id: 123 }, + }, + fields: { + delta: [42], + random: [0.12345], + }, + }; + }); + + it('flattens keys as far down as the mapping goes', function() { + const flat = flattenHit(hit); + + expect(flat).to.have.property('geo.coordinates', hit._source.geo.coordinates); + expect(flat).to.not.have.property('geo.coordinates.lat'); + expect(flat).to.not.have.property('geo.coordinates.lon'); + expect(flat).to.have.property('geo.dest', 'US'); + expect(flat).to.have.property('geo.src', 'IN'); + expect(flat).to.have.property('@timestamp', hit._source['@timestamp']); + expect(flat).to.have.property('message', 'Hello World'); + expect(flat).to.have.property('bytes', 10039103); + }); + + it('flattens keys not in the mapping', function() { + const flat = flattenHit(hit); + + expect(flat).to.have.property('noMapping', true); + expect(flat).to.have.property('groups'); + expect(flat.groups).to.eql(['loners']); + }); + + it('flattens conflicting types in the mapping', function() { + const flat = flattenHit(hit); + + expect(flat).to.not.have.property('user'); + expect(flat).to.have.property('user.name', hit._source.user.name); + expect(flat).to.have.property('user.id', hit._source.user.id); + }); + + it('should preserve objects in arrays', function() { + const flat = flattenHit(hit); + + expect(flat).to.have.property('tags', hit._source.tags); + }); + + it('does not enter into nested fields', function() { + const flat = flattenHit(hit); + + expect(flat).to.have.property('team', hit._source.team); + expect(flat).to.not.have.property('team.name'); + expect(flat).to.not.have.property('team.role'); + expect(flat).to.not.have.property('team[0]'); + expect(flat).to.not.have.property('team.0'); + }); + + it('unwraps script fields', function() { + const flat = flattenHit(hit); + + expect(flat).to.have.property('delta', 42); + }); + + it('assumes that all fields are "computed fields"', function() { + const flat = flattenHit(hit); + + expect(flat).to.have.property('random', 0.12345); + }); + + describe('metaFields', function() { + beforeEach(function() { + metaFields.push('_metaKey'); + }); + + it('ignores fields that start with an _ and are not in the metaFields', function() { + hit.fields._notMetaKey = [100]; + const flat = flattenHit(hit); + expect(flat).to.not.have.property('_notMetaKey'); + }); + + it('includes underscore-prefixed keys that are in the metaFields', function() { + hit.fields._metaKey = [100]; + const flat = flattenHit(hit); + expect(flat).to.have.property('_metaKey', 100); + }); + + it('handles fields that are not arrays, like _timestamp', function() { + hit.fields._metaKey = 20000; + const flat = flattenHit(hit); + expect(flat).to.have.property('_metaKey', 20000); + }); + }); +}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.ts new file mode 100644 index 00000000000000..328d49a27911c7 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/flatten_hit.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; + +type Hit = Record; +type FlattenHitFn = (hit: Hit) => Record; +type FlatHits = Record; + +// TODO this logic should be re-used with Discover +export function createFlattenHit( + fields: string[], + metaFields: string[], + conflictedTypesFields: string[] +): FlattenHitFn { + const flattenSource = (flat: FlatHits, obj: object, keyPrefix = '') => { + keyPrefix = keyPrefix ? keyPrefix + '.' : ''; + _.forOwn(obj, (val, key) => { + key = keyPrefix + key; + + const hasValidMapping = fields.indexOf(key) >= 0 && conflictedTypesFields.indexOf(key) === -1; + const isValue = !_.isPlainObject(val); + + if (hasValidMapping || isValue) { + if (!flat[key]) { + flat[key] = val; + } else if (_.isArray(flat[key])) { + flat[key].push(val); + } else { + flat[key] = [flat[key], val]; + } + return; + } + + flattenSource(flat, val, key); + }); + }; + + const flattenMetaFields = (flat: Hit, hit: Hit) => { + _.each(metaFields, meta => { + if (meta === '_source') return; + flat[meta] = hit[meta]; + }); + }; + + const flattenFields = (flat: FlatHits, hitFields: string[]) => { + _.forOwn(hitFields, (val, key) => { + if (key) { + if (key[0] === '_' && !_.contains(metaFields, key)) return; + flat[key] = _.isArray(val) && val.length === 1 ? val[0] : val; + } + }); + }; + + return function flattenHit(hit) { + const flat = {}; + flattenSource(flat, hit._source); + flattenMetaFields(flat, hit); + flattenFields(flat, hit.fields); + return flat; + }; +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.js deleted file mode 100644 index 9083e8ce04f88c..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.js +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { isObject, isNull, isUndefined } from 'lodash'; - -export function createFormatCsvValues(escapeValue, separator, fields, formatsMap) { - return function formatCsvValues(values) { - return fields - .map(field => { - let value; - if (field === '_source') { - value = values; - } else { - value = values[field]; - } - if (isNull(value) || isUndefined(value)) { - return ''; - } - - let formattedValue = value; - if (formatsMap.has(field)) { - const formatter = formatsMap.get(field); - formattedValue = formatter.convert(value); - } - - return formattedValue; - }) - .map(value => (isObject(value) ? JSON.stringify(value) : value)) - .map(value => value.toString()) - .map(escapeValue) - .join(separator); - }; -} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.test.ts new file mode 100644 index 00000000000000..b38bad11794717 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.test.ts @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { createFormatCsvValues } from './format_csv_values'; + +describe('formatCsvValues', function() { + const separator = ','; + const fields = ['foo', 'bar']; + const mockEscapeValue = (value: any, index: number, array: any[]) => value || ''; + describe('with _source as one of the fields', function() { + const formatsMap = new Map(); + const formatCsvValues = createFormatCsvValues( + mockEscapeValue, + separator, + ['foo', '_source'], + formatsMap + ); + it('should return full _source for _source field', function() { + const values = { + foo: 'baz', + }; + expect(formatCsvValues(values)).to.be('baz,{"foo":"baz"}'); + }); + }); + describe('without field formats', function() { + const formatsMap = new Map(); + const formatCsvValues = createFormatCsvValues(mockEscapeValue, separator, fields, formatsMap); + + it('should use the specified separator', function() { + expect(formatCsvValues({})).to.be(separator); + }); + + it('should replace null and undefined with empty strings', function() { + const values = { + foo: undefined, + bar: null, + }; + expect(formatCsvValues(values)).to.be(','); + }); + + it('should JSON.stringify objects', function() { + const values = { + foo: { + baz: 'qux', + }, + }; + expect(formatCsvValues(values)).to.be('{"baz":"qux"},'); + }); + + it('should concatenate strings', function() { + const values = { + foo: 'baz', + bar: 'qux', + }; + expect(formatCsvValues(values)).to.be('baz,qux'); + }); + }); + + describe('with field formats', function() { + const mockFieldFormat = { + convert: (val: string) => String(val).toUpperCase(), + }; + const formatsMap = new Map(); + formatsMap.set('bar', mockFieldFormat); + const formatCsvValues = createFormatCsvValues(mockEscapeValue, separator, fields, formatsMap); + + it('should replace null and undefined with empty strings', function() { + const values = { + foo: undefined, + bar: null, + }; + expect(formatCsvValues(values)).to.be(','); + }); + + it('should format value with appropriate FieldFormat', function() { + const values = { + foo: 'baz', + bar: 'qux', + }; + expect(formatCsvValues(values)).to.be('baz,QUX'); + }); + }); +}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.ts new file mode 100644 index 00000000000000..0bcf0fc31beae5 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/format_csv_values.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { isObject, isNull, isUndefined } from 'lodash'; +import { RawValue } from './types'; + +export function createFormatCsvValues( + escapeValue: (value: RawValue, index: number, array: RawValue[]) => string, + separator: string, + fields: string[], + formatsMap: any +) { + return function formatCsvValues(values: Record) { + return fields + .map(field => { + let value; + if (field === '_source') { + value = values; + } else { + value = values[field]; + } + if (isNull(value) || isUndefined(value)) { + return ''; + } + + let formattedValue = value; + if (formatsMap.has(field)) { + const formatter = formatsMap.get(field); + formattedValue = formatter.convert(value); + } + + return formattedValue; + }) + .map(value => (isObject(value) ? JSON.stringify(value) : value)) + .map(value => (value ? value.toString() : value)) + .map(escapeValue) + .join(separator); + }; +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.js deleted file mode 100644 index c13d24022c40c4..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.js +++ /dev/null @@ -1,85 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { createFlattenHit } from './flatten_hit'; -import { createFormatCsvValues } from './format_csv_values'; -import { createEscapeValue } from './escape_value'; -import { createHitIterator } from './hit_iterator'; -import { MaxSizeStringBuilder } from './max_size_string_builder'; -import { checkIfRowsHaveFormulas } from './check_cells_for_formulas'; - -export function createGenerateCsv(logger) { - const hitIterator = createHitIterator(logger); - - return async function generateCsv({ - searchRequest, - fields, - formatsMap, - metaFields, - conflictedTypesFields, - callEndpoint, - cancellationToken, - settings, - }) { - const escapeValue = createEscapeValue(settings.quoteValues); - const builder = new MaxSizeStringBuilder(settings.maxSizeBytes); - const header = `${fields.map(escapeValue).join(settings.separator)}\n`; - if (!builder.tryAppend(header)) { - return { - content: '', - maxSizeReached: true, - }; - } - - const iterator = hitIterator(settings.scroll, callEndpoint, searchRequest, cancellationToken); - let maxSizeReached = false; - let csvContainsFormulas = false; - - const flattenHit = createFlattenHit(fields, metaFields, conflictedTypesFields); - const formatCsvValues = createFormatCsvValues( - escapeValue, - settings.separator, - fields, - formatsMap - ); - try { - while (true) { - const { done, value: hit } = await iterator.next(); - - if (done) { - break; - } - - const flattened = flattenHit(hit); - const rows = formatCsvValues(flattened); - const rowsHaveFormulas = - settings.checkForFormulas && checkIfRowsHaveFormulas(flattened, fields); - - if (rowsHaveFormulas) { - csvContainsFormulas = true; - } - - if (!builder.tryAppend(rows + '\n')) { - logger.warn('max Size Reached'); - maxSizeReached = true; - cancellationToken.cancel(); - break; - } - } - } finally { - await iterator.return(); - } - const size = builder.getSizeInBytes(); - logger.debug(`finished generating, total size in bytes: ${size}`); - - return { - content: builder.getString(), - csvContainsFormulas, - maxSizeReached, - size, - }; - }; -} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts new file mode 100644 index 00000000000000..1986e68917ba86 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Logger } from '../../../../types'; +import { GenerateCsvParams, SavedSearchGeneratorResult } from '../../types'; +import { createFlattenHit } from './flatten_hit'; +import { createFormatCsvValues } from './format_csv_values'; +import { createEscapeValue } from './escape_value'; +import { createHitIterator } from './hit_iterator'; +import { MaxSizeStringBuilder } from './max_size_string_builder'; +import { checkIfRowsHaveFormulas } from './check_cells_for_formulas'; + +export function createGenerateCsv(logger: Logger) { + const hitIterator = createHitIterator(logger); + + return async function generateCsv({ + searchRequest, + fields, + formatsMap, + metaFields, + conflictedTypesFields, + callEndpoint, + cancellationToken, + settings, + }: GenerateCsvParams): Promise { + const escapeValue = createEscapeValue(settings.quoteValues); + const builder = new MaxSizeStringBuilder(settings.maxSizeBytes); + const header = `${fields.map(escapeValue).join(settings.separator)}\n`; + if (!builder.tryAppend(header)) { + return { + size: 0, + content: '', + maxSizeReached: true, + }; + } + + const iterator = hitIterator(settings.scroll, callEndpoint, searchRequest, cancellationToken); + let maxSizeReached = false; + let csvContainsFormulas = false; + + const flattenHit = createFlattenHit(fields, metaFields, conflictedTypesFields); + const formatCsvValues = createFormatCsvValues( + escapeValue, + settings.separator, + fields, + formatsMap + ); + try { + while (true) { + const { done, value: hit } = await iterator.next(); + + if (!hit) { + break; + } + + if (done) { + break; + } + + const flattened = flattenHit(hit); + const rows = formatCsvValues(flattened); + const rowsHaveFormulas = + settings.checkForFormulas && checkIfRowsHaveFormulas(flattened, fields); + + if (rowsHaveFormulas) { + csvContainsFormulas = true; + } + + if (!builder.tryAppend(rows + '\n')) { + logger.warn('max Size Reached'); + maxSizeReached = true; + cancellationToken.cancel(); + break; + } + } + } finally { + await iterator.return(); + } + const size = builder.getSizeInBytes(); + logger.debug(`finished generating, total size in bytes: ${size}`); + + return { + content: builder.getString(), + csvContainsFormulas, + maxSizeReached, + size, + }; + }; +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts new file mode 100644 index 00000000000000..3765217de92859 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.test.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import sinon from 'sinon'; +import { CancellationToken } from '../../../../common/cancellation_token'; +import { Logger, ScrollConfig } from '../../../../types'; +import { createHitIterator } from './hit_iterator'; + +const mockLogger = { + error: new Function(), + debug: new Function(), + warning: new Function(), +} as Logger; +const debugLogStub = sinon.stub(mockLogger, 'debug'); +const warnLogStub = sinon.stub(mockLogger, 'warning'); +const errorLogStub = sinon.stub(mockLogger, 'error'); +const mockCallEndpoint = sinon.stub(); +const mockSearchRequest = {}; +const mockConfig: ScrollConfig = { duration: '2s', size: 123 }; +let realCancellationToken = new CancellationToken(); +let isCancelledStub: sinon.SinonStub<[], boolean>; + +describe('hitIterator', function() { + beforeEach(() => { + debugLogStub.resetHistory(); + warnLogStub.resetHistory(); + errorLogStub.resetHistory(); + mockCallEndpoint.resetHistory(); + mockCallEndpoint.resetBehavior(); + mockCallEndpoint.resolves({ _scroll_id: '123blah', hits: { hits: ['you found me'] } }); + mockCallEndpoint.onCall(11).resolves({ _scroll_id: '123blah', hits: {} }); + + isCancelledStub = sinon.stub(realCancellationToken, 'isCancelled'); + isCancelledStub.returns(false); + }); + + afterEach(() => { + realCancellationToken = new CancellationToken(); + }); + + it('iterates hits', async () => { + // Begin + const hitIterator = createHitIterator(mockLogger); + const iterator = hitIterator( + mockConfig, + mockCallEndpoint, + mockSearchRequest, + realCancellationToken + ); + + while (true) { + const { done: iterationDone, value: hit } = await iterator.next(); + if (iterationDone) { + break; + } + expect(hit).to.be('you found me'); + } + + expect(mockCallEndpoint.callCount).to.be(13); + expect(debugLogStub.callCount).to.be(13); + expect(warnLogStub.callCount).to.be(0); + expect(errorLogStub.callCount).to.be(0); + }); + + it('stops searches after cancellation', async () => { + // Setup + isCancelledStub.onFirstCall().returns(false); + isCancelledStub.returns(true); + + // Begin + const hitIterator = createHitIterator(mockLogger); + const iterator = hitIterator( + mockConfig, + mockCallEndpoint, + mockSearchRequest, + realCancellationToken + ); + + while (true) { + const { done: iterationDone, value: hit } = await iterator.next(); + if (iterationDone) { + break; + } + expect(hit).to.be('you found me'); + } + + expect(mockCallEndpoint.callCount).to.be(3); + expect(debugLogStub.callCount).to.be(3); + expect(warnLogStub.callCount).to.be(1); + expect(errorLogStub.callCount).to.be(0); + + expect(warnLogStub.firstCall.lastArg).to.be( + 'Any remaining scrolling searches have been cancelled by the cancellation token.' + ); + }); + + it('handles time out', async () => { + // Setup + mockCallEndpoint.onCall(2).resolves({ status: 404 }); + + // Begin + const hitIterator = createHitIterator(mockLogger); + const iterator = hitIterator( + mockConfig, + mockCallEndpoint, + mockSearchRequest, + realCancellationToken + ); + + let errorThrown = false; + try { + while (true) { + const { done: iterationDone, value: hit } = await iterator.next(); + if (iterationDone) { + break; + } + expect(hit).to.be('you found me'); + } + } catch (err) { + expect(err).to.eql( + new Error('Expected _scroll_id in the following Elasticsearch response: {"status":404}') + ); + errorThrown = true; + } + + expect(mockCallEndpoint.callCount).to.be(4); + expect(debugLogStub.callCount).to.be(4); + expect(warnLogStub.callCount).to.be(0); + expect(errorLogStub.callCount).to.be(1); + expect(errorThrown).to.be(true); + }); +}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts index 68836c01369e3f..90690b62ff4a41 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts @@ -3,8 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams, SearchResponse } from 'elasticsearch'; +import { SearchParams, SearchResponse } from 'elasticsearch'; import { i18n } from '@kbn/i18n'; import { CancellationToken, ScrollConfig, Logger } from '../../../../types'; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.js deleted file mode 100644 index b4bdfcc13b3f6e..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export class MaxSizeStringBuilder { - constructor(maxSizeBytes) { - this._buffer = Buffer.alloc(maxSizeBytes); - this._size = 0; - this._maxSize = maxSizeBytes; - } - - tryAppend(str) { - const byteLength = Buffer.byteLength(str); - if (this._size + byteLength <= this._maxSize) { - this._buffer.write(str, this._size); - this._size += byteLength; - return true; - } - - return false; - } - - getSizeInBytes() { - return this._size; - } - - getString() { - return this._buffer.slice(0, this._size).toString(); - } -} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.test.ts new file mode 100644 index 00000000000000..843ff82e7c4bc9 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.test.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { MaxSizeStringBuilder } from './max_size_string_builder'; + +describe('MaxSizeStringBuilder', function() { + describe('tryAppend', function() { + it(`should return true if appended string is under maxSize`, function() { + const builder = new MaxSizeStringBuilder(100); + const result = builder.tryAppend('aa'); + expect(result).to.be(true); + }); + + it(`should return false if appended string is over the maxSize`, function() { + const builder = new MaxSizeStringBuilder(1); + const result = builder.tryAppend('aa'); + expect(result).to.be(false); + }); + + it(`should return true then false if second appended string puts total size over the maxSize`, function() { + const builder = new MaxSizeStringBuilder(1); + expect(builder.tryAppend('a')).to.be(true); + expect(builder.tryAppend('a')).to.be(false); + }); + }); + + describe('getBuffer', function() { + it(`should return an empty string when we don't call tryAppend`, function() { + const builder = new MaxSizeStringBuilder(100); + expect(builder.getString()).to.be(''); + }); + + it('should return equivalent string if tryAppend called once and less than maxSize', function() { + const str = 'foo'; + const builder = new MaxSizeStringBuilder(100); + builder.tryAppend(str); + expect(builder.getString()).to.be(str); + }); + + it('should return equivalent string if tryAppend called multiple times and total size less than maxSize', function() { + const strs = ['foo', 'bar', 'baz']; + const builder = new MaxSizeStringBuilder(100); + strs.forEach(str => builder.tryAppend(str)); + expect(builder.getString()).to.be(strs.join('')); + }); + + it('should return empty string if tryAppend called one time with size greater than maxSize', function() { + const str = 'aa'; // each a is one byte + const builder = new MaxSizeStringBuilder(1); + builder.tryAppend(str); + expect(builder.getString()).to.be(''); + }); + + it('should return partial string if tryAppend called multiple times with total size greater than maxSize', function() { + const str = 'a'; // each a is one byte + const builder = new MaxSizeStringBuilder(1); + builder.tryAppend(str); + builder.tryAppend(str); + expect(builder.getString()).to.be('a'); + }); + }); + + describe('getSizeInBytes', function() { + it(`should return 0 when no strings have been appended`, function() { + const builder = new MaxSizeStringBuilder(100); + expect(builder.getSizeInBytes()).to.be(0); + }); + + it(`should the size in bytes`, function() { + const builder = new MaxSizeStringBuilder(100); + const stringValue = 'foobar'; + builder.tryAppend(stringValue); + expect(builder.getSizeInBytes()).to.be(stringValue.length); + }); + }); +}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.ts new file mode 100644 index 00000000000000..70bc2030d290c6 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/max_size_string_builder.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export class MaxSizeStringBuilder { + private _buffer: Buffer; + private _size: number; + private _maxSize: number; + + constructor(maxSizeBytes: number) { + this._buffer = Buffer.alloc(maxSizeBytes); + this._size = 0; + this._maxSize = maxSizeBytes; + } + + tryAppend(str: string) { + const byteLength = Buffer.byteLength(str); + if (this._size + byteLength <= this._maxSize) { + this._buffer.write(str, this._size); + this._size += byteLength; + return true; + } + + return false; + } + + getSizeInBytes() { + return this._size; + } + + getString() { + return this._buffer.slice(0, this._size).toString(); + } +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts new file mode 100644 index 00000000000000..b4dc7436649956 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/types.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export type RawValue = string | object | null | undefined; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts index 9d1eb9cc1bd4d3..842330fa7c93f3 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { CancellationToken } from '../../common/cancellation_token'; import { JobDocPayload, JobParamPostPayload, ConditionalHeaders, RequestFacade } from '../../types'; interface DocValueField { @@ -37,3 +38,75 @@ export interface JobDocPayloadDiscoverCsv extends JobDocPayload; + stored_fields: string[]; + } + | any; +} + +type EndpointCaller = (method: string, params: any) => Promise; + +type FormatsMap = Map< + string, + { + id: string; + params: { + pattern: string; + }; + } +>; + +export interface SavedSearchGeneratorResult { + content: string; + size: number; + maxSizeReached: boolean; + csvContainsFormulas?: boolean; +} + +export interface CsvResultFromSearch { + type: string; + result: SavedSearchGeneratorResult; +} + +export interface GenerateCsvParams { + searchRequest: SearchRequest; + callEndpoint: EndpointCaller; + fields: string[]; + formatsMap: FormatsMap; + metaFields: string[]; + conflictedTypesFields: string[]; + cancellationToken: CancellationToken; + settings: { + separator: string; + quoteValues: boolean; + timezone: string | null; + maxSizeBytes: number; + scroll: { duration: string; size: number }; + checkForFormulas?: boolean; + }; +} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts index 8443be2b25f4f9..a270e3e0329fe8 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts @@ -6,13 +6,14 @@ import { notFound, notImplemented } from 'boom'; import { get } from 'lodash'; -import { PLUGIN_ID, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../../common/constants'; -import { cryptoFactory, LevelLogger } from '../../../../server/lib'; +import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../../common/constants'; +import { cryptoFactory } from '../../../../server/lib'; import { CreateJobFactory, ImmediateCreateJobFn, ServerFacade, RequestFacade, + Logger, } from '../../../../types'; import { SavedObject, @@ -34,13 +35,9 @@ interface VisData { export const createJobFactory: CreateJobFactory> = function createJobFactoryFn(server: ServerFacade) { +>> = function createJobFactoryFn(server: ServerFacade, parentLogger: Logger) { const crypto = cryptoFactory(server); - const logger = LevelLogger.createForServer(server, [ - PLUGIN_ID, - CSV_FROM_SAVEDOBJECT_JOB_TYPE, - 'create-job', - ]); + const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'create-job']); return async function createJob( jobParams: JobParamsPanelCsv, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts index e161d7afc84e27..03f491deaa43d6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts @@ -5,43 +5,31 @@ */ import { i18n } from '@kbn/i18n'; -import { cryptoFactory, LevelLogger } from '../../../server/lib'; +import { CONTENT_TYPE_CSV, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; +import { cryptoFactory } from '../../../server/lib'; import { ExecuteJobFactory, ImmediateExecuteFn, - JobDocOutputExecuted, - ServerFacade, + JobDocOutput, + Logger, RequestFacade, + ServerFacade, } from '../../../types'; -import { - CONTENT_TYPE_CSV, - CSV_FROM_SAVEDOBJECT_JOB_TYPE, - PLUGIN_ID, -} from '../../../common/constants'; -import { - CsvResultFromSearch, - JobParamsPanelCsv, - SearchPanel, - JobDocPayloadPanelCsv, - FakeRequest, -} from '../types'; +import { CsvResultFromSearch } from '../../csv/types'; +import { FakeRequest, JobDocPayloadPanelCsv, JobParamsPanelCsv, SearchPanel } from '../types'; import { createGenerateCsv } from './lib'; export const executeJobFactory: ExecuteJobFactory> = function executeJobFactoryFn(server: ServerFacade) { +>> = function executeJobFactoryFn(server: ServerFacade, parentLogger: Logger) { const crypto = cryptoFactory(server); - const logger = LevelLogger.createForServer(server, [ - PLUGIN_ID, - CSV_FROM_SAVEDOBJECT_JOB_TYPE, - 'execute-job', - ]); + const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'execute-job']); return async function executeJob( jobId: string | null, job: JobDocPayloadPanelCsv, realRequest?: RequestFacade - ): Promise { + ): Promise { // There will not be a jobID for "immediate" generation. // jobID is only for "queued" jobs // Use the jobID as a logging tag or "immediate" diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts index d39d2bbf08c9f8..8f31509962481b 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts @@ -4,20 +4,26 @@ * you may not use this file except in compliance with the Elastic License. */ -// @ts-ignore no module definition TODO +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { KibanaRequest } from '../../../../../../../../src/core/server'; import { createGenerateCsv } from '../../../csv/server/lib/generate_csv'; import { CancellationToken } from '../../../../common/cancellation_token'; import { ServerFacade, RequestFacade, Logger } from '../../../../types'; -import { SavedSearchObjectAttributes, SearchPanel, SearchRequest, SearchSource } from '../../types'; import { + JobParamsDiscoverCsv, CsvResultFromSearch, + SearchRequest, GenerateCsvParams, +} from '../../../csv/types'; +import { IndexPatternField, QueryFilter, + SavedSearchObjectAttributes, + SearchPanel, + SearchSource, } from '../../types'; import { getDataSource } from './get_data_source'; import { getFilters } from './get_filters'; -import { JobParamsDiscoverCsv } from '../../../csv/types'; import { esQuery, @@ -57,7 +63,9 @@ export async function generateCsvSearch( jobParams: JobParamsDiscoverCsv ): Promise { const { savedObjects, uiSettingsServiceFactory } = server; - const savedObjectsClient = savedObjects.getScopedSavedObjectsClient(req.getRawRequest()); + const savedObjectsClient = savedObjects.getScopedSavedObjectsClient( + KibanaRequest.from(req.getRawRequest()) + ); const { indexPatternSavedObjectId, timerange } = searchPanel; const savedSearchObjectAttr = searchPanel.attributes as SavedSearchObjectAttributes; const { indexPatternSavedObject } = await getDataSource( diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts index b6dd174410c119..6a7d5f336e238d 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CancellationToken } from '../../common/cancellation_token'; import { JobParamPostPayload, JobDocPayload, ServerFacade } from '../../types'; export interface FakeRequest { @@ -144,75 +143,6 @@ export interface SearchSource { filter: any[]; } -export interface SearchRequest { - index: string; - body: - | { - _source: { - excludes: string[]; - includes: string[]; - }; - docvalue_fields: string[]; - query: - | { - bool: { - filter: any[]; - must_not: any[]; - should: any[]; - must: any[]; - }; - } - | any; - script_fields: any; - sort: Array<{ - [key: string]: { - order: string; - }; - }>; - stored_fields: string[]; - } - | any; -} - -export interface SavedSearchGeneratorResult { - content: string; - maxSizeReached: boolean; - size: number; -} - -export interface CsvResultFromSearch { - type: string; - result: SavedSearchGeneratorResult; -} - -type EndpointCaller = (method: string, params: any) => Promise; -type FormatsMap = Map< - string, - { - id: string; - params: { - pattern: string; - }; - } ->; - -export interface GenerateCsvParams { - searchRequest: SearchRequest; - callEndpoint: EndpointCaller; - fields: string[]; - formatsMap: FormatsMap; - metaFields: string[]; // FIXME not sure what this is for - conflictedTypesFields: string[]; // FIXME not sure what this is for - cancellationToken: CancellationToken; - settings: { - separator: string; - quoteValues: boolean; - timezone: string | null; - maxSizeBytes: number; - scroll: { duration: string; size: number }; - }; -} - /* * These filter types are stub types to help ensure things get passed to * non-Typescript functions in the right order. An actual structure is not diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js index 1be65722fa668b..4f02ab5d4c077e 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js @@ -57,6 +57,8 @@ beforeEach(() => { afterEach(() => generatePngObservableFactory.mockReset()); +const getMockLogger = () => new LevelLogger(); + const encryptHeaders = async headers => { const crypto = cryptoFactory(mockServer); return await crypto.encrypt(headers); @@ -68,7 +70,7 @@ test(`passes browserTimezone to generatePng`, async () => { const generatePngObservable = generatePngObservableFactory(); generatePngObservable.mockReturnValue(Rx.of(Buffer.from(''))); - const executeJob = executeJobFactory(mockServer, { browserDriverFactory: {} }); + const executeJob = executeJobFactory(mockServer, getMockLogger(), { browserDriverFactory: {} }); const browserTimezone = 'UTC'; await executeJob( 'pngJobId', @@ -86,7 +88,7 @@ test(`passes browserTimezone to generatePng`, async () => { }); test(`returns content_type of application/png`, async () => { - const executeJob = executeJobFactory(mockServer, { browserDriverFactory: {} }); + const executeJob = executeJobFactory(mockServer, getMockLogger(), { browserDriverFactory: {} }); const encryptedHeaders = await encryptHeaders({}); const generatePngObservable = generatePngObservableFactory(); @@ -106,7 +108,7 @@ test(`returns content of generatePng getBuffer base64 encoded`, async () => { const generatePngObservable = generatePngObservableFactory(); generatePngObservable.mockReturnValue(Rx.of(Buffer.from(testContent))); - const executeJob = executeJobFactory(mockServer, { browserDriverFactory: {} }); + const executeJob = executeJobFactory(mockServer, getMockLogger(), { browserDriverFactory: {} }); const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pngJobId', diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts index c2fda05fbe3e93..7d5c69655c362f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.ts @@ -6,14 +6,14 @@ import * as Rx from 'rxjs'; import { catchError, map, mergeMap, takeUntil } from 'rxjs/operators'; -import { PLUGIN_ID, PNG_JOB_TYPE } from '../../../../common/constants'; +import { PNG_JOB_TYPE } from '../../../../common/constants'; import { ServerFacade, ExecuteJobFactory, ESQueueWorkerExecuteFn, HeadlessChromiumDriverFactory, + Logger, } from '../../../../types'; -import { LevelLogger } from '../../../../server/lib'; import { decryptJobHeaders, omitBlacklistedHeaders, @@ -27,10 +27,11 @@ type QueuedPngExecutorFactory = ExecuteJobFactory { afterEach(() => generatePdfObservableFactory.mockReset()); +const getMockLogger = () => new LevelLogger(); + const encryptHeaders = async headers => { const crypto = cryptoFactory(mockServer); return await crypto.encrypt(headers); @@ -68,7 +70,7 @@ test(`passes browserTimezone to generatePdf`, async () => { const generatePdfObservable = generatePdfObservableFactory(); generatePdfObservable.mockReturnValue(Rx.of(Buffer.from(''))); - const executeJob = executeJobFactory(mockServer, { browserDriverFactory: {} }); + const executeJob = executeJobFactory(mockServer, getMockLogger(), { browserDriverFactory: {} }); const browserTimezone = 'UTC'; await executeJob( 'pdfJobId', @@ -89,7 +91,7 @@ test(`passes browserTimezone to generatePdf`, async () => { }); test(`returns content_type of application/pdf`, async () => { - const executeJob = executeJobFactory(mockServer, { browserDriverFactory: {} }); + const executeJob = executeJobFactory(mockServer, getMockLogger(), { browserDriverFactory: {} }); const encryptedHeaders = await encryptHeaders({}); const generatePdfObservable = generatePdfObservableFactory(); @@ -109,7 +111,7 @@ test(`returns content of generatePdf getBuffer base64 encoded`, async () => { const generatePdfObservable = generatePdfObservableFactory(); generatePdfObservable.mockReturnValue(Rx.of(Buffer.from(testContent))); - const executeJob = executeJobFactory(mockServer, { browserDriverFactory: {} }); + const executeJob = executeJobFactory(mockServer, getMockLogger(), { browserDriverFactory: {} }); const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pdfJobId', diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts index d85207e6712125..dee53697c6681d 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.ts @@ -11,10 +11,10 @@ import { ExecuteJobFactory, ESQueueWorkerExecuteFn, HeadlessChromiumDriverFactory, + Logger, } from '../../../../types'; import { JobDocPayloadPDF } from '../../types'; -import { PLUGIN_ID, PDF_JOB_TYPE } from '../../../../common/constants'; -import { LevelLogger } from '../../../../server/lib'; +import { PDF_JOB_TYPE } from '../../../../common/constants'; import { generatePdfObservableFactory } from '../lib/generate_pdf'; import { decryptJobHeaders, @@ -28,10 +28,11 @@ type QueuedPdfExecutorFactory = ExecuteJobFactory { return Math.floor((kb * 1024 * 8) / 6); }; +interface ReportingDeps { + data: DataPluginStart; +} + export const reporting = (kibana: any) => { return new kibana.Plugin({ id: PLUGIN_ID, @@ -70,6 +77,14 @@ export const reporting = (kibana: any) => { const pluginsSetup: ReportingSetupDeps = { usageCollection: server.newPlatform.setup.plugins.usageCollection, }; + + const fieldFormatServiceFactory = async (uiSettings: IUiSettingsClient) => { + const [, plugins] = await coreSetup.getStartServices(); + const { fieldFormats } = (plugins as ReportingDeps).data; + + return fieldFormats.fieldFormatServiceFactory(uiSettings); + }; + const __LEGACY: LegacySetup = { config: server.config, info: server.info, @@ -80,13 +95,12 @@ export const reporting = (kibana: any) => { security: server.plugins.security, }, savedObjects: server.savedObjects, + fieldFormatServiceFactory, uiSettingsServiceFactory: server.uiSettingsServiceFactory, - // @ts-ignore Property 'fieldFormatServiceFactory' does not exist on type 'Server'. - fieldFormatServiceFactory: server.fieldFormatServiceFactory, - log: server.log.bind(server), }; - const plugin: ReportingPlugin = reportingPluginFactory(__LEGACY, this); + const initializerContext = server.newPlatform.coreContext; + const plugin: ReportingPlugin = reportingPluginFactory(initializerContext, __LEGACY, this); await plugin.setup(coreSetup, pluginsSetup); }, diff --git a/x-pack/legacy/plugins/reporting/public/lib/job_queue_client.ts b/x-pack/legacy/plugins/reporting/public/lib/job_queue_client.ts index 173a4e31cfef60..0f68c56a18bf69 100644 --- a/x-pack/legacy/plugins/reporting/public/lib/job_queue_client.ts +++ b/x-pack/legacy/plugins/reporting/public/lib/job_queue_client.ts @@ -5,8 +5,6 @@ */ import { kfetch } from 'ui/kfetch'; -// @ts-ignore -import { addSystemApiHeader } from 'ui/system_api'; const API_BASE_URL = '/api/reporting/jobs'; @@ -64,7 +62,7 @@ class JobQueueClient { method: 'GET', pathname: `${API_BASE_URL}/list`, query, - headers: addSystemApiHeader({}), + asSystemRequest: true, }); }; @@ -72,7 +70,7 @@ class JobQueueClient { return kfetch({ method: 'GET', pathname: `${API_BASE_URL}/count`, - headers: addSystemApiHeader({}), + asSystemRequest: true, }); } @@ -80,7 +78,7 @@ class JobQueueClient { return kfetch({ method: 'GET', pathname: `${API_BASE_URL}/output/${jobId}`, - headers: addSystemApiHeader({}), + asSystemRequest: true, }); } @@ -88,7 +86,7 @@ class JobQueueClient { return kfetch({ method: 'GET', pathname: `${API_BASE_URL}/info/${jobId}`, - headers: addSystemApiHeader({}), + asSystemRequest: true, }); } } diff --git a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts index a253988b01952e..128df4d318c764 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts @@ -6,17 +6,16 @@ import { ensureBrowserDownloaded } from './download'; import { installBrowser } from './install'; -import { LevelLogger } from '../lib/level_logger'; -import { ServerFacade, CaptureConfig } from '../../types'; -import { PLUGIN_ID, BROWSER_TYPE } from '../../common/constants'; +import { ServerFacade, CaptureConfig, Logger } from '../../types'; +import { BROWSER_TYPE } from '../../common/constants'; import { chromium } from './index'; import { HeadlessChromiumDriverFactory } from './chromium/driver_factory'; export async function createBrowserDriverFactory( - server: ServerFacade + server: ServerFacade, + logger: Logger ): Promise { const config = server.config(); - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'browser-driver']); const dataDir: string = config.get('path.data'); const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts index 5cf760250ec0e3..05b760c0c3bd6c 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts @@ -4,18 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PLUGIN_ID } from '../../common/constants'; import { ServerFacade, ExportTypesRegistry, HeadlessChromiumDriverFactory, QueueConfig, + Logger, } from '../../types'; // @ts-ignore import { Esqueue } from './esqueue'; import { createWorkerFactory } from './create_worker'; -import { LevelLogger } from './level_logger'; -// @ts-ignore import { createTaggedLogger } from './create_tagged_logger'; // TODO remove createTaggedLogger once esqueue is removed interface CreateQueueFactoryOpts { @@ -25,6 +23,7 @@ interface CreateQueueFactoryOpts { export function createQueueFactory( server: ServerFacade, + logger: Logger, { exportTypesRegistry, browserDriverFactory }: CreateQueueFactoryOpts ): Esqueue { const queueConfig: QueueConfig = server.config().get('xpack.reporting.queue'); @@ -35,23 +34,25 @@ export function createQueueFactory( timeout: queueConfig.timeout, dateSeparator: '.', client: server.plugins.elasticsearch.getCluster('admin'), - logger: createTaggedLogger(server, [PLUGIN_ID, 'esqueue', 'queue-worker']), + logger: createTaggedLogger(logger, ['esqueue', 'queue-worker']), }; const queue: Esqueue = new Esqueue(index, queueOptions); if (queueConfig.pollEnabled) { // create workers to poll the index for idle jobs waiting to be claimed and executed - const createWorker = createWorkerFactory(server, { exportTypesRegistry, browserDriverFactory }); + const createWorker = createWorkerFactory(server, logger, { + exportTypesRegistry, + browserDriverFactory, + }); createWorker(queue); } else { - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'create_queue']); logger.info( 'xpack.reporting.queue.pollEnabled is set to false. This Kibana instance ' + 'will not poll for idle jobs to claim and execute. Make sure another ' + 'Kibana instance with polling enabled is running in this cluster so ' + 'reporting jobs can complete.', - ['info'] + ['create_queue'] ); } diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.js b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.js deleted file mode 100644 index 838024f801b676..00000000000000 --- a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.js +++ /dev/null @@ -1,24 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -/** - * @function taggedLogger - * @param {string} message - * @param {string[]} [additionalTags] - */ - -/** - * Creates a taggedLogger function with tags, allows the consumer to optionally provide additional tags - * - * @param {Server} server - * @param {string[]} tags - tags to always be passed into the `logger` function - * @returns taggedLogger - */ -export function createTaggedLogger(server, tags) { - return (msg, additionalTags = []) => { - server.log([...tags, ...additionalTags], msg); - }; -} diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts new file mode 100644 index 00000000000000..97b34dfe40830c --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/lib/create_tagged_logger.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Logger } from '../../types'; + +export function createTaggedLogger(logger: Logger, tags: string[]) { + return (msg: string, additionalTags = []) => { + const allTags = [...tags, ...additionalTags]; + + if (allTags.includes('info')) { + const newTags = allTags.filter(t => t !== 'info'); // Ensure 'info' is not included twice + logger.info(msg, newTags); + } else if (allTags.includes('debug')) { + const newTags = allTags.filter(t => t !== 'debug'); + logger.debug(msg, newTags); + } else if (allTags.includes('warn') || allTags.includes('warning')) { + const newTags = allTags.filter(t => t !== 'warn' && t !== 'warning'); + logger.warn(msg, newTags); + } else { + logger.error(msg, allTags); + } + }; +} diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts index 8f843752491ecb..6a5c93db32376a 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts @@ -25,10 +25,11 @@ const executeJobFactoryStub = sinon.stub(); const getMockServer = (): ServerFacade => { return ({ - log: sinon.stub(), config: () => ({ get: configGetStub }), } as unknown) as ServerFacade; }; +const getMockLogger = jest.fn(); + const getMockExportTypesRegistry = ( exportTypes: any[] = [{ executeJobFactory: executeJobFactoryStub }] ) => ({ @@ -47,7 +48,7 @@ describe('Create Worker', () => { test('Creates a single Esqueue worker for Reporting', async () => { const exportTypesRegistry = getMockExportTypesRegistry(); - const createWorker = createWorkerFactory(getMockServer(), { + const createWorker = createWorkerFactory(getMockServer(), getMockLogger(), { exportTypesRegistry: exportTypesRegistry as ExportTypesRegistry, browserDriverFactory: {} as HeadlessChromiumDriverFactory, }); @@ -81,7 +82,7 @@ Object { { executeJobFactory: executeJobFactoryStub }, { executeJobFactory: executeJobFactoryStub }, ]); - const createWorker = createWorkerFactory(getMockServer(), { + const createWorker = createWorkerFactory(getMockServer(), getMockLogger(), { exportTypesRegistry: exportTypesRegistry as ExportTypesRegistry, browserDriverFactory: {} as HeadlessChromiumDriverFactory, }); diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts index 1326e411b6c5c7..67869016a250be 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts @@ -17,10 +17,10 @@ import { JobSource, RequestFacade, ServerFacade, + Logger, } from '../../types'; // @ts-ignore untyped dependency import { events as esqueueEvents } from './esqueue'; -import { LevelLogger } from './level_logger'; interface CreateWorkerFactoryOpts { exportTypesRegistry: ExportTypesRegistry; @@ -29,11 +29,11 @@ interface CreateWorkerFactoryOpts { export function createWorkerFactory( server: ServerFacade, + logger: Logger, { exportTypesRegistry, browserDriverFactory }: CreateWorkerFactoryOpts ) { type JobDocPayloadType = JobDocPayload; const config = server.config(); - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'queue-worker']); const queueConfig: QueueConfig = config.get('xpack.reporting.queue'); const kibanaName: string = config.get('server.name'); const kibanaId: string = config.get('server.uuid'); @@ -50,7 +50,7 @@ export function createWorkerFactory( ExportTypeDefinition >) { // TODO: the executeJobFn should be unwrapped in the register method of the export types registry - const jobExecutor = exportType.executeJobFactory(server, { browserDriverFactory }); + const jobExecutor = exportType.executeJobFactory(server, logger, { browserDriverFactory }); jobExecutors.set(exportType.jobType, jobExecutor); } diff --git a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts index 2d044ab31a160e..14c57fa35dcf4e 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts @@ -35,8 +35,10 @@ interface EnqueueJobFactoryOpts { export function enqueueJobFactory( server: ServerFacade, + parentLogger: Logger, { exportTypesRegistry, esqueue }: EnqueueJobFactoryOpts ): EnqueueJobFn { + const logger = parentLogger.clone(['queue-job']); const config = server.config(); const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); const browserType = captureConfig.browser.type; @@ -44,7 +46,6 @@ export function enqueueJobFactory( const queueConfig: QueueConfig = config.get('xpack.reporting.queue'); return async function enqueueJob( - parentLogger: Logger, exportTypeId: string, jobParams: JobParamsType, user: string, @@ -53,7 +54,6 @@ export function enqueueJobFactory( ): Promise { type CreateJobFn = ESQueueCreateJobFn | ImmediateCreateJobFn; - const logger = parentLogger.clone(['queue-job']); const exportType = exportTypesRegistry.getById(exportTypeId); if (exportType == null) { @@ -61,7 +61,7 @@ export function enqueueJobFactory( } // TODO: the createJobFn should be unwrapped in the register method of the export types registry - const createJob = exportType.createJobFactory(server) as CreateJobFn; + const createJob = exportType.createJobFactory(server, logger) as CreateJobFn; const payload = await createJob(jobParams, headers, request); const options = { diff --git a/x-pack/legacy/plugins/reporting/server/lib/get_user.ts b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts index e2921de795012b..9ee8d9a835c89e 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/get_user.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts @@ -5,9 +5,9 @@ */ import { Legacy } from 'kibana'; -import { ServerFacade } from '../../types'; +import { Logger, ServerFacade } from '../../types'; -export function getUserFactory(server: ServerFacade) { +export function getUserFactory(server: ServerFacade, logger: Logger) { /* * Legacy.Request because this is called from routing middleware */ @@ -19,7 +19,7 @@ export function getUserFactory(server: ServerFacade) { try { return await server.plugins.security.getUser(request); } catch (err) { - server.log(['reporting', 'getUser', 'error'], err); + logger.error(err, ['getUser']); return null; } }; diff --git a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.js b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.js deleted file mode 100644 index 2162ecedb8371f..00000000000000 --- a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.js +++ /dev/null @@ -1,127 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get } from 'lodash'; - -const defaultSize = 10; - -export function jobsQueryFactory(server) { - const index = server.config().get('xpack.reporting.index'); - const { callWithInternalUser, errors: esErrors } = server.plugins.elasticsearch.getCluster( - 'admin' - ); - - function getUsername(user) { - return get(user, 'username', false); - } - - function execQuery(queryType, body) { - const defaultBody = { - search: { - _source: { - excludes: ['output.content'], - }, - sort: [{ created_at: { order: 'desc' } }], - size: defaultSize, - }, - }; - - const query = { - index: `${index}-*`, - body: Object.assign(defaultBody[queryType] || {}, body), - }; - - return callWithInternalUser(queryType, query).catch(err => { - if (err instanceof esErrors['401']) return; - if (err instanceof esErrors['403']) return; - if (err instanceof esErrors['404']) return; - throw err; - }); - } - - function getHits(query) { - return query.then(res => get(res, 'hits.hits', [])); - } - - return { - list(jobTypes, user, page = 0, size = defaultSize, jobIds) { - const username = getUsername(user); - - const body = { - size, - from: size * page, - query: { - constant_score: { - filter: { - bool: { - must: [{ terms: { jobtype: jobTypes } }, { term: { created_by: username } }], - }, - }, - }, - }, - }; - - if (jobIds) { - body.query.constant_score.filter.bool.must.push({ - ids: { values: jobIds }, - }); - } - - return getHits(execQuery('search', body)); - }, - - count(jobTypes, user) { - const username = getUsername(user); - - const body = { - query: { - constant_score: { - filter: { - bool: { - must: [{ terms: { jobtype: jobTypes } }, { term: { created_by: username } }], - }, - }, - }, - }, - }; - - return execQuery('count', body).then(doc => { - if (!doc) return 0; - return doc.count; - }); - }, - - get(user, id, opts = {}) { - if (!id) return Promise.resolve(); - - const username = getUsername(user); - - const body = { - query: { - constant_score: { - filter: { - bool: { - must: [{ term: { _id: id } }, { term: { created_by: username } }], - }, - }, - }, - }, - size: 1, - }; - - if (opts.includeContent) { - body._source = { - excludes: [], - }; - } - - return getHits(execQuery('search', body)).then(hits => { - if (hits.length !== 1) return; - return hits[0]; - }); - }, - }; -} diff --git a/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts new file mode 100644 index 00000000000000..0c16f780c34acd --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/lib/jobs_query.ts @@ -0,0 +1,156 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get } from 'lodash'; +import { ServerFacade, JobSource } from '../../types'; + +const defaultSize = 10; + +interface QueryBody { + size?: number; + from?: number; + _source?: { + excludes: string[]; + }; + query: { + constant_score: { + filter: { + bool: { + must: Array>; + }; + }; + }; + }; +} + +interface GetOpts { + includeContent?: boolean; +} + +interface CountAggResult { + count: number; +} + +export function jobsQueryFactory(server: ServerFacade) { + const index = server.config().get('xpack.reporting.index'); + // @ts-ignore `errors` does not exist on type Cluster + const { callWithInternalUser, errors: esErrors } = server.plugins.elasticsearch.getCluster( + 'admin' + ); + + function getUsername(user: any) { + return get(user, 'username', false); + } + + function execQuery(queryType: string, body: QueryBody) { + const defaultBody: Record = { + search: { + _source: { + excludes: ['output.content'], + }, + sort: [{ created_at: { order: 'desc' } }], + size: defaultSize, + }, + }; + + const query = { + index: `${index}-*`, + body: Object.assign(defaultBody[queryType] || {}, body), + }; + + return callWithInternalUser(queryType, query).catch(err => { + if (err instanceof esErrors['401']) return; + if (err instanceof esErrors['403']) return; + if (err instanceof esErrors['404']) return; + throw err; + }); + } + + type Result = number; + + function getHits(query: Promise) { + return query.then(res => get(res, 'hits.hits', [])); + } + + return { + list(jobTypes: string[], user: any, page = 0, size = defaultSize, jobIds: string[] | null) { + const username = getUsername(user); + + const body: QueryBody = { + size, + from: size * page, + query: { + constant_score: { + filter: { + bool: { + must: [{ terms: { jobtype: jobTypes } }, { term: { created_by: username } }], + }, + }, + }, + }, + }; + + if (jobIds) { + body.query.constant_score.filter.bool.must.push({ + ids: { values: jobIds }, + }); + } + + return getHits(execQuery('search', body)); + }, + + count(jobTypes: string[], user: any) { + const username = getUsername(user); + + const body: QueryBody = { + query: { + constant_score: { + filter: { + bool: { + must: [{ terms: { jobtype: jobTypes } }, { term: { created_by: username } }], + }, + }, + }, + }, + }; + + return execQuery('count', body).then((doc: CountAggResult) => { + if (!doc) return 0; + return doc.count; + }); + }, + + get(user: any, id: string, opts: GetOpts = {}): Promise | void> { + if (!id) return Promise.resolve(); + + const username = getUsername(user); + + const body: QueryBody = { + query: { + constant_score: { + filter: { + bool: { + must: [{ term: { _id: id } }, { term: { created_by: username } }], + }, + }, + }, + }, + size: 1, + }; + + if (opts.includeContent) { + body._source = { + excludes: [], + }; + } + + return getHits(execQuery('search', body)).then(hits => { + if (hits.length !== 1) return; + return hits[0]; + }); + }, + }; +} diff --git a/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts b/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts index 839fa16a716b7d..d015d500363c12 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts @@ -4,48 +4,46 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ServerFacade } from '../../types'; +import { LoggerFactory } from 'src/core/server'; const trimStr = (toTrim: string) => { return typeof toTrim === 'string' ? toTrim.trim() : toTrim; }; export class LevelLogger { - private _logger: any; + private _logger: LoggerFactory; private _tags: string[]; + public warning: (msg: string, tags?: string[]) => void; - public warn: (msg: string, tags?: string[]) => void; - - static createForServer(server: ServerFacade, tags: string[]) { - const serverLog: ServerFacade['log'] = (tgs: string[], msg: string) => server.log(tgs, msg); - return new LevelLogger(serverLog, tags); - } - - constructor(logger: ServerFacade['log'], tags: string[]) { + constructor(logger: LoggerFactory, tags?: string[]) { this._logger = logger; - this._tags = tags; + this._tags = tags || []; /* * This shortcut provides maintenance convenience: Reporting code has been * using both .warn and .warning */ - this.warn = this.warning.bind(this); + this.warning = this.warn.bind(this); + } + + private getLogger(tags: string[]) { + return this._logger.get(...this._tags, ...tags); } public error(err: string | Error, tags: string[] = []) { - this._logger([...this._tags, ...tags, 'error'], err); + this.getLogger(tags).error(err); } - public warning(msg: string, tags: string[] = []) { - this._logger([...this._tags, ...tags, 'warning'], trimStr(msg)); + public warn(msg: string, tags: string[] = []) { + this.getLogger(tags).warn(msg); } public debug(msg: string, tags: string[] = []) { - this._logger([...this._tags, ...tags, 'debug'], trimStr(msg)); + this.getLogger(tags).debug(msg); } public info(msg: string, tags: string[] = []) { - this._logger([...this._tags, ...tags, 'info'], trimStr(msg)); + this.getLogger(tags).info(trimStr(msg)); } public clone(tags: string[]) { diff --git a/x-pack/legacy/plugins/reporting/server/plugin.ts b/x-pack/legacy/plugins/reporting/server/plugin.ts index 934a3487209c42..42ef5c3df182e6 100644 --- a/x-pack/legacy/plugins/reporting/server/plugin.ts +++ b/x-pack/legacy/plugins/reporting/server/plugin.ts @@ -5,8 +5,7 @@ */ import { Legacy } from 'kibana'; -import { CoreSetup, CoreStart, Plugin } from 'src/core/server'; -import { IUiSettingsClient } from 'src/core/server'; +import { CoreSetup, CoreStart, Plugin, LoggerFactory } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; // @ts-ignore @@ -14,10 +13,15 @@ import { mirrorPluginStatus } from '../../../server/lib/mirror_plugin_status'; import { PLUGIN_ID } from '../common/constants'; import { ReportingPluginSpecOptions } from '../types.d'; import { registerRoutes } from './routes'; -import { LevelLogger, checkLicenseFactory, getExportTypesRegistry, runValidations } from './lib'; +import { checkLicenseFactory, getExportTypesRegistry, runValidations, LevelLogger } from './lib'; import { createBrowserDriverFactory } from './browsers'; import { registerReportingUsageCollector } from './usage'; import { logConfiguration } from '../log_configuration'; +import { PluginStart as DataPluginStart } from '../../../../../src/plugins/data/server'; + +export interface ReportingInitializerContext { + logger: LoggerFactory; +} // For now there is no exposed functionality to other plugins export type ReportingSetup = object; @@ -33,7 +37,6 @@ type LegacyPlugins = Legacy.Server['plugins']; export interface LegacySetup { config: Legacy.Server['config']; info: Legacy.Server['info']; - log: Legacy.Server['log']; plugins: { elasticsearch: LegacyPlugins['elasticsearch']; security: LegacyPlugins['security']; @@ -44,7 +47,7 @@ export interface LegacySetup { route: Legacy.Server['route']; savedObjects: Legacy.Server['savedObjects']; uiSettingsServiceFactory: Legacy.Server['uiSettingsServiceFactory']; - fieldFormatServiceFactory: (uiConfig: IUiSettingsClient) => unknown; + fieldFormatServiceFactory: DataPluginStart['fieldFormats']['fieldFormatServiceFactory']; } export type ReportingPlugin = Plugin< @@ -59,10 +62,17 @@ export type ReportingPlugin = Plugin< * into `setup`. The factory parameters take the legacy dependencies, and the * `setup` method gets it from enclosure */ export function reportingPluginFactory( + initializerContext: ReportingInitializerContext, __LEGACY: LegacySetup, legacyPlugin: ReportingPluginSpecOptions ) { return new (class ReportingPlugin implements ReportingPlugin { + private initializerContext: ReportingInitializerContext; + + constructor(context: ReportingInitializerContext) { + this.initializerContext = context; + } + public async setup(core: CoreSetup, plugins: ReportingSetupDeps): Promise { const exportTypesRegistry = getExportTypesRegistry(); @@ -76,8 +86,8 @@ export function reportingPluginFactory( exportTypesRegistry ); - const logger = LevelLogger.createForServer(__LEGACY, [PLUGIN_ID]); - const browserDriverFactory = await createBrowserDriverFactory(__LEGACY); + const logger = new LevelLogger(this.initializerContext.logger.get('reporting')); + const browserDriverFactory = await createBrowserDriverFactory(__LEGACY, logger); logConfiguration(__LEGACY, logger); runValidations(__LEGACY, logger, browserDriverFactory); @@ -103,5 +113,5 @@ export function reportingPluginFactory( public start(core: CoreStart, plugins: ReportingStartDeps): ReportingStart { return {}; } - })(); + })(initializerContext); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts index c9225dfee69788..d920015c4290c0 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts @@ -9,7 +9,7 @@ import boom from 'boom'; import Joi from 'joi'; import rison from 'rison-node'; import { API_BASE_URL } from '../../common/constants'; -import { ServerFacade, ReportingResponseToolkit } from '../../types'; +import { ServerFacade, ReportingResponseToolkit, Logger } from '../../types'; import { getRouteConfigFactoryReportingPre, GetRouteConfigFactoryFn, @@ -23,11 +23,13 @@ const BASE_GENERATE = `${API_BASE_URL}/generate`; export function registerGenerateFromJobParams( server: ServerFacade, handler: HandlerFunction, - handleError: HandlerErrorFunction + handleError: HandlerErrorFunction, + logger: Logger ) { const getRouteConfig = () => { const getOriginalRouteConfig: GetRouteConfigFactoryFn = getRouteConfigFactoryReportingPre( - server + server, + logger ); const routeConfigFactory: RouteConfigFactory = getOriginalRouteConfig( ({ params: { exportType } }) => exportType diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts index 2c509136b1b441..0da8e40ea29c0f 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts @@ -7,7 +7,7 @@ import { Legacy } from 'kibana'; import { get } from 'lodash'; import { API_BASE_GENERATE_V1, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../common/constants'; -import { ServerFacade, ReportingResponseToolkit } from '../../types'; +import { ServerFacade, ReportingResponseToolkit, Logger } from '../../types'; import { HandlerErrorFunction, HandlerFunction, QueuedJobPayload } from './types'; import { getRouteOptionsCsv } from './lib/route_config_factories'; import { makeRequestFacade } from './lib/make_request_facade'; @@ -25,9 +25,10 @@ import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject export function registerGenerateCsvFromSavedObject( server: ServerFacade, handleRoute: HandlerFunction, - handleRouteError: HandlerErrorFunction + handleRouteError: HandlerErrorFunction, + logger: Logger ) { - const routeOptions = getRouteOptionsCsv(server); + const routeOptions = getRouteOptionsCsv(server, logger); server.route({ path: `${API_BASE_GENERATE_V1}/csv/saved-object/{savedObjectType}:{savedObjectId}`, diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts index 8d1c84664cbe9d..60799b20ce4205 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts @@ -13,7 +13,7 @@ import { HeadlessChromiumDriverFactory, ReportingResponseToolkit, Logger, - JobDocOutputExecuted, + JobDocOutput, } from '../../types'; import { JobDocPayloadPanelCsv } from '../../export_types/csv_from_savedobject/types'; import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request'; @@ -33,7 +33,7 @@ export function registerGenerateCsvFromSavedObjectImmediate( server: ServerFacade, parentLogger: Logger ) { - const routeOptions = getRouteOptionsCsv(server); + const routeOptions = getRouteOptionsCsv(server, parentLogger); /* * CSV export with the `immediate` option does not queue a job with Reporting's ESQueue to run the job async. Instead, this does: @@ -55,8 +55,8 @@ export function registerGenerateCsvFromSavedObjectImmediate( * * Calling an execute job factory requires passing a browserDriverFactory option, so we should not call the factory from here */ - const createJobFn = createJobFactory(server); - const executeJobFn = executeJobFactory(server, { + const createJobFn = createJobFactory(server, logger); + const executeJobFn = executeJobFactory(server, logger, { browserDriverFactory: {} as HeadlessChromiumDriverFactory, }); const jobDocPayload: JobDocPayloadPanelCsv = await createJobFn( @@ -68,7 +68,7 @@ export function registerGenerateCsvFromSavedObjectImmediate( content_type: jobOutputContentType, content: jobOutputContent, size: jobOutputSize, - }: JobDocOutputExecuted = await executeJobFn(null, jobDocPayload, request); + }: JobDocOutput = await executeJobFn(null, jobDocPayload, request); logger.info(`Job output size: ${jobOutputSize} bytes`); diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.ts index 21af54ddf11e36..2a3102d0dd1590 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generation.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generation.ts @@ -31,8 +31,8 @@ export function registerJobGenerationRoutes( // @ts-ignore TODO const { errors: esErrors } = server.plugins.elasticsearch.getCluster('admin'); - const esqueue = createQueueFactory(server, { exportTypesRegistry, browserDriverFactory }); - const enqueueJob = enqueueJobFactory(server, { exportTypesRegistry, esqueue }); + const esqueue = createQueueFactory(server, logger, { exportTypesRegistry, browserDriverFactory }); + const enqueueJob = enqueueJobFactory(server, logger, { exportTypesRegistry, esqueue }); /* * Generates enqueued job details to use in responses @@ -47,7 +47,7 @@ export function registerJobGenerationRoutes( const user = request.pre.user; const headers = request.headers; - const job = await enqueueJob(logger, exportTypeId, jobParams, user, headers, request); + const job = await enqueueJob(exportTypeId, jobParams, user, headers, request); // return the queue's job information const jobJson = job.toJSON(); @@ -73,11 +73,11 @@ export function registerJobGenerationRoutes( return err; } - registerGenerateFromJobParams(server, handler, handleError); + registerGenerateFromJobParams(server, handler, handleError, logger); // Register beta panel-action download-related API's if (config.get('xpack.reporting.csv.enablePanelActionDownload')) { - registerGenerateCsvFromSavedObject(server, handler, handleError); + registerGenerateCsvFromSavedObject(server, handler, handleError, logger); registerGenerateCsvFromSavedObjectImmediate(server, logger); } } diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts index a0be15d60f3164..049ee0ce20ceb7 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import Boom from 'boom'; import { Legacy } from 'kibana'; -import boom from 'boom'; +import { ResponseObject } from 'hapi'; import { API_BASE_URL } from '../../common/constants'; import { ServerFacade, @@ -16,9 +17,7 @@ import { JobSource, ListQuery, } from '../../types'; -// @ts-ignore import { jobsQueryFactory } from '../lib/jobs_query'; -// @ts-ignore import { jobResponseHandlerFactory } from './lib/job_response_handler'; import { getRouteConfigFactoryDownloadPre, @@ -28,14 +27,18 @@ import { makeRequestFacade } from './lib/make_request_facade'; const MAIN_ENTRY = `${API_BASE_URL}/jobs`; +function isResponse(response: Boom | ResponseObject): response is ResponseObject { + return !(response as Boom).isBoom; +} + export function registerJobInfoRoutes( server: ServerFacade, exportTypesRegistry: ExportTypesRegistry, logger: Logger ) { const jobsQuery = jobsQueryFactory(server); - const getRouteConfig = getRouteConfigFactoryManagementPre(server); - const getRouteConfigDownload = getRouteConfigFactoryDownloadPre(server); + const getRouteConfig = getRouteConfigFactoryManagementPre(server, logger); + const getRouteConfigDownload = getRouteConfigFactoryDownloadPre(server, logger); // list jobs in the queue, paginated server.route({ @@ -82,17 +85,19 @@ export function registerJobInfoRoutes( const { docId } = request.params; return jobsQuery.get(request.pre.user, docId, { includeContent: true }).then( - ({ _source: job }: JobSource): JobDocOutput => { - if (!job) { - throw boom.notFound(); + (result): JobDocOutput => { + if (!result) { + throw Boom.notFound(); } + const { + _source: { jobtype: jobType, output: jobOutput }, + } = result; - const { jobtype: jobType } = job; if (!request.pre.management.jobTypes.includes(jobType)) { - throw boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); + throw Boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); } - return job.output; + return jobOutput; } ); }, @@ -107,26 +112,25 @@ export function registerJobInfoRoutes( const request = makeRequestFacade(legacyRequest); const { docId } = request.params; - return jobsQuery - .get(request.pre.user, docId) - .then(({ _source: job }: JobSource): JobSource['_source'] => { - if (!job) { - throw boom.notFound(); - } + return jobsQuery.get(request.pre.user, docId).then((result): JobSource['_source'] => { + if (!result) { + throw Boom.notFound(); + } - const { jobtype: jobType, payload } = job; - if (!request.pre.management.jobTypes.includes(jobType)) { - throw boom.unauthorized(`Sorry, you are not authorized to view ${jobType} info`); - } + const { _source: job } = result; + const { jobtype: jobType, payload: jobPayload } = job; + if (!request.pre.management.jobTypes.includes(jobType)) { + throw Boom.unauthorized(`Sorry, you are not authorized to view ${jobType} info`); + } - return { - ...job, - payload: { - ...payload, - headers: undefined, - }, - }; - }); + return { + ...job, + payload: { + ...jobPayload, + headers: undefined, + }, + }; + }); }, }); @@ -146,21 +150,22 @@ export function registerJobInfoRoutes( h, { docId } ); - const { statusCode } = response; - - if (statusCode !== 200) { - if (statusCode === 500) { - logger.error(`Report ${docId} has failed: ${JSON.stringify(response.source)}`); - } else { - logger.debug( - `Report ${docId} has non-OK status: [${statusCode}] Reason: [${JSON.stringify( - response.source - )}]` - ); + + if (isResponse(response)) { + const { statusCode } = response; + + if (statusCode !== 200) { + if (statusCode === 500) { + logger.error(`Report ${docId} has failed: ${JSON.stringify(response.source)}`); + } else { + logger.debug( + `Report ${docId} has non-OK status: [${statusCode}] Reason: [${JSON.stringify( + response.source + )}]` + ); + } } - } - if (!response.isBoom) { response = response.header('accept-ranges', 'none'); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.js b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.js deleted file mode 100644 index 79a5f1a4f6f5fe..00000000000000 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.js +++ /dev/null @@ -1,45 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import boom from 'boom'; -import { getUserFactory } from '../../lib/get_user'; - -const superuserRole = 'superuser'; - -export const authorizedUserPreRoutingFactory = function authorizedUserPreRoutingFn(server) { - const getUser = getUserFactory(server); - const config = server.config(); - - return async function authorizedUserPreRouting(request) { - const xpackInfo = server.plugins.xpack_main.info; - - if (!xpackInfo || !xpackInfo.isAvailable()) { - server.log( - ['reporting', 'authorizedUserPreRouting', 'debug'], - 'Unable to authorize user before xpack info is available.' - ); - return boom.notFound(); - } - - const security = xpackInfo.feature('security'); - if (!security.isEnabled() || !security.isAvailable()) { - return null; - } - - const user = await getUser(request); - - if (!user) { - return boom.unauthorized(`Sorry, you aren't authenticated`); - } - - const authorizedRoles = [superuserRole, ...config.get('xpack.reporting.roles.allow')]; - if (!user.roles.find(role => authorizedRoles.includes(role))) { - return boom.forbidden(`Sorry, you don't have access to Reporting`); - } - - return user; - }; -}; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.js similarity index 87% rename from x-pack/legacy/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js rename to x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.js index 0b2aff53793cdb..841f753f0c09b4 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.js @@ -5,8 +5,7 @@ */ import expect from '@kbn/expect'; -import sinon from 'sinon'; -import { authorizedUserPreRoutingFactory } from '../authorized_user_pre_routing'; +import { authorizedUserPreRoutingFactory } from './authorized_user_pre_routing'; describe('authorized_user_pre_routing', function() { // the getClientShield is using `once` which forces us to use a constant mock @@ -14,14 +13,14 @@ describe('authorized_user_pre_routing', function() { // so createMockServer reuses the same 'instance' of the server and overwrites // the properties to contain different values const createMockServer = (function() { - const getUserStub = sinon.stub(); + const getUserStub = jest.fn(); let mockConfig; const mockServer = { - expose: function() {}, - config: function() { + expose() {}, + config() { return { - get: function(key) { + get(key) { return mockConfig[key]; }, }; @@ -45,7 +44,7 @@ describe('authorized_user_pre_routing', function() { mockServer.plugins.xpack_main = { info: !xpackInfoUndefined && { isAvailable: () => xpackInfoAvailable, - feature: function(featureName) { + feature(featureName) { if (featureName === 'security') { return { isEnabled: () => securityEnabled, @@ -56,17 +55,18 @@ describe('authorized_user_pre_routing', function() { }, }; - getUserStub.resetHistory(); - getUserStub.resolves(user); + getUserStub.mockReset(); + getUserStub.mockResolvedValue(user); return mockServer; }; })(); + const getMockLogger = () => ({ warn: jest.fn() }); it('should return with boom notFound when xpackInfo is undefined', async function() { const mockServer = createMockServer({ xpackInfoUndefined: true }); - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); - const response = await authorizedUserPreRouting(); + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); + const response = await authorizedUserPreRouting({}); expect(response.isBoom).to.be(true); expect(response.output.statusCode).to.be(404); }); @@ -74,7 +74,7 @@ describe('authorized_user_pre_routing', function() { it(`should return with boom notFound when xpackInfo isn't available`, async function() { const mockServer = createMockServer({ xpackInfoAvailable: false }); - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); const response = await authorizedUserPreRouting(); expect(response.isBoom).to.be(true); expect(response.output.statusCode).to.be(404); @@ -83,7 +83,7 @@ describe('authorized_user_pre_routing', function() { it('should return with null user when security is disabled in Elasticsearch', async function() { const mockServer = createMockServer({ securityEnabled: false }); - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); const response = await authorizedUserPreRouting(); expect(response).to.be(null); }); @@ -91,7 +91,7 @@ describe('authorized_user_pre_routing', function() { it('should return with boom unauthenticated when security is enabled but no authenticated user', async function() { const mockServer = createMockServer({ user: null }); - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); const response = await authorizedUserPreRouting(); expect(response.isBoom).to.be(true); expect(response.output.statusCode).to.be(401); @@ -103,7 +103,7 @@ describe('authorized_user_pre_routing', function() { config: { 'xpack.reporting.roles.allow': ['.reporting_user'] }, }); - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); const response = await authorizedUserPreRouting(); expect(response.isBoom).to.be(true); expect(response.output.statusCode).to.be(403); @@ -116,7 +116,7 @@ describe('authorized_user_pre_routing', function() { config: { 'xpack.reporting.roles.allow': ['.reporting_user'] }, }); - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); const response = await authorizedUserPreRouting(); expect(response).to.be(user); }); @@ -128,7 +128,7 @@ describe('authorized_user_pre_routing', function() { config: { 'xpack.reporting.roles.allow': [] }, }); - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer, getMockLogger()); const response = await authorizedUserPreRouting(); expect(response).to.be(user); }); diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts new file mode 100644 index 00000000000000..906f266290a421 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/authorized_user_pre_routing.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import Boom from 'boom'; +import { Legacy } from 'kibana'; +import { AuthenticatedUser } from '../../../../../../plugins/security/server'; +import { getUserFactory } from '../../lib/get_user'; +import { ServerFacade, Logger } from '../../../types'; + +const superuserRole = 'superuser'; + +export type PreRoutingFunction = ( + request: Legacy.Request +) => Promise | AuthenticatedUser | null>; + +export const authorizedUserPreRoutingFactory = function authorizedUserPreRoutingFn( + server: ServerFacade, + logger: Logger +) { + const getUser = getUserFactory(server, logger); + const config = server.config(); + + return async function authorizedUserPreRouting(request: Legacy.Request) { + const xpackInfo = server.plugins.xpack_main.info; + + if (!xpackInfo || !xpackInfo.isAvailable()) { + logger.warn('Unable to authorize user before xpack info is available.', [ + 'authorizedUserPreRouting', + ]); + return Boom.notFound(); + } + + const security = xpackInfo.feature('security'); + if (!security.isEnabled() || !security.isAvailable()) { + return null; + } + + const user = await getUser(request); + + if (!user) { + return Boom.unauthorized(`Sorry, you aren't authenticated`); + } + + const authorizedRoles = [ + superuserRole, + ...(config.get('xpack.reporting.roles.allow') as string[]), + ]; + if (!user.roles.find(role => authorizedRoles.includes(role))) { + return Boom.forbidden(`Sorry, you don't have access to Reporting`); + } + + return user; + }; +}; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts index c3a30f9dda4543..1c0566100e1977 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/get_document_payload.ts @@ -11,8 +11,8 @@ import { ServerFacade, ExportTypesRegistry, ExportTypeDefinition, - JobDocExecuted, - JobDocOutputExecuted, + JobDocOutput, + JobSource, } from '../../../types'; import { CSV_JOB_TYPE } from '../../../common/constants'; @@ -20,14 +20,21 @@ interface ICustomHeaders { [x: string]: any; } -const DEFAULT_TITLE = 'report'; +type ExportTypeType = ExportTypeDefinition; + +interface Payload { + statusCode: number; + content: any; + contentType: string; + headers: Record; +} -type ExportTypeType = ExportTypeDefinition; +const DEFAULT_TITLE = 'report'; const getTitle = (exportType: ExportTypeType, title?: string): string => `${title || DEFAULT_TITLE}.${exportType.jobContentExtension}`; -const getReportingHeaders = (output: JobDocOutputExecuted, exportType: ExportTypeType) => { +const getReportingHeaders = (output: JobDocOutput, exportType: ExportTypeType) => { const metaDataHeaders: ICustomHeaders = {}; if (exportType.jobType === CSV_JOB_TYPE) { @@ -54,7 +61,7 @@ export function getDocumentPayloadFactory( } } - function getCompleted(output: JobDocOutputExecuted, jobType: string, title: string) { + function getCompleted(output: JobDocOutput, jobType: string, title: string) { const exportType = exportTypesRegistry.get((item: ExportTypeType) => item.jobType === jobType); const filename = getTitle(exportType, title); const headers = getReportingHeaders(output, exportType); @@ -70,7 +77,7 @@ export function getDocumentPayloadFactory( }; } - function getFailure(output: JobDocOutputExecuted) { + function getFailure(output: JobDocOutput) { return { statusCode: 500, content: { @@ -78,6 +85,7 @@ export function getDocumentPayloadFactory( reason: output.content, }, contentType: 'application/json', + headers: {}, }; } @@ -90,9 +98,7 @@ export function getDocumentPayloadFactory( }; } - return function getDocumentPayload(doc: { - _source: JobDocExecuted<{ output: JobDocOutputExecuted }>; - }) { + return function getDocumentPayload(doc: JobSource): Payload { const { status, jobtype: jobType, payload: { title } = { title: '' } } = doc._source; const { output } = doc._source; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.js b/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.js deleted file mode 100644 index e2da3235461136..00000000000000 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.js +++ /dev/null @@ -1,48 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import boom from 'boom'; -import { jobsQueryFactory } from '../../lib/jobs_query'; -import { WHITELISTED_JOB_CONTENT_TYPES } from '../../../common/constants'; -import { getDocumentPayloadFactory } from './get_document_payload'; - -export function jobResponseHandlerFactory(server, exportTypesRegistry) { - const jobsQuery = jobsQueryFactory(server); - const getDocumentPayload = getDocumentPayloadFactory(server, exportTypesRegistry); - - return function jobResponseHandler(validJobTypes, user, h, params, opts = {}) { - const { docId } = params; - return jobsQuery.get(user, docId, { includeContent: !opts.excludeContent }).then(doc => { - if (!doc) return boom.notFound(); - - const { jobtype: jobType } = doc._source; - if (!validJobTypes.includes(jobType)) { - return boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); - } - - const output = getDocumentPayload(doc); - - if (!WHITELISTED_JOB_CONTENT_TYPES.includes(output.contentType)) { - return boom.badImplementation( - `Unsupported content-type of ${output.contentType} specified by job output` - ); - } - - const response = h - .response(output.content) - .type(output.contentType) - .code(output.statusCode); - - if (output.headers) { - Object.keys(output.headers).forEach(key => { - response.header(key, output.headers[key]); - }); - } - - return response; - }); - }; -} diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts new file mode 100644 index 00000000000000..3ba7aa30eedcb7 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/job_response_handler.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import Boom from 'boom'; +import { ResponseToolkit } from 'hapi'; +import { ServerFacade, ExportTypesRegistry } from '../../../types'; +import { jobsQueryFactory } from '../../lib/jobs_query'; +import { WHITELISTED_JOB_CONTENT_TYPES } from '../../../common/constants'; +import { getDocumentPayloadFactory } from './get_document_payload'; + +interface JobResponseHandlerParams { + docId: string; +} + +interface JobResponseHandlerOpts { + excludeContent?: boolean; +} + +export function jobResponseHandlerFactory( + server: ServerFacade, + exportTypesRegistry: ExportTypesRegistry +) { + const jobsQuery = jobsQueryFactory(server); + const getDocumentPayload = getDocumentPayloadFactory(server, exportTypesRegistry); + + return function jobResponseHandler( + validJobTypes: string[], + user: any, + h: ResponseToolkit, + params: JobResponseHandlerParams, + opts: JobResponseHandlerOpts = {} + ) { + const { docId } = params; + return jobsQuery.get(user, docId, { includeContent: !opts.excludeContent }).then(doc => { + if (!doc) return Boom.notFound(); + + const { jobtype: jobType } = doc._source; + if (!validJobTypes.includes(jobType)) { + return Boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); + } + + const output = getDocumentPayload(doc); + + if (!WHITELISTED_JOB_CONTENT_TYPES.includes(output.contentType)) { + return Boom.badImplementation( + `Unsupported content-type of ${output.contentType} specified by job output` + ); + } + + const response = h + .response(output.content) + .type(output.contentType) + .code(output.statusCode); + + if (output.headers) { + Object.keys(output.headers).forEach(key => { + response.header(key, output.headers[key]); + }); + } + + return response; // Hapi + }); + }; +} diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.js b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.js deleted file mode 100644 index 92973e3d0b4220..00000000000000 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.js +++ /dev/null @@ -1,26 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; - -export const reportingFeaturePreRoutingFactory = function reportingFeaturePreRoutingFn(server) { - const xpackMainPlugin = server.plugins.xpack_main; - const pluginId = 'reporting'; - - // License checking and enable/disable logic - return function reportingFeaturePreRouting(getReportingFeatureId) { - return function licensePreRouting(request) { - const licenseCheckResults = xpackMainPlugin.info.feature(pluginId).getLicenseCheckResults(); - const reportingFeatureId = getReportingFeatureId(request); - const reportingFeature = licenseCheckResults[reportingFeatureId]; - if (!reportingFeature.showLinks || !reportingFeature.enableLinks) { - throw Boom.forbidden(reportingFeature.message); - } else { - return reportingFeature; - } - }; - }; -}; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts new file mode 100644 index 00000000000000..88c5e4edc12f87 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/reporting_feature_pre_routing.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import Boom from 'boom'; +import { Legacy } from 'kibana'; +import { Logger, ServerFacade } from '../../../types'; + +export type GetReportingFeatureIdFn = (request: Legacy.Request) => string; + +export const reportingFeaturePreRoutingFactory = function reportingFeaturePreRoutingFn( + server: ServerFacade, + logger: Logger +) { + const xpackMainPlugin = server.plugins.xpack_main; + const pluginId = 'reporting'; + + // License checking and enable/disable logic + return function reportingFeaturePreRouting(getReportingFeatureId: GetReportingFeatureIdFn) { + return function licensePreRouting(request: Legacy.Request) { + const licenseCheckResults = xpackMainPlugin.info.feature(pluginId).getLicenseCheckResults(); + const reportingFeatureId = getReportingFeatureId(request) as string; + const reportingFeature = licenseCheckResults[reportingFeatureId]; + if (!reportingFeature.showLinks || !reportingFeature.enableLinks) { + throw Boom.forbidden(reportingFeature.message); + } else { + return reportingFeature; + } + }; + }; +}; diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts index 29ded68d403c58..25c08261490d56 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts @@ -6,11 +6,10 @@ import Joi from 'joi'; import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; -import { ServerFacade, RequestFacade } from '../../../types'; -// @ts-ignore +import { ServerFacade, Logger } from '../../../types'; import { authorizedUserPreRoutingFactory } from './authorized_user_pre_routing'; -// @ts-ignore import { reportingFeaturePreRoutingFactory } from './reporting_feature_pre_routing'; +import { GetReportingFeatureIdFn } from './reporting_feature_pre_routing'; const API_TAG = 'api'; @@ -22,19 +21,19 @@ export interface RouteConfigFactory { }; } -type GetFeatureFunction = (request: RequestFacade) => any; -type PreRoutingFunction = (getFeatureId?: GetFeatureFunction) => any; - export type GetRouteConfigFactoryFn = ( - getFeatureId?: GetFeatureFunction | undefined + getFeatureId?: GetReportingFeatureIdFn ) => RouteConfigFactory; -export function getRouteConfigFactoryReportingPre(server: ServerFacade): GetRouteConfigFactoryFn { - const authorizedUserPreRouting: PreRoutingFunction = authorizedUserPreRoutingFactory(server); - const reportingFeaturePreRouting: PreRoutingFunction = reportingFeaturePreRoutingFactory(server); +export function getRouteConfigFactoryReportingPre( + server: ServerFacade, + logger: Logger +): GetRouteConfigFactoryFn { + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server, logger); + const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server, logger); - return (getFeatureId?: GetFeatureFunction): RouteConfigFactory => { - const preRouting = [{ method: authorizedUserPreRouting, assign: 'user' }]; + return (getFeatureId?: GetReportingFeatureIdFn): RouteConfigFactory => { + const preRouting: any[] = [{ method: authorizedUserPreRouting, assign: 'user' }]; if (getFeatureId) { preRouting.push(reportingFeaturePreRouting(getFeatureId)); } @@ -46,8 +45,8 @@ export function getRouteConfigFactoryReportingPre(server: ServerFacade): GetRout }; } -export function getRouteOptionsCsv(server: ServerFacade) { - const getRouteConfig = getRouteConfigFactoryReportingPre(server); +export function getRouteOptionsCsv(server: ServerFacade, logger: Logger) { + const getRouteConfig = getRouteConfigFactoryReportingPre(server, logger); return { ...getRouteConfig(() => CSV_FROM_SAVEDOBJECT_JOB_TYPE), validate: { @@ -67,9 +66,12 @@ export function getRouteOptionsCsv(server: ServerFacade) { }; } -export function getRouteConfigFactoryManagementPre(server: ServerFacade): GetRouteConfigFactoryFn { - const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server); - const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server); +export function getRouteConfigFactoryManagementPre( + server: ServerFacade, + logger: Logger +): GetRouteConfigFactoryFn { + const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server, logger); + const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server, logger); const managementPreRouting = reportingFeaturePreRouting(() => 'management'); return (): RouteConfigFactory => { @@ -87,8 +89,11 @@ export function getRouteConfigFactoryManagementPre(server: ServerFacade): GetRou // TOC at the end of the PDF, but it's sending multiple cookies and causing our auth to fail with a 401. // Additionally, the range-request doesn't alleviate any performance issues on the server as the entire // download is loaded into memory. -export function getRouteConfigFactoryDownloadPre(server: ServerFacade): GetRouteConfigFactoryFn { - const getManagementRouteConfig = getRouteConfigFactoryManagementPre(server); +export function getRouteConfigFactoryDownloadPre( + server: ServerFacade, + logger: Logger +): GetRouteConfigFactoryFn { + const getManagementRouteConfig = getRouteConfigFactoryManagementPre(server, logger); return (): RouteConfigFactory => ({ ...getManagementRouteConfig(), tags: [API_TAG], diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 9fae60afee4e82..9ba016d8b828d8 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -7,10 +7,7 @@ import { ResponseObject } from 'hapi'; import { EventEmitter } from 'events'; import { Legacy } from 'kibana'; -import { - ElasticsearchPlugin, - CallCluster, -} from '../../../../src/legacy/core_plugins/elasticsearch'; +import { CallCluster } from '../../../../src/legacy/core_plugins/elasticsearch'; import { CancellationToken } from './common/cancellation_token'; import { LevelLogger } from './server/lib/level_logger'; import { HeadlessChromiumDriverFactory } from './server/browsers/chromium/driver_factory'; @@ -74,7 +71,6 @@ export type ServerFacade = LegacySetup; export type ReportingPluginSpecOptions = Legacy.PluginSpecOptions; export type EnqueueJobFn = ( - parentLogger: LevelLogger, exportTypeId: string, jobParams: JobParamsType, user: string, @@ -200,18 +196,6 @@ export interface JobDocPayload { type: string | null; } -export interface JobDocOutput { - content: string; // encoded content - contentType: string; -} - -export interface JobDocExecuted { - jobtype: string; - output: JobDocOutputExecuted; - payload: JobDocPayload; - status: string; // completed, failed, etc -} - export interface JobSource { _id: string; _source: { @@ -222,21 +206,9 @@ export interface JobSource { }; } -/* - * A snake_cased field is the only significant difference in structure of - * JobDocOutputExecuted vs JobDocOutput. - * - * JobDocOutput is the structure of the object returned by getDocumentPayload - * - * data in the _source fields of the - * Reporting index. - * - * The ESQueueWorker internals have executed job objects returned with this - * structure. See `_formatOutput` in reporting/server/lib/esqueue/worker.js - */ -export interface JobDocOutputExecuted { - content_type: string; // vs `contentType` above - content: string | null; // defaultOutput is null +export interface JobDocOutput { + content_type: string; + content: string | null; max_size_reached: boolean; size: number; } @@ -279,7 +251,7 @@ export type ImmediateExecuteFn = ( jobId: null, job: JobDocPayload, request: RequestFacade -) => Promise; +) => Promise; export interface ESQueueWorkerOptions { kibanaName: string; @@ -292,7 +264,7 @@ export interface ESQueueWorkerOptions { type GenericWorkerFn = ( jobSource: JobSource, ...workerRestArgs: any[] -) => void | Promise; +) => void | Promise; export interface ESQueueInstance { registerWorker: ( @@ -302,9 +274,13 @@ export interface ESQueueInstance { ) => ESQueueWorker; } -export type CreateJobFactory = (server: ServerFacade) => CreateJobFnType; +export type CreateJobFactory = ( + server: ServerFacade, + logger: LevelLogger +) => CreateJobFnType; export type ExecuteJobFactory = ( server: ServerFacade, + logger: LevelLogger, opts: { browserDriverFactory: HeadlessChromiumDriverFactory; } diff --git a/x-pack/legacy/plugins/rollup/public/search/register.js b/x-pack/legacy/plugins/rollup/public/search/register.js index f7f1c681b63caa..05db100088e8a9 100644 --- a/x-pack/legacy/plugins/rollup/public/search/register.js +++ b/x-pack/legacy/plugins/rollup/public/search/register.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { addSearchStrategy } from '../../../../../../src/legacy/ui/public/courier'; +import { addSearchStrategy } from '../../../../../../src/plugins/data/public'; import { rollupSearchStrategy } from './rollup_search_strategy'; export function initSearch() { diff --git a/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.js b/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.js index becaf6dd338c8b..18e72cdf0fd3dc 100644 --- a/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.js +++ b/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.js @@ -5,7 +5,7 @@ */ import { kfetch } from 'ui/kfetch'; -import { SearchError, getSearchErrorType } from '../../../../../../src/legacy/ui/public/courier'; +import { SearchError, getSearchErrorType } from '../../../../../../src/plugins/data/public'; function serializeFetchParams(searchRequests) { return JSON.stringify( diff --git a/x-pack/legacy/plugins/searchprofiler/README.md b/x-pack/legacy/plugins/searchprofiler/README.md deleted file mode 100644 index 1dec1bb4e54504..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Profiler - -A UI for the query and aggregation profiler in Elasticsearch - -## Development - -Assuming you've checked out x-plugins next to kibana... - -- Run `yarn kbn bootstrap` -- Run `yarn start` to watch for and sync files on change -- Open a new terminal to run Kibana - use `yarn start` to launch it in dev mode - - Kibana will automatically restart as files are synced - - If you need debugging output, run `DEBUG=reporting yarn start` instead - -If you have installed this somewhere other than via x-plugins, and next to the kibana repo, you'll need to change the `pathToKibana` setting in `gulpfile.js` - -## Testing - -To run the server tests, change into `x-plugins/kibana` and run: - -```bash -mocha --debug --compilers js:@babel/register plugins/profiler/**/__tests__/**/*.js -``` - - ---kbnServer.tests_bundle.pluginId diff --git a/x-pack/legacy/plugins/searchprofiler/index.ts b/x-pack/legacy/plugins/searchprofiler/index.ts index 834f331cd7bf41..fab2e438473488 100644 --- a/x-pack/legacy/plugins/searchprofiler/index.ts +++ b/x-pack/legacy/plugins/searchprofiler/index.ts @@ -5,12 +5,10 @@ */ import { resolve } from 'path'; -import Boom from 'boom'; -import { CoreSetup } from 'src/core/server'; -import { Server } from 'src/legacy/server/kbn_server'; -import { LegacySetup } from './server/np_ready/types'; -import { plugin } from './server/np_ready'; +// TODO: +// Until we can process SCSS in new platform, this part of Searchprofiler +// legacy must remain here. export const searchprofiler = (kibana: any) => { const publicSrc = resolve(__dirname, 'public'); @@ -22,43 +20,8 @@ export const searchprofiler = (kibana: any) => { publicDir: publicSrc, uiExports: { - // NP Ready - devTools: [`${publicSrc}/legacy`], - styleSheetPaths: `${publicSrc}/np_ready/application/index.scss`, - // Legacy - home: ['plugins/searchprofiler/register_feature'], - }, - init(server: Server) { - const serverPlugin = plugin(); - const thisPlugin = this; - - const commonRouteConfig = { - pre: [ - function forbidApiAccess() { - const licenseCheckResults = server.plugins.xpack_main.info - .feature(thisPlugin.id) - .getLicenseCheckResults(); - if (licenseCheckResults.showAppLink && licenseCheckResults.enableAppLink) { - return null; - } else { - throw Boom.forbidden(licenseCheckResults.message); - } - }, - ], - }; - - const legacySetup: LegacySetup = { - route: (args: Parameters[0]) => server.route(args), - plugins: { - __LEGACY: { - thisPlugin, - xpackMain: server.plugins.xpack_main, - elasticsearch: server.plugins.elasticsearch, - commonRouteConfig, - }, - }, - }; - serverPlugin.setup({} as CoreSetup, legacySetup); + styleSheetPaths: `${publicSrc}/index.scss`, }, + init() {}, }); }; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.scss b/x-pack/legacy/plugins/searchprofiler/public/index.scss similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.scss rename to x-pack/legacy/plugins/searchprofiler/public/index.scss diff --git a/x-pack/legacy/plugins/searchprofiler/public/legacy.ts b/x-pack/legacy/plugins/searchprofiler/public/legacy.ts deleted file mode 100644 index b767705e025a00..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/legacy.ts +++ /dev/null @@ -1,28 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -/* eslint-disable @kbn/eslint/no-restricted-paths */ -import { npSetup } from 'ui/new_platform'; -import { I18nContext } from 'ui/i18n'; -// @ts-ignore -import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; -// @ts-ignore -import { formatAngularHttpError } from 'ui/notify/lib'; -import 'ui/autoload/all'; - -import { plugin } from './np_ready'; - -const pluginInstance = plugin({} as any); - -pluginInstance.setup(npSetup.core, { - ...npSetup.plugins, - __LEGACY: { - I18nContext, - licenseEnabled: xpackInfo.get('features.searchprofiler.enableAppLink'), - notifications: npSetup.core.notifications.toasts, - formatAngularHttpError, - }, -}); diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/boot.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/boot.tsx deleted file mode 100644 index fa02124f8a2454..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/boot.tsx +++ /dev/null @@ -1,26 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import { render, unmountComponentAtNode } from 'react-dom'; -import React from 'react'; -import { HttpStart as Http, ToastsSetup } from 'src/core/public'; -import { App } from '.'; - -export interface Dependencies { - el: HTMLElement; - http: Http; - licenseEnabled: boolean; - I18nContext: any; - notifications: ToastsSetup; - formatAngularHttpError: any; -} - -export type AppDependencies = Omit; - -export function boot(deps: Dependencies): () => void { - const { el, ...rest } = deps; - render(, deps.el); - return () => unmountComponentAtNode(deps.el); -} diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/profile_tree.test.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/profile_tree.test.tsx deleted file mode 100644 index ca95ac97e260a9..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/profile_tree.test.tsx +++ /dev/null @@ -1,21 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { registerTestBed } from '../../../../../../../../../test_utils'; -import { searchResponse } from './fixtures/search_response'; -import { ProfileTree, Props } from '../profile_tree'; - -describe('ProfileTree', () => { - it('renders', async () => { - const props: Props = { - onHighlight: () => {}, - target: 'searches', - data: searchResponse, - }; - const init = registerTestBed(ProfileTree); - await init(props); - }); -}); diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/app_context.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/app_context.tsx deleted file mode 100644 index 7f8a6cf01dcb27..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/app_context.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useContext, createContext } from 'react'; -import { HttpSetup, ToastsSetup } from 'kibana/public'; - -export interface ContextValue { - http: HttpSetup; - notifications: ToastsSetup; - licenseEnabled: boolean; - formatAngularHttpError: (error: any) => string; -} - -const AppContext = createContext(null as any); - -export const AppContextProvider = ({ - children, - value, -}: { - children: React.ReactNode; - value: ContextValue; -}) => { - return {children}; -}; - -export const useAppContext = () => { - const ctx = useContext(AppContext); - if (ctx == null) { - throw new Error(`useAppContext must be called inside AppContextProvider`); - } - return ctx; -}; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/use_request_profile.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/use_request_profile.ts deleted file mode 100644 index 34b49be7dc39c6..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/use_request_profile.ts +++ /dev/null @@ -1,77 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import { i18n } from '@kbn/i18n'; - -import { useAppContext } from '../contexts/app_context'; -import { checkForParseErrors } from '../utils'; -import { ShardSerialized } from '../types'; - -interface Args { - query: string; - index: string; -} - -interface ReturnValue { - data: ShardSerialized[] | null; - error?: string; -} - -export const useRequestProfile = () => { - const { http, notifications, formatAngularHttpError, licenseEnabled } = useAppContext(); - return async ({ query, index }: Args): Promise => { - if (!licenseEnabled) { - return { data: null }; - } - const { error, parsed } = checkForParseErrors(query); - if (error) { - notifications.addError(error, { - title: i18n.translate('xpack.searchProfiler.errorToastTitle', { - defaultMessage: 'JSON parse error', - }), - }); - return { data: null }; - } - // Shortcut the network request if we have json with shards already... - if (parsed.profile && parsed.profile.shards) { - return { data: parsed.profile.shards }; - } - - const payload: Record = { query }; - - if (index == null || index === '') { - payload.index = '_all'; - } else { - payload.index = index; - } - - try { - const resp = await http.post('../api/searchprofiler/profile', { - body: JSON.stringify(payload), - headers: { 'Content-Type': 'application/json' }, - }); - - if (!resp.ok) { - return { data: null, error: resp.err.msg }; - } - - return { data: resp.resp.profile.shards }; - } catch (e) { - try { - // Is this a known error type? - const errorString = formatAngularHttpError(e); - notifications.addError(e, { title: errorString }); - } catch (_) { - // Otherwise just report the original error - notifications.addError(e, { - title: i18n.translate('xpack.searchProfiler.errorSomethingWentWrongTitle', { - defaultMessage: 'Something went wrong', - }), - }); - } - return { data: null }; - } - }; -}; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.tsx b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.tsx deleted file mode 100644 index d29f193ce9d90d..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import { Main } from './containers'; -import { AppContextProvider } from './contexts/app_context'; -import { ProfileContextProvider } from './contexts/profiler_context'; - -import { AppDependencies } from './boot'; - -export function App({ - I18nContext, - licenseEnabled, - notifications, - http, - formatAngularHttpError, -}: AppDependencies) { - return ( - - - -
    - - - - ); -} diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/reducer.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/reducer.ts deleted file mode 100644 index 394110ac495246..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/reducer.ts +++ /dev/null @@ -1,64 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Reducer } from 'react'; -import { State } from './store'; - -import { OnHighlightChangeArgs } from '../components/profile_tree'; -import { ShardSerialized, Targets } from '../types'; - -export type Action = - | { type: 'setProfiling'; value: boolean } - | { type: 'setHighlightDetails'; value: OnHighlightChangeArgs | null } - | { type: 'setActiveTab'; value: Targets | null } - | { type: 'setCurrentResponse'; value: ShardSerialized[] | null }; - -export const reducer: Reducer = (state, action) => { - const nextState = { ...state }; - - if (action.type === 'setProfiling') { - nextState.pristine = false; - nextState.profiling = action.value; - if (nextState.profiling) { - nextState.currentResponse = null; - nextState.highlightDetails = null; - } - return nextState; - } - - if (action.type === 'setHighlightDetails') { - if (action.value) { - const value = action.value; - // Exclude children to avoid unnecessary work copying a recursive structure. - const { children, parent, ...restOfOperation } = value.operation; - nextState.highlightDetails = { - indexName: value.indexName, - operation: Object.freeze(restOfOperation), - // prettier-ignore - shardName: `[${/* shard id */value.shard.id[0]}][${/* shard number */value.shard.id[2] }]` - }; - } else { - nextState.highlightDetails = null; - } - return nextState; - } - - if (action.type === 'setActiveTab') { - nextState.activeTab = action.value; - return nextState; - } - - if (action.type === 'setCurrentResponse') { - nextState.currentResponse = action.value; - if (nextState.currentResponse) { - // Default to the searches tab - nextState.activeTab = 'searches'; - } - return nextState; - } - - throw new Error(`Unknown action: ${action}`); -}; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/index.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/index.ts deleted file mode 100644 index 556a03fc96fe35..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { checkForParseErrors } from './check_for_json_errors'; -export { msToPretty } from './ms_to_pretty'; -export { nsToPretty } from './ns_to_pretty'; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts b/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts deleted file mode 100644 index f2acc97e55a705..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/plugin.ts +++ /dev/null @@ -1,62 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { - Plugin, - CoreStart, - CoreSetup, - PluginInitializerContext, - ToastsStart, -} from 'src/core/public'; - -import { DevToolsSetup } from '../../../../../../src/plugins/dev_tools/public'; - -export class SearchProfilerUIPlugin implements Plugin { - constructor(ctx: PluginInitializerContext) {} - - async setup( - core: CoreSetup, - plugins: { - __LEGACY: { - I18nContext: any; - licenseEnabled: boolean; - notifications: ToastsStart; - formatAngularHttpError: any; - }; - dev_tools: DevToolsSetup; - } - ) { - const { http } = core; - const { - __LEGACY: { I18nContext, licenseEnabled, notifications, formatAngularHttpError }, - dev_tools, - } = plugins; - dev_tools.register({ - id: 'searchprofiler', - title: i18n.translate('xpack.searchProfiler.pageDisplayName', { - defaultMessage: 'Search Profiler', - }), - order: 5, - enableRouting: false, - async mount(ctx, params) { - const { boot } = await import('./application/boot'); - return boot({ - http, - licenseEnabled, - el: params.element, - I18nContext, - notifications, - formatAngularHttpError, - }); - }, - }); - } - - async start(core: CoreStart, plugins: any) {} - - async stop() {} -} diff --git a/x-pack/legacy/plugins/searchprofiler/public/register_feature.js b/x-pack/legacy/plugins/searchprofiler/public/register_feature.js deleted file mode 100644 index 2a4218e2527c7c..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/public/register_feature.js +++ /dev/null @@ -1,28 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - FeatureCatalogueRegistryProvider, - FeatureCatalogueCategory, -} from 'ui/registry/feature_catalogue'; - -import { i18n } from '@kbn/i18n'; - -FeatureCatalogueRegistryProvider.register(() => { - return { - id: 'searchprofiler', - title: i18n.translate('xpack.searchProfiler.registryProviderTitle', { - defaultMessage: 'Search Profiler', - }), - description: i18n.translate('xpack.searchProfiler.registryProviderDescription', { - defaultMessage: 'Quickly check the performance of any Elasticsearch query.', - }), - icon: 'searchProfilerApp', - path: '/app/kibana#/dev_tools/searchprofiler', - showOnHomePage: false, - category: FeatureCatalogueCategory.ADMIN, - }; -}); diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_index.scss b/x-pack/legacy/plugins/searchprofiler/public/styles/_index.scss similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_index.scss rename to x-pack/legacy/plugins/searchprofiler/public/styles/_index.scss diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_mixins.scss b/x-pack/legacy/plugins/searchprofiler/public/styles/_mixins.scss similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/_mixins.scss rename to x-pack/legacy/plugins/searchprofiler/public/styles/_mixins.scss diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_highlight_details_flyout.scss b/x-pack/legacy/plugins/searchprofiler/public/styles/components/_highlight_details_flyout.scss similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_highlight_details_flyout.scss rename to x-pack/legacy/plugins/searchprofiler/public/styles/components/_highlight_details_flyout.scss diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_percentage_badge.scss b/x-pack/legacy/plugins/searchprofiler/public/styles/components/_percentage_badge.scss similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_percentage_badge.scss rename to x-pack/legacy/plugins/searchprofiler/public/styles/components/_percentage_badge.scss diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_profile_tree.scss b/x-pack/legacy/plugins/searchprofiler/public/styles/components/_profile_tree.scss similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/components/_profile_tree.scss rename to x-pack/legacy/plugins/searchprofiler/public/styles/components/_profile_tree.scss diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_main.scss b/x-pack/legacy/plugins/searchprofiler/public/styles/containers/_main.scss similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_main.scss rename to x-pack/legacy/plugins/searchprofiler/public/styles/containers/_main.scss diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_profile_query_editor.scss b/x-pack/legacy/plugins/searchprofiler/public/styles/containers/_profile_query_editor.scss similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/styles/containers/_profile_query_editor.scss rename to x-pack/legacy/plugins/searchprofiler/public/styles/containers/_profile_query_editor.scss diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/index.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/index.ts deleted file mode 100644 index 9253a0d6b15242..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/server/np_ready/index.ts +++ /dev/null @@ -1,10 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import { SearchProfilerServerPlugin } from './plugin'; - -export const plugin = () => { - return new SearchProfilerServerPlugin(); -}; diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.test.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.test.ts deleted file mode 100644 index 1b8155221cb9d1..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.test.ts +++ /dev/null @@ -1,81 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { set } from 'lodash'; -import { checkLicense } from './check_license'; - -describe('check_license', () => { - let mockLicenseInfo: any; - beforeEach(() => (mockLicenseInfo = {})); - - describe('license information is not available', () => { - beforeEach(() => (mockLicenseInfo.isAvailable = () => false)); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showAppLink).to.be(true); - }); - - it('should set enableLinks to false', () => { - expect(checkLicense(mockLicenseInfo).enableAppLink).to.be(false); - }); - }); - - describe('license information is available', () => { - beforeEach(() => { - mockLicenseInfo.isAvailable = () => true; - set(mockLicenseInfo, 'license.getType', () => 'basic'); - }); - - describe('& license is > basic', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => true)); - - describe('& license is active', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true)); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showAppLink).to.be(true); - }); - - it('should set enableLinks to true', () => { - expect(checkLicense(mockLicenseInfo).enableAppLink).to.be(true); - }); - }); - - describe('& license is expired', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false)); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showAppLink).to.be(true); - }); - - it('should set enableLinks to false', () => { - expect(checkLicense(mockLicenseInfo).enableAppLink).to.be(false); - }); - }); - }); - - describe('& license is basic', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => false)); - - describe('& license is active', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true)); - - it('should set showLinks to false', () => { - expect(checkLicense(mockLicenseInfo).showAppLink).to.be(false); - }); - }); - - describe('& license is expired', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false)); - - it('should set showLinks to false', () => { - expect(checkLicense(mockLicenseInfo).showAppLink).to.be(false); - }); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.ts deleted file mode 100644 index 2a22d615ca6e54..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/check_license.ts +++ /dev/null @@ -1,59 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { XPackInfo } from '../../../../xpack_main/server/lib/xpack_info'; - -export function checkLicense( - xpackLicenseInfo: XPackInfo -): { showAppLink: boolean; enableAppLink: boolean; message: string | undefined } { - if (!xpackLicenseInfo || !xpackLicenseInfo.isAvailable()) { - return { - showAppLink: true, - enableAppLink: false, - message: i18n.translate('xpack.searchProfiler.unavailableLicenseInformationMessage', { - defaultMessage: - 'Search Profiler is unavailable - license information is not available at this time.', - }), - }; - } - - const isLicenseActive = xpackLicenseInfo.license.isActive(); - let message: string | undefined; - if (!isLicenseActive) { - message = i18n.translate('xpack.searchProfiler.licenseHasExpiredMessage', { - defaultMessage: 'Search Profiler is unavailable - license has expired.', - }); - } - - if ( - xpackLicenseInfo.license.isOneOf([ - 'trial', - 'basic', - 'standard', - 'gold', - 'platinum', - 'enterprise', - ]) - ) { - return { - showAppLink: true, - enableAppLink: isLicenseActive, - message, - }; - } - - message = i18n.translate('xpack.searchProfiler.upgradeLicenseMessage', { - defaultMessage: - 'Search Profiler is unavailable for the current {licenseInfo} license. Please upgrade your license.', - values: { licenseInfo: xpackLicenseInfo.license.getType() }, - }); - return { - showAppLink: false, - enableAppLink: false, - message, - }; -} diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/index.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/index.ts deleted file mode 100644 index f2c070fd44b6e6..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/server/np_ready/lib/index.ts +++ /dev/null @@ -1,7 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { checkLicense } from './check_license'; diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/plugin.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/plugin.ts deleted file mode 100644 index e00e2829f980d2..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/server/np_ready/plugin.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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { CoreSetup, Plugin } from 'src/core/server'; -import { LegacySetup } from './types'; -import { checkLicense } from './lib'; -// @ts-ignore -import { mirrorPluginStatus } from '../../../../server/lib/mirror_plugin_status'; - -import * as profileRoute from './routes/profile'; - -export class SearchProfilerServerPlugin implements Plugin { - async setup( - core: CoreSetup, - { - route, - plugins: { - __LEGACY: { thisPlugin, elasticsearch, xpackMain, commonRouteConfig }, - }, - }: LegacySetup - ) { - mirrorPluginStatus(xpackMain, thisPlugin); - (xpackMain as any).status.once('green', () => { - // Register a function that is called whenever the xpack info changes, - // to re-compute the license check results for this plugin - xpackMain.info.feature(thisPlugin.id).registerLicenseCheckResultsGenerator(checkLicense); - }); - - profileRoute.register({ elasticsearch }, route, commonRouteConfig); - } - - async start() {} - - stop(): void {} -} diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/routes/profile.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/routes/profile.ts deleted file mode 100644 index 082307b5a7a2be..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/server/np_ready/routes/profile.ts +++ /dev/null @@ -1,53 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import Joi from 'joi'; -import { RequestShim, ServerShim, RegisterRoute } from '../types'; - -export const handler = async (server: ServerShim, request: RequestShim) => { - const { callWithRequest } = server.elasticsearch.getCluster('data'); - let parsed = request.payload.query; - parsed.profile = true; - parsed = JSON.stringify(parsed, null, 2); - - const body = { - index: request.payload.index, - body: parsed, - }; - try { - const resp = await callWithRequest(request, 'search', body); - return { - ok: true, - resp, - }; - } catch (err) { - return { - ok: false, - err, - }; - } -}; - -export const register = (server: ServerShim, route: RegisterRoute, commonConfig: any) => { - route({ - path: '/api/searchprofiler/profile', - method: 'POST', - config: { - ...commonConfig, - validate: { - payload: Joi.object() - .keys({ - query: Joi.object().required(), - index: Joi.string().required(), - type: Joi.string().optional(), - }) - .required(), - }, - }, - handler: req => { - return handler(server, { headers: req.headers, payload: req.payload as any }); - }, - }); -}; diff --git a/x-pack/legacy/plugins/searchprofiler/server/np_ready/types.ts b/x-pack/legacy/plugins/searchprofiler/server/np_ready/types.ts deleted file mode 100644 index 9b25f8bb36b0cf..00000000000000 --- a/x-pack/legacy/plugins/searchprofiler/server/np_ready/types.ts +++ /dev/null @@ -1,33 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ServerRoute } from 'hapi'; -import { ElasticsearchPlugin, Request } from 'src/legacy/core_plugins/elasticsearch'; -import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main'; - -export type RegisterRoute = (args: ServerRoute & { config: any }) => void; - -export interface LegacyPlugins { - __LEGACY: { - thisPlugin: any; - elasticsearch: ElasticsearchPlugin; - xpackMain: XPackMainPlugin; - commonRouteConfig: any; - }; -} - -export interface LegacySetup { - route: RegisterRoute; - plugins: LegacyPlugins; -} - -export interface ServerShim { - elasticsearch: ElasticsearchPlugin; -} - -export interface RequestShim extends Request { - payload: any; -} diff --git a/x-pack/legacy/plugins/security/common/model.ts b/x-pack/legacy/plugins/security/common/model.ts deleted file mode 100644 index 733e89f774db8c..00000000000000 --- a/x-pack/legacy/plugins/security/common/model.ts +++ /dev/null @@ -1,28 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { - ApiKey, - ApiKeyToInvalidate, - AuthenticatedUser, - BuiltinESPrivileges, - EditUser, - FeaturesPrivileges, - InlineRoleTemplate, - InvalidRoleTemplate, - KibanaPrivileges, - RawKibanaFeaturePrivileges, - RawKibanaPrivileges, - Role, - RoleIndexPrivilege, - RoleKibanaPrivilege, - RoleMapping, - RoleTemplate, - StoredRoleTemplate, - User, - canUserChangePassword, - getUserDisplayName, -} from '../../../../plugins/security/common/model'; diff --git a/x-pack/legacy/plugins/security/index.d.ts b/x-pack/legacy/plugins/security/index.d.ts index 18284c8be689a1..d453415f73376c 100644 --- a/x-pack/legacy/plugins/security/index.d.ts +++ b/x-pack/legacy/plugins/security/index.d.ts @@ -5,7 +5,7 @@ */ import { Legacy } from 'kibana'; -import { AuthenticatedUser } from './common/model'; +import { AuthenticatedUser } from '../../../plugins/security/public'; /** * Public interface of the security plugin. diff --git a/x-pack/legacy/plugins/security/index.js b/x-pack/legacy/plugins/security/index.js index bc403b803b8df0..4988c30a1398b0 100644 --- a/x-pack/legacy/plugins/security/index.js +++ b/x-pack/legacy/plugins/security/index.js @@ -40,8 +40,6 @@ export const security = kibana => }, uiExports: { - chromeNavControls: [], - managementSections: ['plugins/security/views/management'], styleSheetPaths: resolve(__dirname, 'public/index.scss'), apps: [ { @@ -76,7 +74,6 @@ export const security = kibana => 'plugins/security/hacks/on_unauthorized_response', 'plugins/security/hacks/register_account_management_app', ], - home: ['plugins/security/register_feature'], injectDefaultVars: server => { const securityPlugin = server.newPlatform.setup.plugins.security; if (!securityPlugin) { diff --git a/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.test.tsx b/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.test.tsx deleted file mode 100644 index 9f69fc7a7551f0..00000000000000 --- a/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.test.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ConfirmDeleteUsers } from './confirm_delete'; -import React from 'react'; -import { UserAPIClient } from '../../../lib/api'; - -jest.mock('ui/kfetch'); - -describe('ConfirmDeleteUsers', () => { - it('renders a warning for a single user', () => { - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find('EuiModalHeaderTitle').text()).toMatchInlineSnapshot(`"Delete user foo"`); - }); - - it('renders a warning for a multiple users', () => { - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find('EuiModalHeaderTitle').text()).toMatchInlineSnapshot(`"Delete 3 users"`); - }); - - it('fires onCancel when the operation is cancelled', () => { - const onCancel = jest.fn(); - const wrapper = mountWithIntl( - - ); - - expect(onCancel).toBeCalledTimes(0); - - wrapper.find('EuiButtonEmpty[data-test-subj="confirmModalCancelButton"]').simulate('click'); - - expect(onCancel).toBeCalledTimes(1); - }); - - it('deletes the requested users when confirmed', () => { - const onCancel = jest.fn(); - const deleteUser = jest.fn(); - - const apiClient = new UserAPIClient(); - apiClient.deleteUser = deleteUser; - - const wrapper = mountWithIntl( - - ); - - wrapper.find('EuiButton[data-test-subj="confirmModalConfirmButton"]').simulate('click'); - - expect(deleteUser).toBeCalledTimes(2); - expect(deleteUser).toBeCalledWith('foo'); - expect(deleteUser).toBeCalledWith('bar'); - }); - - it('attempts to delete all users even if some fail', () => { - const onCancel = jest.fn(); - const deleteUser = jest.fn().mockImplementation(user => { - if (user === 'foo') { - return Promise.reject('something terrible happened'); - } - return Promise.resolve(); - }); - - const apiClient = new UserAPIClient(); - apiClient.deleteUser = deleteUser; - - const wrapper = mountWithIntl( - - ); - - wrapper.find('EuiButton[data-test-subj="confirmModalConfirmButton"]').simulate('click'); - - expect(deleteUser).toBeCalledTimes(2); - expect(deleteUser).toBeCalledWith('foo'); - expect(deleteUser).toBeCalledWith('bar'); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.tsx b/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.tsx deleted file mode 100644 index 53bb022afb513f..00000000000000 --- a/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.tsx +++ /dev/null @@ -1,120 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component, Fragment } from 'react'; -import { EuiOverlayMask, EuiConfirmModal } from '@elastic/eui'; -import { toastNotifications } from 'ui/notify'; -import { FormattedMessage, injectI18n, InjectedIntl } from '@kbn/i18n/react'; -import { UserAPIClient } from '../../../lib/api'; - -interface Props { - intl: InjectedIntl; - usersToDelete: string[]; - apiClient: UserAPIClient; - onCancel: () => void; - callback?: (usersToDelete: string[], errors: string[]) => void; -} - -class ConfirmDeleteUI extends Component { - public render() { - const { usersToDelete, onCancel, intl } = this.props; - const moreThanOne = usersToDelete.length > 1; - const title = moreThanOne - ? intl.formatMessage( - { - id: 'xpack.security.management.users.confirmDelete.deleteMultipleUsersTitle', - defaultMessage: 'Delete {userLength} users', - }, - { userLength: usersToDelete.length } - ) - : intl.formatMessage( - { - id: 'xpack.security.management.users.confirmDelete.deleteOneUserTitle', - defaultMessage: 'Delete user {userLength}', - }, - { userLength: usersToDelete[0] } - ); - return ( - - -
    - {moreThanOne ? ( - -

    - -

    -
      - {usersToDelete.map(username => ( -
    • {username}
    • - ))} -
    -
    - ) : null} -

    - -

    -
    -
    -
    - ); - } - - private deleteUsers = () => { - const { usersToDelete, callback, apiClient } = this.props; - const errors: string[] = []; - usersToDelete.forEach(async username => { - try { - await apiClient.deleteUser(username); - toastNotifications.addSuccess( - this.props.intl.formatMessage( - { - id: - 'xpack.security.management.users.confirmDelete.userSuccessfullyDeletedNotificationMessage', - defaultMessage: 'Deleted user {username}', - }, - { username } - ) - ); - } catch (e) { - errors.push(username); - toastNotifications.addDanger( - this.props.intl.formatMessage( - { - id: - 'xpack.security.management.users.confirmDelete.userDeletingErrorNotificationMessage', - defaultMessage: 'Error deleting user {username}', - }, - { username } - ) - ); - } - if (callback) { - callback(usersToDelete, errors); - } - }); - }; -} - -export const ConfirmDeleteUsers = injectI18n(ConfirmDeleteUI); diff --git a/x-pack/legacy/plugins/security/public/components/management/users/index.ts b/x-pack/legacy/plugins/security/public/components/management/users/index.ts deleted file mode 100644 index 813e671c05ccf2..00000000000000 --- a/x-pack/legacy/plugins/security/public/components/management/users/index.ts +++ /dev/null @@ -1,7 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { ConfirmDeleteUsers } from './confirm_delete'; diff --git a/x-pack/legacy/plugins/security/public/documentation_links.js b/x-pack/legacy/plugins/security/public/documentation_links.js deleted file mode 100644 index 8050289b95e9df..00000000000000 --- a/x-pack/legacy/plugins/security/public/documentation_links.js +++ /dev/null @@ -1,16 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; - -const ES_REF_URL = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}`; - -export const documentationLinks = { - dashboardViewMode: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/xpack-view-modes.html`, - esClusterPrivileges: `${ES_REF_URL}/security-privileges.html#privileges-list-cluster`, - esIndicesPrivileges: `${ES_REF_URL}/security-privileges.html#privileges-list-indices`, - esRunAsPrivileges: `${ES_REF_URL}/security-privileges.html#_run_as_privilege`, -}; diff --git a/x-pack/legacy/plugins/security/public/images/logout.svg b/x-pack/legacy/plugins/security/public/images/logout.svg deleted file mode 100644 index d6533c07199040..00000000000000 --- a/x-pack/legacy/plugins/security/public/images/logout.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/x-pack/legacy/plugins/security/public/images/person.svg b/x-pack/legacy/plugins/security/public/images/person.svg deleted file mode 100644 index 988ddac8859d71..00000000000000 --- a/x-pack/legacy/plugins/security/public/images/person.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/x-pack/legacy/plugins/security/public/index.scss b/x-pack/legacy/plugins/security/public/index.scss index 2d7696bed39890..187ad5231534d2 100644 --- a/x-pack/legacy/plugins/security/public/index.scss +++ b/x-pack/legacy/plugins/security/public/index.scss @@ -15,3 +15,6 @@ $secFormWidth: 460px; // Public views @import './views/index'; +// Styles of Kibana Platform plugin +@import '../../../../plugins/security/public/index'; + diff --git a/x-pack/legacy/plugins/security/public/lib/__tests__/parse_next.js b/x-pack/legacy/plugins/security/public/lib/__tests__/parse_next.js deleted file mode 100644 index 7516433c77f83d..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/__tests__/parse_next.js +++ /dev/null @@ -1,172 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { parseNext } from '../parse_next'; - -describe('parseNext', () => { - it('should return a function', () => { - expect(parseNext).to.be.a('function'); - }); - - describe('with basePath defined', () => { - // trailing slash is important since it must match the cookie path exactly - it('should return basePath with a trailing slash when next is not specified', () => { - const basePath = '/iqf'; - const href = `${basePath}/login`; - expect(parseNext(href, basePath)).to.equal(`${basePath}/`); - }); - - it('should properly handle next without hash', () => { - const basePath = '/iqf'; - const next = `${basePath}/app/kibana`; - const href = `${basePath}/login?next=${next}`; - expect(parseNext(href, basePath)).to.equal(next); - }); - - it('should properly handle next with hash', () => { - const basePath = '/iqf'; - const next = `${basePath}/app/kibana`; - const hash = '/discover/New-Saved-Search'; - const href = `${basePath}/login?next=${next}#${hash}`; - expect(parseNext(href, basePath)).to.equal(`${next}#${hash}`); - }); - - it('should properly decode special characters', () => { - const basePath = '/iqf'; - const next = `${encodeURIComponent(basePath)}%2Fapp%2Fkibana`; - const hash = '/discover/New-Saved-Search'; - const href = `${basePath}/login?next=${next}#${hash}`; - expect(parseNext(href, basePath)).to.equal(decodeURIComponent(`${next}#${hash}`)); - }); - - // to help prevent open redirect to a different url - it('should return basePath if next includes a protocol/hostname', () => { - const basePath = '/iqf'; - const next = `https://example.com${basePath}/app/kibana`; - const href = `${basePath}/login?next=${next}`; - expect(parseNext(href, basePath)).to.equal(`${basePath}/`); - }); - - // to help prevent open redirect to a different url by abusing encodings - it('should return basePath if including a protocol/host even if it is encoded', () => { - const basePath = '/iqf'; - const baseUrl = `http://example.com${basePath}`; - const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`; - const hash = '/discover/New-Saved-Search'; - const href = `${basePath}/login?next=${next}#${hash}`; - expect(parseNext(href, basePath)).to.equal(`${basePath}/`); - }); - - // to help prevent open redirect to a different port - it('should return basePath if next includes a port', () => { - const basePath = '/iqf'; - const next = `http://localhost:5601${basePath}/app/kibana`; - const href = `${basePath}/login?next=${next}`; - expect(parseNext(href, basePath)).to.equal(`${basePath}/`); - }); - - // to help prevent open redirect to a different port by abusing encodings - it('should return basePath if including a port even if it is encoded', () => { - const basePath = '/iqf'; - const baseUrl = `http://example.com:5601${basePath}`; - const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`; - const hash = '/discover/New-Saved-Search'; - const href = `${basePath}/login?next=${next}#${hash}`; - expect(parseNext(href, basePath)).to.equal(`${basePath}/`); - }); - - // to help prevent open redirect to a different base path - it('should return basePath if next does not begin with basePath', () => { - const basePath = '/iqf'; - const next = '/notbasepath/app/kibana'; - const href = `${basePath}/login?next=${next}`; - expect(parseNext(href, basePath)).to.equal(`${basePath}/`); - }); - - // disallow network-path references - it('should return / if next is url without protocol', () => { - const nextWithTwoSlashes = '//example.com'; - const hrefWithTwoSlashes = `/login?next=${nextWithTwoSlashes}`; - expect(parseNext(hrefWithTwoSlashes)).to.equal('/'); - - const nextWithThreeSlashes = '///example.com'; - const hrefWithThreeSlashes = `/login?next=${nextWithThreeSlashes}`; - expect(parseNext(hrefWithThreeSlashes)).to.equal('/'); - }); - }); - - describe('without basePath defined', () => { - // trailing slash is important since it must match the cookie path exactly - it('should return / with a trailing slash when next is not specified', () => { - const href = '/login'; - expect(parseNext(href)).to.equal('/'); - }); - - it('should properly handle next without hash', () => { - const next = '/app/kibana'; - const href = `/login?next=${next}`; - expect(parseNext(href)).to.equal(next); - }); - - it('should properly handle next with hash', () => { - const next = '/app/kibana'; - const hash = '/discover/New-Saved-Search'; - const href = `/login?next=${next}#${hash}`; - expect(parseNext(href)).to.equal(`${next}#${hash}`); - }); - - it('should properly decode special characters', () => { - const next = '%2Fapp%2Fkibana'; - const hash = '/discover/New-Saved-Search'; - const href = `/login?next=${next}#${hash}`; - expect(parseNext(href)).to.equal(decodeURIComponent(`${next}#${hash}`)); - }); - - // to help prevent open redirect to a different url - it('should return / if next includes a protocol/hostname', () => { - const next = 'https://example.com/app/kibana'; - const href = `/login?next=${next}`; - expect(parseNext(href)).to.equal('/'); - }); - - // to help prevent open redirect to a different url by abusing encodings - it('should return / if including a protocol/host even if it is encoded', () => { - const baseUrl = 'http://example.com'; - const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`; - const hash = '/discover/New-Saved-Search'; - const href = `/login?next=${next}#${hash}`; - expect(parseNext(href)).to.equal('/'); - }); - - // to help prevent open redirect to a different port - it('should return / if next includes a port', () => { - const next = 'http://localhost:5601/app/kibana'; - const href = `/login?next=${next}`; - expect(parseNext(href)).to.equal('/'); - }); - - // to help prevent open redirect to a different port by abusing encodings - it('should return / if including a port even if it is encoded', () => { - const baseUrl = 'http://example.com:5601'; - const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`; - const hash = '/discover/New-Saved-Search'; - const href = `/login?next=${next}#${hash}`; - expect(parseNext(href)).to.equal('/'); - }); - - // disallow network-path references - it('should return / if next is url without protocol', () => { - const nextWithTwoSlashes = '//example.com'; - const hrefWithTwoSlashes = `/login?next=${nextWithTwoSlashes}`; - expect(parseNext(hrefWithTwoSlashes)).to.equal('/'); - - const nextWithThreeSlashes = '///example.com'; - const hrefWithThreeSlashes = `/login?next=${nextWithThreeSlashes}`; - expect(parseNext(hrefWithThreeSlashes)).to.equal('/'); - }); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/lib/__tests__/util.js b/x-pack/legacy/plugins/security/public/lib/__tests__/util.js deleted file mode 100644 index 3f7d8aea53a85f..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/__tests__/util.js +++ /dev/null @@ -1,49 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { toggle, toggleSort } from '../../../public/lib/util'; - -describe('util', () => { - describe('toggle', () => { - it('should add an item to a collection if not already included', () => { - const collection = [1, 2, 3, 4, 5]; - toggle(collection, 6); - expect(collection.indexOf(6)).to.be.above(0); - }); - - it('should remove an item from a collection if already included', () => { - const collection = [1, 2, 3, 4, 5]; - toggle(collection, 3); - expect(collection.indexOf(3)).to.be.below(0); - }); - }); - - describe('toggleSort', () => { - it('should toggle reverse if called with the same orderBy', () => { - const sort = { orderBy: 'foo', reverse: false }; - - toggleSort(sort, 'foo'); - expect(sort.reverse).to.be.true; - - toggleSort(sort, 'foo'); - expect(sort.reverse).to.be.false; - }); - - it('should change orderBy and set reverse to false when called with a different orderBy', () => { - const sort = { orderBy: 'foo', reverse: false }; - - toggleSort(sort, 'bar'); - expect(sort.orderBy).to.equal('bar'); - expect(sort.reverse).to.be.false; - - sort.reverse = true; - toggleSort(sort, 'foo'); - expect(sort.orderBy).to.equal('foo'); - expect(sort.reverse).to.be.false; - }); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/lib/api.ts b/x-pack/legacy/plugins/security/public/lib/api.ts deleted file mode 100644 index c5c6994bf4be36..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/api.ts +++ /dev/null @@ -1,56 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { kfetch } from 'ui/kfetch'; -import { Role, User, EditUser } from '../../common/model'; - -const usersUrl = '/internal/security/users'; -const rolesUrl = '/api/security/role'; - -export class UserAPIClient { - public async getUsers(): Promise { - return await kfetch({ pathname: usersUrl }); - } - - public async getUser(username: string): Promise { - const url = `${usersUrl}/${encodeURIComponent(username)}`; - return await kfetch({ pathname: url }); - } - - public async deleteUser(username: string) { - const url = `${usersUrl}/${encodeURIComponent(username)}`; - await kfetch({ pathname: url, method: 'DELETE' }, {}); - } - - public async saveUser(user: EditUser) { - const url = `${usersUrl}/${encodeURIComponent(user.username)}`; - - await kfetch({ pathname: url, body: JSON.stringify(user), method: 'POST' }); - } - - public async getRoles(): Promise { - return await kfetch({ pathname: rolesUrl }); - } - - public async getRole(name: string): Promise { - const url = `${rolesUrl}/${encodeURIComponent(name)}`; - return await kfetch({ pathname: url }); - } - - public async changePassword(username: string, password: string, currentPassword: string) { - const data: Record = { - newPassword: password, - }; - if (currentPassword) { - data.password = currentPassword; - } - await kfetch({ - pathname: `${usersUrl}/${encodeURIComponent(username)}/password`, - method: 'POST', - body: JSON.stringify(data), - }); - } -} diff --git a/x-pack/legacy/plugins/security/public/lib/api_keys_api.ts b/x-pack/legacy/plugins/security/public/lib/api_keys_api.ts deleted file mode 100644 index fbc0460c5908a7..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/api_keys_api.ts +++ /dev/null @@ -1,47 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { kfetch } from 'ui/kfetch'; -import { ApiKey, ApiKeyToInvalidate } from '../../common/model'; - -interface CheckPrivilegesResponse { - areApiKeysEnabled: boolean; - isAdmin: boolean; -} - -interface InvalidateApiKeysResponse { - itemsInvalidated: ApiKeyToInvalidate[]; - errors: any[]; -} - -interface GetApiKeysResponse { - apiKeys: ApiKey[]; -} - -const apiKeysUrl = `/internal/security/api_key`; - -export class ApiKeysApi { - public static async checkPrivileges(): Promise { - return kfetch({ pathname: `${apiKeysUrl}/privileges` }); - } - - public static async getApiKeys(isAdmin: boolean = false): Promise { - const query = { - isAdmin, - }; - - return kfetch({ pathname: apiKeysUrl, query }); - } - - public static async invalidateApiKeys( - apiKeys: ApiKeyToInvalidate[], - isAdmin: boolean = false - ): Promise { - const pathname = `${apiKeysUrl}/invalidate`; - const body = JSON.stringify({ apiKeys, isAdmin }); - return kfetch({ pathname, method: 'POST', body }); - } -} diff --git a/x-pack/legacy/plugins/security/public/lib/role_mappings_api.ts b/x-pack/legacy/plugins/security/public/lib/role_mappings_api.ts deleted file mode 100644 index b8bcba91388b53..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/role_mappings_api.ts +++ /dev/null @@ -1,58 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { CoreSetup } from 'src/core/public'; -import { RoleMapping } from '../../common/model'; - -interface CheckRoleMappingFeaturesResponse { - canManageRoleMappings: boolean; - canUseInlineScripts: boolean; - canUseStoredScripts: boolean; - hasCompatibleRealms: boolean; -} - -type DeleteRoleMappingsResponse = Array<{ - name: string; - success: boolean; - error?: Error; -}>; - -export class RoleMappingsAPI { - constructor(private readonly http: CoreSetup['http']) {} - - public async checkRoleMappingFeatures(): Promise { - return this.http.get(`/internal/security/_check_role_mapping_features`); - } - - public async getRoleMappings(): Promise { - return this.http.get(`/internal/security/role_mapping`); - } - - public async getRoleMapping(name: string): Promise { - return this.http.get(`/internal/security/role_mapping/${encodeURIComponent(name)}`); - } - - public async saveRoleMapping(roleMapping: RoleMapping) { - const payload = { ...roleMapping }; - delete payload.name; - - return this.http.post( - `/internal/security/role_mapping/${encodeURIComponent(roleMapping.name)}`, - { body: JSON.stringify(payload) } - ); - } - - public async deleteRoleMappings(names: string[]): Promise { - return Promise.all( - names.map(name => - this.http - .delete(`/internal/security/role_mapping/${encodeURIComponent(name)}`) - .then(() => ({ success: true, name })) - .catch(error => ({ success: false, name, error })) - ) - ); - } -} diff --git a/x-pack/legacy/plugins/security/public/lib/role_utils.test.ts b/x-pack/legacy/plugins/security/public/lib/role_utils.test.ts deleted file mode 100644 index 9d94017c3f0fe4..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/role_utils.test.ts +++ /dev/null @@ -1,181 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Role } from '../../common/model'; -import { - copyRole, - isReadOnlyRole, - isReservedRole, - isRoleEnabled, - prepareRoleClone, -} from './role_utils'; - -describe('role', () => { - describe('isRoleEnabled', () => { - test('should return false if role is explicitly not enabled', () => { - const testRole = { - transient_metadata: { - enabled: false, - }, - }; - expect(isRoleEnabled(testRole)).toBe(false); - }); - - test('should return true if role is explicitly enabled', () => { - const testRole = { - transient_metadata: { - enabled: true, - }, - }; - expect(isRoleEnabled(testRole)).toBe(true); - }); - - test('should return true if role is NOT explicitly enabled or disabled', () => { - const testRole = {}; - expect(isRoleEnabled(testRole)).toBe(true); - }); - }); - - describe('isReservedRole', () => { - test('should return false if role is explicitly not reserved', () => { - const testRole = { - metadata: { - _reserved: false, - }, - }; - expect(isReservedRole(testRole)).toBe(false); - }); - - test('should return true if role is explicitly reserved', () => { - const testRole = { - metadata: { - _reserved: true, - }, - }; - expect(isReservedRole(testRole)).toBe(true); - }); - - test('should return false if role is NOT explicitly reserved or not reserved', () => { - const testRole = {}; - expect(isReservedRole(testRole)).toBe(false); - }); - }); - - describe('isReadOnlyRole', () => { - test('returns true for reserved roles', () => { - const testRole = { - metadata: { - _reserved: true, - }, - }; - expect(isReadOnlyRole(testRole)).toBe(true); - }); - - test('returns true for roles with transform errors', () => { - const testRole = { - _transform_error: ['kibana'], - }; - expect(isReadOnlyRole(testRole)).toBe(true); - }); - - test('returns false for disabled roles', () => { - const testRole = { - transient_metadata: { - enabled: false, - }, - }; - expect(isReadOnlyRole(testRole)).toBe(false); - }); - - test('returns false for all other roles', () => { - const testRole = {}; - expect(isReadOnlyRole(testRole)).toBe(false); - }); - }); - - describe('copyRole', () => { - it('should perform a deep copy', () => { - const role: Role = { - name: '', - elasticsearch: { - cluster: ['all'], - indices: [{ names: ['index*'], privileges: ['all'] }], - run_as: ['user'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - { - spaces: ['default'], - base: ['foo'], - feature: {}, - }, - { - spaces: ['marketing'], - base: ['read'], - feature: {}, - }, - ], - }; - - const result = copyRole(role); - expect(result).toEqual(role); - - role.elasticsearch.indices[0].names = ['something else']; - - expect(result).not.toEqual(role); - }); - }); - - describe('prepareRoleClone', () => { - it('should return a copy of the role, with a blank role name', () => { - const role: Role = { - name: 'my_role', - elasticsearch: { - cluster: ['all'], - indices: [{ names: ['index*'], privileges: ['all'] }], - run_as: ['user'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - { - spaces: ['default'], - base: ['foo'], - feature: {}, - }, - { - spaces: ['marketing'], - base: ['read'], - feature: {}, - }, - ], - metadata: { - _reserved: true, - }, - transient_metadata: { - enabled: false, - }, - }; - - const { name: originalName, ...originalRest } = role; - - const result = prepareRoleClone(role); - const { name, ...rest } = result; - - expect(originalName).toEqual('my_role'); - expect(name).toEqual(''); - - expect(rest).toEqual(originalRest); - }); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/lib/role_utils.ts b/x-pack/legacy/plugins/security/public/lib/role_utils.ts deleted file mode 100644 index c33b7385306fb8..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/role_utils.ts +++ /dev/null @@ -1,58 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { cloneDeep, get } from 'lodash'; -import { Role } from '../../common/model'; - -/** - * Returns whether given role is enabled or not - * - * @param role Object Role JSON, as returned by roles API - * @return Boolean true if role is enabled; false otherwise - */ -export function isRoleEnabled(role: Partial) { - return get(role, 'transient_metadata.enabled', true); -} - -/** - * Returns whether given role is reserved or not. - * - * @param {role} the Role as returned by roles API - */ -export function isReservedRole(role: Partial) { - return get(role, 'metadata._reserved', false); -} - -/** - * Returns whether given role is editable through the UI or not. - * - * @param role the Role as returned by roles API - */ -export function isReadOnlyRole(role: Partial): boolean { - return isReservedRole(role) || !!(role._transform_error && role._transform_error.length > 0); -} - -/** - * Returns a deep copy of the role. - * - * @param role the Role to copy. - */ -export function copyRole(role: Role) { - return cloneDeep(role); -} - -/** - * Creates a deep copy of the role suitable for cloning. - * - * @param role the Role to clone. - */ -export function prepareRoleClone(role: Role): Role { - const clone = copyRole(role); - - clone.name = ''; - - return clone; -} diff --git a/x-pack/legacy/plugins/security/public/lib/roles_api.ts b/x-pack/legacy/plugins/security/public/lib/roles_api.ts deleted file mode 100644 index 20c1491ccaac69..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/roles_api.ts +++ /dev/null @@ -1,25 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { kfetch } from 'ui/kfetch'; -import { Role } from '../../common/model'; - -export class RolesApi { - public static async getRoles(): Promise { - return kfetch({ pathname: '/api/security/role' }); - } - - public static async getRole(roleName: string): Promise { - return kfetch({ pathname: `/api/security/role/${encodeURIComponent(roleName)}` }); - } - - public static async deleteRole(roleName: string) { - return kfetch({ - pathname: `/api/security/role/${encodeURIComponent(roleName)}`, - method: 'DELETE', - }); - } -} diff --git a/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.test.ts b/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.test.ts deleted file mode 100644 index 1ea19f2637305e..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.test.ts +++ /dev/null @@ -1,484 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Role } from '../../common/model'; -import { transformRoleForSave } from './transform_role_for_save'; - -describe('transformRoleForSave', () => { - describe('spaces disabled', () => { - it('removes placeholder index privileges', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [{ names: [], privileges: [] }], - run_as: [], - }, - kibana: [], - }; - - const result = transformRoleForSave(role, false); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }); - }); - - it('removes placeholder query entries', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [{ names: ['.kibana*'], privileges: ['all'], query: '' }], - run_as: [], - }, - kibana: [], - }; - - const result = transformRoleForSave(role, false); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [{ names: ['.kibana*'], privileges: ['all'] }], - run_as: [], - }, - kibana: [], - }); - }); - - it('removes transient fields not required for save', () => { - const role: Role = { - name: 'my role', - transient_metadata: { - foo: 'bar', - }, - _transform_error: ['kibana'], - metadata: { - someOtherMetadata: true, - }, - _unrecognized_applications: ['foo'], - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }; - - const result = transformRoleForSave(role, false); - - expect(result).toEqual({ - metadata: { - someOtherMetadata: true, - }, - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }); - }); - - it('does not remove actual query entries', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [{ names: ['.kibana*'], privileges: ['all'], query: 'something' }], - run_as: [], - }, - kibana: [], - }; - - const result = transformRoleForSave(role, false); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [{ names: ['.kibana*'], privileges: ['all'], query: 'something' }], - run_as: [], - }, - kibana: [], - }); - }); - - it('should remove feature privileges if a corresponding base privilege is defined', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }; - - const result = transformRoleForSave(role, false); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }); - }); - - it('should not remove feature privileges if a corresponding base privilege is not defined', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['*'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }; - - const result = transformRoleForSave(role, false); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['*'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }); - }); - - it('should remove space privileges', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['*'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - { - spaces: ['marketing'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }; - - const result = transformRoleForSave(role, false); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['*'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }); - }); - }); - - describe('spaces enabled', () => { - it('removes placeholder index privileges', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [{ names: [], privileges: [] }], - run_as: [], - }, - kibana: [], - }; - - const result = transformRoleForSave(role, true); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }); - }); - - it('removes placeholder query entries', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [{ names: ['.kibana*'], privileges: ['all'], query: '' }], - run_as: [], - }, - kibana: [], - }; - - const result = transformRoleForSave(role, true); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [{ names: ['.kibana*'], privileges: ['all'] }], - run_as: [], - }, - kibana: [], - }); - }); - - it('removes transient fields not required for save', () => { - const role: Role = { - name: 'my role', - transient_metadata: { - foo: 'bar', - }, - _transform_error: ['kibana'], - metadata: { - someOtherMetadata: true, - }, - _unrecognized_applications: ['foo'], - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }; - - const result = transformRoleForSave(role, true); - - expect(result).toEqual({ - metadata: { - someOtherMetadata: true, - }, - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }); - }); - - it('does not remove actual query entries', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [{ names: ['.kibana*'], privileges: ['all'], query: 'something' }], - run_as: [], - }, - kibana: [], - }; - - const result = transformRoleForSave(role, true); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [{ names: ['.kibana*'], privileges: ['all'], query: 'something' }], - run_as: [], - }, - kibana: [], - }); - }); - - it('should remove feature privileges if a corresponding base privilege is defined', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['foo'], - base: ['all'], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }; - - const result = transformRoleForSave(role, true); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['foo'], - base: ['all'], - feature: {}, - }, - ], - }); - }); - - it('should not remove feature privileges if a corresponding base privilege is not defined', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['foo'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }; - - const result = transformRoleForSave(role, true); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['foo'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }); - }); - - it('should not remove space privileges', () => { - const role: Role = { - name: 'my role', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['*'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - { - spaces: ['marketing'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }; - - const result = transformRoleForSave(role, true); - - expect(result).toEqual({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [ - { - spaces: ['*'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - { - spaces: ['marketing'], - base: [], - feature: { - feature1: ['read'], - feature2: ['write'], - }, - }, - ], - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.ts b/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.ts deleted file mode 100644 index 861ba530050a13..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Role, RoleIndexPrivilege } from '../../common/model'; -import { isGlobalPrivilegeDefinition } from './privilege_utils'; - -export function transformRoleForSave(role: Role, spacesEnabled: boolean) { - // Remove any placeholder index privileges - role.elasticsearch.indices = role.elasticsearch.indices.filter( - indexPrivilege => !isPlaceholderPrivilege(indexPrivilege) - ); - - // Remove any placeholder query entries - role.elasticsearch.indices.forEach(index => index.query || delete index.query); - - // If spaces are disabled, then do not persist any space privileges - if (!spacesEnabled) { - role.kibana = role.kibana.filter(isGlobalPrivilegeDefinition); - } - - role.kibana.forEach(kibanaPrivilege => { - // If a base privilege is defined, then do not persist feature privileges - if (kibanaPrivilege.base.length > 0) { - kibanaPrivilege.feature = {}; - } - }); - - delete role.name; - delete role.transient_metadata; - delete role._unrecognized_applications; - delete role._transform_error; - - return role; -} - -function isPlaceholderPrivilege(indexPrivilege: RoleIndexPrivilege) { - return indexPrivilege.names.length === 0; -} diff --git a/x-pack/legacy/plugins/security/public/lib/util.js b/x-pack/legacy/plugins/security/public/lib/util.js deleted file mode 100644 index bdf44aa3f10bb8..00000000000000 --- a/x-pack/legacy/plugins/security/public/lib/util.js +++ /dev/null @@ -1,19 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export function toggle(collection, item) { - const i = collection.indexOf(item); - if (i >= 0) collection.splice(i, 1); - else collection.push(item); -} - -export function toggleSort(sort, orderBy) { - if (sort.orderBy === orderBy) sort.reverse = !sort.reverse; - else { - sort.orderBy = orderBy; - sort.reverse = false; - } -} diff --git a/x-pack/legacy/plugins/security/public/objects/index.ts b/x-pack/legacy/plugins/security/public/objects/index.ts deleted file mode 100644 index a6238ca879901c..00000000000000 --- a/x-pack/legacy/plugins/security/public/objects/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { saveRole, deleteRole } from './lib/roles'; - -export { getFields } from './lib/get_fields'; diff --git a/x-pack/legacy/plugins/security/public/objects/lib/get_fields.ts b/x-pack/legacy/plugins/security/public/objects/lib/get_fields.ts deleted file mode 100644 index 91d98782dab423..00000000000000 --- a/x-pack/legacy/plugins/security/public/objects/lib/get_fields.ts +++ /dev/null @@ -1,15 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import { IHttpResponse } from 'angular'; -import chrome from 'ui/chrome'; - -const apiBase = chrome.addBasePath(`/internal/security/fields`); - -export async function getFields($http: any, query: string): Promise { - return await $http - .get(`${apiBase}/${query}`) - .then((response: IHttpResponse) => response.data || []); -} diff --git a/x-pack/legacy/plugins/security/public/objects/lib/roles.ts b/x-pack/legacy/plugins/security/public/objects/lib/roles.ts deleted file mode 100644 index e33cbe4c6c031c..00000000000000 --- a/x-pack/legacy/plugins/security/public/objects/lib/roles.ts +++ /dev/null @@ -1,21 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import chrome from 'ui/chrome'; -import { Role } from '../../../common/model'; -import { copyRole } from '../../lib/role_utils'; -import { transformRoleForSave } from '../../lib/transform_role_for_save'; - -const apiBase = chrome.addBasePath(`/api/security/role`); - -export async function saveRole($http: any, role: Role, spacesEnabled: boolean) { - const data = transformRoleForSave(copyRole(role), spacesEnabled); - - return await $http.put(`${apiBase}/${role.name}`, data); -} - -export async function deleteRole($http: any, name: string) { - return await $http.delete(`${apiBase}/${name}`); -} diff --git a/x-pack/legacy/plugins/security/public/register_feature.js b/x-pack/legacy/plugins/security/public/register_feature.js deleted file mode 100644 index c0bd42690b6fdb..00000000000000 --- a/x-pack/legacy/plugins/security/public/register_feature.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - FeatureCatalogueRegistryProvider, - FeatureCatalogueCategory, -} from 'ui/registry/feature_catalogue'; - -import { i18n } from '@kbn/i18n'; - -FeatureCatalogueRegistryProvider.register(() => { - return { - id: 'security', - title: i18n.translate('xpack.security.registerFeature.securitySettingsTitle', { - defaultMessage: 'Security Settings', - }), - description: i18n.translate('xpack.security.registerFeature.securitySettingsDescription', { - defaultMessage: - 'Protect your data and easily manage who has access to what with users and roles.', - }), - icon: 'securityApp', - path: '/app/kibana#/management/security', - showOnHomePage: true, - category: FeatureCatalogueCategory.ADMIN, - }; -}); diff --git a/x-pack/legacy/plugins/security/public/services/shield_indices.js b/x-pack/legacy/plugins/security/public/services/shield_indices.js deleted file mode 100644 index 791fa6cb596488..00000000000000 --- a/x-pack/legacy/plugins/security/public/services/shield_indices.js +++ /dev/null @@ -1,18 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { uiModules } from 'ui/modules'; - -const module = uiModules.get('security', []); -module.service('shieldIndices', ($http, chrome) => { - return { - getFields: query => { - return $http - .get(chrome.addBasePath(`/internal/security/fields/${query}`)) - .then(response => response.data); - }, - }; -}); diff --git a/x-pack/legacy/plugins/security/public/services/shield_role.js b/x-pack/legacy/plugins/security/public/services/shield_role.js deleted file mode 100644 index 261d3449a7a2d1..00000000000000 --- a/x-pack/legacy/plugins/security/public/services/shield_role.js +++ /dev/null @@ -1,30 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import 'angular-resource'; -import { omit } from 'lodash'; -import angular from 'angular'; -import { uiModules } from 'ui/modules'; - -const module = uiModules.get('security', ['ngResource']); -module.service('ShieldRole', ($resource, chrome) => { - return $resource( - chrome.addBasePath('/api/security/role/:name'), - { - name: '@name', - }, - { - save: { - method: 'PUT', - transformRequest(data) { - return angular.toJson( - omit(data, 'name', 'transient_metadata', '_unrecognized_applications') - ); - }, - }, - } - ); -}); diff --git a/x-pack/legacy/plugins/security/public/views/_index.scss b/x-pack/legacy/plugins/security/public/views/_index.scss index b85a7e19973906..6c2a091adf536e 100644 --- a/x-pack/legacy/plugins/security/public/views/_index.scss +++ b/x-pack/legacy/plugins/security/public/views/_index.scss @@ -1,5 +1,2 @@ // Login styles @import './login/index'; - -// Management styles -@import './management/index'; diff --git a/x-pack/legacy/plugins/security/public/views/account/account.html b/x-pack/legacy/plugins/security/public/views/account/account.html deleted file mode 100644 index 0935c415b18295..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/account/account.html +++ /dev/null @@ -1 +0,0 @@ -
    diff --git a/x-pack/legacy/plugins/security/public/views/account/account.js b/x-pack/legacy/plugins/security/public/views/account/account.js index 70a7b8dce727ec..13abc44e08f965 100644 --- a/x-pack/legacy/plugins/security/public/views/account/account.js +++ b/x-pack/legacy/plugins/security/public/views/account/account.js @@ -4,17 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import routes from 'ui/routes'; -import template from './account.html'; -import { i18n } from '@kbn/i18n'; -import { I18nContext } from 'ui/i18n'; -import { npSetup } from 'ui/new_platform'; -import { AccountManagementPage } from './components'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; +import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; +import routes from 'ui/routes'; routes.when('/account', { - template, + template: '
    ', k7Breadcrumbs: () => [ { text: i18n.translate('xpack.security.account.breadcrumb', { @@ -24,19 +21,15 @@ routes.when('/account', { ], controllerAs: 'accountController', controller($scope) { - $scope.$on('$destroy', () => { - const elem = document.getElementById('userProfileReactRoot'); - if (elem) { - unmountComponentAtNode(elem); - } - }); $scope.$$postDigest(() => { + const domNode = document.getElementById('userProfileReactRoot'); + render( - - - , - document.getElementById('userProfileReactRoot') + , + domNode ); + + $scope.$on('$destroy', () => unmountComponentAtNode(domNode)); }); }, }); diff --git a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.test.tsx b/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.test.tsx deleted file mode 100644 index 366842e58e9e4a..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.test.tsx +++ /dev/null @@ -1,120 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import { act } from '@testing-library/react'; -import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { securityMock } from '../../../../../../../plugins/security/public/mocks'; -import { AccountManagementPage } from './account_management_page'; -import { AuthenticatedUser } from '../../../../common/model'; - -jest.mock('ui/kfetch'); - -interface Options { - withFullName?: boolean; - withEmail?: boolean; - realm?: string; -} -const createUser = ({ withFullName = true, withEmail = true, realm = 'native' }: Options = {}) => { - return { - full_name: withFullName ? 'Casey Smith' : '', - username: 'csmith', - email: withEmail ? 'csmith@domain.com' : '', - enabled: true, - roles: [], - authentication_realm: { - type: realm, - name: realm, - }, - lookup_realm: { - type: realm, - name: realm, - }, - }; -}; - -function getSecuritySetupMock({ currentUser }: { currentUser: AuthenticatedUser }) { - const securitySetupMock = securityMock.createSetup(); - securitySetupMock.authc.getCurrentUser.mockResolvedValue(currentUser); - return securitySetupMock; -} - -describe('', () => { - it(`displays users full name, username, and email address`, async () => { - const user = createUser(); - const wrapper = mountWithIntl( - - ); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - - expect(wrapper.find('EuiText[data-test-subj="userDisplayName"]').text()).toEqual( - user.full_name - ); - expect(wrapper.find('[data-test-subj="username"]').text()).toEqual(user.username); - expect(wrapper.find('[data-test-subj="email"]').text()).toEqual(user.email); - }); - - it(`displays username when full_name is not provided`, async () => { - const user = createUser({ withFullName: false }); - const wrapper = mountWithIntl( - - ); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - - expect(wrapper.find('EuiText[data-test-subj="userDisplayName"]').text()).toEqual(user.username); - }); - - it(`displays a placeholder when no email address is provided`, async () => { - const user = createUser({ withEmail: false }); - const wrapper = mountWithIntl( - - ); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - - expect(wrapper.find('[data-test-subj="email"]').text()).toEqual('no email address'); - }); - - it(`displays change password form for users in the native realm`, async () => { - const user = createUser(); - const wrapper = mountWithIntl( - - ); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - - expect(wrapper.find('EuiFieldText[data-test-subj="currentPassword"]')).toHaveLength(1); - expect(wrapper.find('EuiFieldText[data-test-subj="newPassword"]')).toHaveLength(1); - }); - - it(`does not display change password form for users in the saml realm`, async () => { - const user = createUser({ realm: 'saml' }); - const wrapper = mountWithIntl( - - ); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - - expect(wrapper.find('EuiFieldText[data-test-subj="currentPassword"]')).toHaveLength(0); - expect(wrapper.find('EuiFieldText[data-test-subj="newPassword"]')).toHaveLength(0); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx b/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx deleted file mode 100644 index 6abee73e0b3535..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ -import { EuiPage, EuiPageBody, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; -import React, { useEffect, useState } from 'react'; -import { SecurityPluginSetup } from '../../../../../../../plugins/security/public'; -import { getUserDisplayName, AuthenticatedUser } from '../../../../common/model'; -import { ChangePassword } from './change_password'; -import { PersonalInfo } from './personal_info'; - -interface Props { - securitySetup: SecurityPluginSetup; -} - -export const AccountManagementPage = (props: Props) => { - const [currentUser, setCurrentUser] = useState(null); - useEffect(() => { - props.securitySetup.authc.getCurrentUser().then(setCurrentUser); - }, [props]); - - if (!currentUser) { - return null; - } - - return ( - - - - -

    {getUserDisplayName(currentUser)}

    -
    - - - - - - -
    -
    -
    - ); -}; diff --git a/x-pack/legacy/plugins/security/public/views/login/_index.scss b/x-pack/legacy/plugins/security/public/views/login/_index.scss index 9f133940f79777..9083c8dc3b7751 100644 --- a/x-pack/legacy/plugins/security/public/views/login/_index.scss +++ b/x-pack/legacy/plugins/security/public/views/login/_index.scss @@ -5,5 +5,4 @@ // loginChart__legend--small // loginChart__legend-isLoading -@import 'login'; - +@import './components/index'; diff --git a/x-pack/legacy/plugins/security/public/views/login/_login.scss b/x-pack/legacy/plugins/security/public/views/login/_login.scss deleted file mode 100644 index 607e9e6ec5e3f3..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/login/_login.scss +++ /dev/null @@ -1,34 +0,0 @@ - -.loginWelcome { - @include kibanaFullScreenGraphics; -} - -.loginWelcome__header { - position: relative; - padding: $euiSizeXL; - z-index: 10; -} - -.loginWelcome__logo { - @include kibanaCircleLogo; - @include euiBottomShadowMedium; - - margin-bottom: $euiSizeXL; -} - -.loginWelcome__footerAction { - margin-right: $euiSizeS; -} - -.loginWelcome__content { - position: relative; - margin: auto; - max-width: 460px; - padding-left: $euiSizeXL; - padding-right: $euiSizeXL; - z-index: 10; - - &.loginWelcome__contentDisabledForm { - max-width: 700px; - } -} diff --git a/x-pack/legacy/plugins/security/public/views/login/components/_index.scss b/x-pack/legacy/plugins/security/public/views/login/components/_index.scss new file mode 100644 index 00000000000000..a6f9598b9cc043 --- /dev/null +++ b/x-pack/legacy/plugins/security/public/views/login/components/_index.scss @@ -0,0 +1 @@ +@import './login_page/index'; diff --git a/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.test.tsx b/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.test.tsx index 93451453a523ab..3a970d582bdc8d 100644 --- a/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.test.tsx +++ b/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.test.tsx @@ -7,7 +7,7 @@ import { EuiButton, EuiCallOut } from '@elastic/eui'; import React from 'react'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { LoginState } from '../../../../../common/login_state'; +import { LoginState } from '../../login_state'; import { BasicLoginForm } from './basic_login_form'; const createMockHttp = ({ simulateError = false } = {}) => { diff --git a/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.tsx b/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.tsx index e6d3b5b7536b6a..c263381fbdb564 100644 --- a/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.tsx +++ b/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.tsx @@ -9,7 +9,7 @@ import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import React, { ChangeEvent, Component, FormEvent, Fragment, MouseEvent } from 'react'; import ReactMarkdown from 'react-markdown'; import { EuiText } from '@elastic/eui'; -import { LoginState } from '../../../../../common/login_state'; +import { LoginState } from '../../login_state'; interface Props { http: any; diff --git a/x-pack/legacy/plugins/security/public/views/login/components/login_page/_index.scss b/x-pack/legacy/plugins/security/public/views/login/components/login_page/_index.scss new file mode 100644 index 00000000000000..4dd2c0cabfb5e8 --- /dev/null +++ b/x-pack/legacy/plugins/security/public/views/login/components/login_page/_index.scss @@ -0,0 +1 @@ +@import './login_page'; diff --git a/x-pack/legacy/plugins/security/public/views/login/components/login_page/_login_page.scss b/x-pack/legacy/plugins/security/public/views/login/components/login_page/_login_page.scss new file mode 100644 index 00000000000000..cdfad55ee064af --- /dev/null +++ b/x-pack/legacy/plugins/security/public/views/login/components/login_page/_login_page.scss @@ -0,0 +1,29 @@ +.loginWelcome { + @include kibanaFullScreenGraphics; +} + +.loginWelcome__header { + position: relative; + padding: $euiSizeXL; + z-index: 10; +} + +.loginWelcome__logo { + @include kibanaCircleLogo; + @include euiBottomShadowMedium; + + margin-bottom: $euiSizeXL; +} + +.loginWelcome__content { + position: relative; + margin: auto; + max-width: 460px; + padding-left: $euiSizeXL; + padding-right: $euiSizeXL; + z-index: 10; + + &.loginWelcome__contentDisabledForm { + max-width: 700px; + } +} diff --git a/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.test.tsx b/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.test.tsx index c16db007bdbdcf..a0318d50a45e58 100644 --- a/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.test.tsx +++ b/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.test.tsx @@ -6,7 +6,7 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { LoginLayout, LoginState } from '../../../../../common/login_state'; +import { LoginLayout, LoginState } from '../../login_state'; import { LoginPage } from './login_page'; const createMockHttp = ({ simulateError = false } = {}) => { diff --git a/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.tsx b/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.tsx index e7e56947ca58f8..8035789a30e9df 100644 --- a/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.tsx +++ b/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.tsx @@ -19,7 +19,7 @@ import { EuiTitle, } from '@elastic/eui'; import classNames from 'classnames'; -import { LoginState } from '../../../../../common/login_state'; +import { LoginState } from '../../login_state'; import { BasicLoginForm } from '../basic_login_form'; import { DisabledLoginForm } from '../disabled_login_form'; diff --git a/x-pack/legacy/plugins/security/public/views/login/login.html b/x-pack/legacy/plugins/security/public/views/login/login.html deleted file mode 100644 index 2695fabdd63671..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/login/login.html +++ /dev/null @@ -1 +0,0 @@ -
    \ No newline at end of file diff --git a/x-pack/legacy/plugins/security/public/views/login/login.tsx b/x-pack/legacy/plugins/security/public/views/login/login.tsx index d9daf2d1f4d0de..0b89ac553c9a88 100644 --- a/x-pack/legacy/plugins/security/public/views/login/login.tsx +++ b/x-pack/legacy/plugins/security/public/views/login/login.tsx @@ -6,16 +6,14 @@ import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; -import { parseNext } from 'plugins/security/lib/parse_next'; import { LoginPage } from 'plugins/security/views/login/components'; -// @ts-ignore -import template from 'plugins/security/views/login/login.html'; import React from 'react'; import { render } from 'react-dom'; import chrome from 'ui/chrome'; import { I18nContext } from 'ui/i18n'; import { parse } from 'url'; -import { LoginState } from '../../../common/login_state'; +import { parseNext } from './parse_next'; +import { LoginState } from './login_state'; const messageMap = { SESSION_EXPIRED: i18n.translate('xpack.security.login.sessionExpiredDescription', { defaultMessage: 'Your session has timed out. Please log in again.', @@ -31,7 +29,7 @@ interface AnyObject { (chrome as AnyObject) .setVisible(false) - .setRootTemplate(template) + .setRootTemplate('
    ') .setRootController( 'login', ( diff --git a/x-pack/legacy/plugins/security/common/login_state.ts b/x-pack/legacy/plugins/security/public/views/login/login_state.ts similarity index 100% rename from x-pack/legacy/plugins/security/common/login_state.ts rename to x-pack/legacy/plugins/security/public/views/login/login_state.ts diff --git a/x-pack/legacy/plugins/security/public/views/login/parse_next.test.ts b/x-pack/legacy/plugins/security/public/views/login/parse_next.test.ts new file mode 100644 index 00000000000000..b5e6c7dca41d8f --- /dev/null +++ b/x-pack/legacy/plugins/security/public/views/login/parse_next.test.ts @@ -0,0 +1,171 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { parseNext } from './parse_next'; + +describe('parseNext', () => { + it('should return a function', () => { + expect(parseNext).toBeInstanceOf(Function); + }); + + describe('with basePath defined', () => { + // trailing slash is important since it must match the cookie path exactly + it('should return basePath with a trailing slash when next is not specified', () => { + const basePath = '/iqf'; + const href = `${basePath}/login`; + expect(parseNext(href, basePath)).toEqual(`${basePath}/`); + }); + + it('should properly handle next without hash', () => { + const basePath = '/iqf'; + const next = `${basePath}/app/kibana`; + const href = `${basePath}/login?next=${next}`; + expect(parseNext(href, basePath)).toEqual(next); + }); + + it('should properly handle next with hash', () => { + const basePath = '/iqf'; + const next = `${basePath}/app/kibana`; + const hash = '/discover/New-Saved-Search'; + const href = `${basePath}/login?next=${next}#${hash}`; + expect(parseNext(href, basePath)).toEqual(`${next}#${hash}`); + }); + + it('should properly decode special characters', () => { + const basePath = '/iqf'; + const next = `${encodeURIComponent(basePath)}%2Fapp%2Fkibana`; + const hash = '/discover/New-Saved-Search'; + const href = `${basePath}/login?next=${next}#${hash}`; + expect(parseNext(href, basePath)).toEqual(decodeURIComponent(`${next}#${hash}`)); + }); + + // to help prevent open redirect to a different url + it('should return basePath if next includes a protocol/hostname', () => { + const basePath = '/iqf'; + const next = `https://example.com${basePath}/app/kibana`; + const href = `${basePath}/login?next=${next}`; + expect(parseNext(href, basePath)).toEqual(`${basePath}/`); + }); + + // to help prevent open redirect to a different url by abusing encodings + it('should return basePath if including a protocol/host even if it is encoded', () => { + const basePath = '/iqf'; + const baseUrl = `http://example.com${basePath}`; + const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`; + const hash = '/discover/New-Saved-Search'; + const href = `${basePath}/login?next=${next}#${hash}`; + expect(parseNext(href, basePath)).toEqual(`${basePath}/`); + }); + + // to help prevent open redirect to a different port + it('should return basePath if next includes a port', () => { + const basePath = '/iqf'; + const next = `http://localhost:5601${basePath}/app/kibana`; + const href = `${basePath}/login?next=${next}`; + expect(parseNext(href, basePath)).toEqual(`${basePath}/`); + }); + + // to help prevent open redirect to a different port by abusing encodings + it('should return basePath if including a port even if it is encoded', () => { + const basePath = '/iqf'; + const baseUrl = `http://example.com:5601${basePath}`; + const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`; + const hash = '/discover/New-Saved-Search'; + const href = `${basePath}/login?next=${next}#${hash}`; + expect(parseNext(href, basePath)).toEqual(`${basePath}/`); + }); + + // to help prevent open redirect to a different base path + it('should return basePath if next does not begin with basePath', () => { + const basePath = '/iqf'; + const next = '/notbasepath/app/kibana'; + const href = `${basePath}/login?next=${next}`; + expect(parseNext(href, basePath)).toEqual(`${basePath}/`); + }); + + // disallow network-path references + it('should return / if next is url without protocol', () => { + const nextWithTwoSlashes = '//example.com'; + const hrefWithTwoSlashes = `/login?next=${nextWithTwoSlashes}`; + expect(parseNext(hrefWithTwoSlashes)).toEqual('/'); + + const nextWithThreeSlashes = '///example.com'; + const hrefWithThreeSlashes = `/login?next=${nextWithThreeSlashes}`; + expect(parseNext(hrefWithThreeSlashes)).toEqual('/'); + }); + }); + + describe('without basePath defined', () => { + // trailing slash is important since it must match the cookie path exactly + it('should return / with a trailing slash when next is not specified', () => { + const href = '/login'; + expect(parseNext(href)).toEqual('/'); + }); + + it('should properly handle next without hash', () => { + const next = '/app/kibana'; + const href = `/login?next=${next}`; + expect(parseNext(href)).toEqual(next); + }); + + it('should properly handle next with hash', () => { + const next = '/app/kibana'; + const hash = '/discover/New-Saved-Search'; + const href = `/login?next=${next}#${hash}`; + expect(parseNext(href)).toEqual(`${next}#${hash}`); + }); + + it('should properly decode special characters', () => { + const next = '%2Fapp%2Fkibana'; + const hash = '/discover/New-Saved-Search'; + const href = `/login?next=${next}#${hash}`; + expect(parseNext(href)).toEqual(decodeURIComponent(`${next}#${hash}`)); + }); + + // to help prevent open redirect to a different url + it('should return / if next includes a protocol/hostname', () => { + const next = 'https://example.com/app/kibana'; + const href = `/login?next=${next}`; + expect(parseNext(href)).toEqual('/'); + }); + + // to help prevent open redirect to a different url by abusing encodings + it('should return / if including a protocol/host even if it is encoded', () => { + const baseUrl = 'http://example.com'; + const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`; + const hash = '/discover/New-Saved-Search'; + const href = `/login?next=${next}#${hash}`; + expect(parseNext(href)).toEqual('/'); + }); + + // to help prevent open redirect to a different port + it('should return / if next includes a port', () => { + const next = 'http://localhost:5601/app/kibana'; + const href = `/login?next=${next}`; + expect(parseNext(href)).toEqual('/'); + }); + + // to help prevent open redirect to a different port by abusing encodings + it('should return / if including a port even if it is encoded', () => { + const baseUrl = 'http://example.com:5601'; + const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`; + const hash = '/discover/New-Saved-Search'; + const href = `/login?next=${next}#${hash}`; + expect(parseNext(href)).toEqual('/'); + }); + + // disallow network-path references + it('should return / if next is url without protocol', () => { + const nextWithTwoSlashes = '//example.com'; + const hrefWithTwoSlashes = `/login?next=${nextWithTwoSlashes}`; + expect(parseNext(hrefWithTwoSlashes)).toEqual('/'); + + const nextWithThreeSlashes = '///example.com'; + const hrefWithThreeSlashes = `/login?next=${nextWithThreeSlashes}`; + expect(parseNext(hrefWithThreeSlashes)).toEqual('/'); + }); + }); +}); diff --git a/x-pack/legacy/plugins/security/public/lib/parse_next.ts b/x-pack/legacy/plugins/security/public/views/login/parse_next.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/lib/parse_next.ts rename to x-pack/legacy/plugins/security/public/views/login/parse_next.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/_index.scss b/x-pack/legacy/plugins/security/public/views/management/_index.scss deleted file mode 100644 index 78b53845071e4a..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/_index.scss +++ /dev/null @@ -1,4 +0,0 @@ -@import './change_password_form/index'; -@import './edit_role/index'; -@import './edit_user/index'; -@import './role_mappings/edit_role_mapping/index'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.html b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.html deleted file mode 100644 index e46c6f72b5d20e..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    - diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.js b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.js deleted file mode 100644 index e7143b10208148..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import routes from 'ui/routes'; -import template from './api_keys.html'; -import { API_KEYS_PATH } from '../management_urls'; -import { getApiKeysBreadcrumbs } from '../breadcrumbs'; -import { I18nContext } from 'ui/i18n'; -import { ApiKeysGridPage } from './components'; - -routes.when(API_KEYS_PATH, { - template, - k7Breadcrumbs: getApiKeysBreadcrumbs, - controller($scope) { - $scope.$$postDigest(() => { - const domNode = document.getElementById('apiKeysGridReactRoot'); - - render( - - - , - domNode - ); - - // unmount react on controller destroy - $scope.$on('$destroy', () => { - unmountComponentAtNode(domNode); - }); - }); - }, -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx deleted file mode 100644 index 19ac3881f78d93..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx +++ /dev/null @@ -1,180 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -let mockSimulate403 = false; -let mockSimulate500 = false; -let mockAreApiKeysEnabled = true; -let mockIsAdmin = true; - -const mock403 = () => ({ body: { statusCode: 403 } }); -const mock500 = () => ({ body: { error: 'Internal Server Error', message: '', statusCode: 500 } }); - -jest.mock('../../../../lib/api_keys_api', () => { - return { - ApiKeysApi: { - async checkPrivileges() { - if (mockSimulate403) { - throw mock403(); - } - - return { - isAdmin: mockIsAdmin, - areApiKeysEnabled: mockAreApiKeysEnabled, - }; - }, - async getApiKeys() { - if (mockSimulate500) { - throw mock500(); - } - - return { - apiKeys: [ - { - creation: 1571322182082, - expiration: 1571408582082, - id: '0QQZ2m0BO2XZwgJFuWTT', - invalidated: false, - name: 'my-api-key', - realm: 'reserved', - username: 'elastic', - }, - ], - }; - }, - }, - }; -}); - -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ApiKeysGridPage } from './api_keys_grid_page'; -import React from 'react'; -import { ReactWrapper } from 'enzyme'; -import { EuiCallOut } from '@elastic/eui'; - -import { NotEnabled } from './not_enabled'; -import { PermissionDenied } from './permission_denied'; - -const waitForRender = async ( - wrapper: ReactWrapper, - condition: (wrapper: ReactWrapper) => boolean -) => { - return new Promise((resolve, reject) => { - const interval = setInterval(async () => { - await Promise.resolve(); - wrapper.update(); - if (condition(wrapper)) { - resolve(); - } - }, 10); - - setTimeout(() => { - clearInterval(interval); - reject(new Error('waitForRender timeout after 2000ms')); - }, 2000); - }); -}; - -describe('ApiKeysGridPage', () => { - beforeEach(() => { - mockSimulate403 = false; - mockSimulate500 = false; - mockAreApiKeysEnabled = true; - mockIsAdmin = true; - }); - - it('renders a loading state when fetching API keys', async () => { - const wrapper = mountWithIntl(); - - expect(wrapper.find('[data-test-subj="apiKeysSectionLoading"]')).toHaveLength(1); - }); - - it('renders a callout when API keys are not enabled', async () => { - mockAreApiKeysEnabled = false; - const wrapper = mountWithIntl(); - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(NotEnabled).length > 0; - }); - - expect(wrapper.find(NotEnabled)).toMatchSnapshot(); - }); - - it('renders permission denied if user does not have required permissions', async () => { - mockSimulate403 = true; - const wrapper = mountWithIntl(); - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(PermissionDenied).length > 0; - }); - - expect(wrapper.find(PermissionDenied)).toMatchSnapshot(); - }); - - it('renders error callout if error fetching API keys', async () => { - mockSimulate500 = true; - const wrapper = mountWithIntl(); - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(EuiCallOut).length > 0; - }); - - expect(wrapper.find('EuiCallOut[data-test-subj="apiKeysError"]')).toHaveLength(1); - }); - - describe('Admin view', () => { - const wrapper = mountWithIntl(); - - it('renders a callout indicating the user is an administrator', async () => { - const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]'; - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(calloutEl).length > 0; - }); - - expect(wrapper.find(calloutEl).text()).toEqual('You are an API Key administrator.'); - }); - - it('renders the correct description text', async () => { - const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(descriptionEl).length > 0; - }); - - expect(wrapper.find(descriptionEl).text()).toEqual( - 'View and invalidate API keys. An API key sends requests on behalf of a user.' - ); - }); - }); - - describe('Non-admin view', () => { - mockIsAdmin = false; - const wrapper = mountWithIntl(); - - it('does NOT render a callout indicating the user is an administrator', async () => { - const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; - const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]'; - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(descriptionEl).length > 0; - }); - - expect(wrapper.find(calloutEl).length).toEqual(0); - }); - - it('renders the correct description text', async () => { - const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(descriptionEl).length > 0; - }); - - expect(wrapper.find(descriptionEl).text()).toEqual( - 'View and invalidate your API keys. An API key sends requests on your behalf.' - ); - }); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/index.ts b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/index.ts deleted file mode 100644 index 9f4d4239d6b4cc..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/index.ts +++ /dev/null @@ -1,7 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { ApiKeysGridPage } from './api_keys_grid_page'; diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/services/documentation_links.ts b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/services/documentation_links.ts deleted file mode 100644 index 1f03763eb542a3..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/services/documentation_links.ts +++ /dev/null @@ -1,21 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; - -class DocumentationLinksService { - private esDocBasePath = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`; - - public getApiKeyServiceSettingsDocUrl(): string { - return `${this.esDocBasePath}security-settings.html#api-key-service-settings`; - } - - public getCreateApiKeyDocUrl(): string { - return `${this.esDocBasePath}security-api-create-api-key.html`; - } -} - -export const documentationLinks = new DocumentationLinksService(); diff --git a/x-pack/legacy/plugins/security/public/views/management/breadcrumbs.ts b/x-pack/legacy/plugins/security/public/views/management/breadcrumbs.ts deleted file mode 100644 index 4ab7e45e848498..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/breadcrumbs.ts +++ /dev/null @@ -1,115 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { MANAGEMENT_BREADCRUMB } from 'ui/management/breadcrumbs'; - -export function getUsersBreadcrumbs() { - return [ - MANAGEMENT_BREADCRUMB, - { - text: i18n.translate('xpack.security.users.breadcrumb', { - defaultMessage: 'Users', - }), - href: '#/management/security/users', - }, - ]; -} - -export function getEditUserBreadcrumbs($route: Record) { - const { username } = $route.current.params; - return [ - ...getUsersBreadcrumbs(), - { - text: username, - href: `#/management/security/users/edit/${username}`, - }, - ]; -} - -export function getCreateUserBreadcrumbs() { - return [ - ...getUsersBreadcrumbs(), - { - text: i18n.translate('xpack.security.users.createBreadcrumb', { - defaultMessage: 'Create', - }), - }, - ]; -} - -export function getRolesBreadcrumbs() { - return [ - MANAGEMENT_BREADCRUMB, - { - text: i18n.translate('xpack.security.roles.breadcrumb', { - defaultMessage: 'Roles', - }), - href: '#/management/security/roles', - }, - ]; -} - -export function getEditRoleBreadcrumbs($route: Record) { - const { name } = $route.current.params; - return [ - ...getRolesBreadcrumbs(), - { - text: name, - href: `#/management/security/roles/edit/${name}`, - }, - ]; -} - -export function getCreateRoleBreadcrumbs() { - return [ - ...getUsersBreadcrumbs(), - { - text: i18n.translate('xpack.security.roles.createBreadcrumb', { - defaultMessage: 'Create', - }), - }, - ]; -} - -export function getApiKeysBreadcrumbs() { - return [ - MANAGEMENT_BREADCRUMB, - { - text: i18n.translate('xpack.security.apiKeys.breadcrumb', { - defaultMessage: 'API Keys', - }), - href: '#/management/security/api_keys', - }, - ]; -} - -export function getRoleMappingBreadcrumbs() { - return [ - MANAGEMENT_BREADCRUMB, - { - text: i18n.translate('xpack.security.roleMapping.breadcrumb', { - defaultMessage: 'Role Mappings', - }), - href: '#/management/security/role_mappings', - }, - ]; -} - -export function getEditRoleMappingBreadcrumbs($route: Record) { - const { name } = $route.current.params; - return [ - ...getRoleMappingBreadcrumbs(), - { - text: - name || - i18n.translate('xpack.security.roleMappings.createBreadcrumb', { - defaultMessage: 'Create', - }), - href: `#/management/security/role_mappings/edit/${name}`, - }, - ]; -} diff --git a/x-pack/legacy/plugins/security/public/views/management/change_password_form/_change_password_form.scss b/x-pack/legacy/plugins/security/public/views/management/change_password_form/_change_password_form.scss deleted file mode 100644 index 98331c2070a31e..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/change_password_form/_change_password_form.scss +++ /dev/null @@ -1,17 +0,0 @@ -.secChangePasswordForm__panel { - max-width: $secFormWidth; -} - -.secChangePasswordForm__subLabel { - margin-bottom: $euiSizeS; -} - -.secChangePasswordForm__footer { - display: flex; - justify-content: flex-start; - align-items: center; - - .kuiButton + .kuiButton { - margin-left: $euiSizeS; - } -} diff --git a/x-pack/legacy/plugins/security/public/views/management/change_password_form/_index.scss b/x-pack/legacy/plugins/security/public/views/management/change_password_form/_index.scss deleted file mode 100644 index a6058b5ddebbf0..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/change_password_form/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './change_password_form'; diff --git a/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.html b/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.html deleted file mode 100644 index 92fb95861a6f8e..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.html +++ /dev/null @@ -1,141 +0,0 @@ - - -
    - - - - - - -
    - -
    - - - - -
    -
    - - -
    - - - - -
    -
    - - -
    - - - - -
    - - -
    - - -
    -
    - - - -
    -
    -
    diff --git a/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.js b/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.js deleted file mode 100644 index d9aa59f6df1427..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.js +++ /dev/null @@ -1,48 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { uiModules } from 'ui/modules'; -import template from './change_password_form.html'; - -const module = uiModules.get('security', ['kibana']); -module.directive('kbnChangePasswordForm', function() { - return { - template, - scope: { - requireCurrentPassword: '=', - showKibanaWarning: '=', - onChangePassword: '&', - }, - restrict: 'E', - replace: true, - controllerAs: 'changePasswordController', - controller: function($scope) { - this.currentPassword = null; - this.newPassword = null; - this.newPasswordConfirmation = null; - this.isFormVisible = false; - this.isIncorrectPassword = false; - - this.showForm = () => { - this.isFormVisible = true; - }; - - this.hideForm = () => { - $scope.changePasswordForm.$setPristine(); - $scope.changePasswordForm.$setUntouched(); - this.currentPassword = null; - this.newPassword = null; - this.newPasswordConfirmation = null; - this.isFormVisible = false; - this.isIncorrectPassword = false; - }; - - this.onIncorrectPassword = () => { - this.isIncorrectPassword = true; - }; - }, - }; -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/_index.scss b/x-pack/legacy/plugins/security/public/views/management/edit_role/_index.scss deleted file mode 100644 index 192091fb04e3c9..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './components/index'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/_index.scss b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/_index.scss deleted file mode 100644 index 32b3832e7a9fa9..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/_index.scss +++ /dev/null @@ -1,9 +0,0 @@ -@import './collapsible_panel/collapsible_panel'; -@import './privileges/kibana/space_aware_privilege_section/index'; -@import './privileges/kibana/feature_table/index'; -@import './spaces_popover_list/spaces_popover_list'; - -.secPrivilegeFeatureIcon { - flex-shrink: 0; - margin-right: $euiSizeS; -} diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.test.tsx deleted file mode 100644 index 67c32c8393171f..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.test.tsx +++ /dev/null @@ -1,716 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ReactWrapper } from 'enzyme'; -import React from 'react'; -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { UICapabilities } from 'ui/capabilities'; -import { Space } from '../../../../../../spaces/common/model/space'; -import { Feature } from '../../../../../../../../plugins/features/public'; -// These modules should be moved into a common directory -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { Actions } from '../../../../../../../../plugins/security/server/authorization/actions'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { privilegesFactory } from '../../../../../../../../plugins/security/server/authorization/privileges'; -import { RawKibanaPrivileges, Role } from '../../../../../common/model'; -import { EditRolePage } from './edit_role_page'; -import { SimplePrivilegeSection } from './privileges/kibana/simple_privilege_section'; -import { SpaceAwarePrivilegeSection } from './privileges/kibana/space_aware_privilege_section'; -import { TransformErrorSection } from './privileges/kibana/transform_error_section'; - -const buildFeatures = () => { - return [ - { - id: 'feature1', - name: 'Feature 1', - icon: 'addDataApp', - app: ['feature1App'], - privileges: { - all: { - app: ['feature1App'], - ui: ['feature1-ui'], - savedObject: { - all: [], - read: [], - }, - }, - }, - }, - { - id: 'feature2', - name: 'Feature 2', - icon: 'addDataApp', - app: ['feature2App'], - privileges: { - all: { - app: ['feature2App'], - ui: ['feature2-ui'], - savedObject: { - all: ['feature2'], - read: ['config'], - }, - }, - }, - }, - ] as Feature[]; -}; - -const buildRawKibanaPrivileges = () => { - return privilegesFactory(new Actions('unit_test_version'), { - getFeatures: () => buildFeatures(), - }).get(); -}; - -const buildBuiltinESPrivileges = () => { - return { - cluster: ['all', 'manage', 'monitor'], - index: ['all', 'read', 'write', 'index'], - }; -}; - -const buildUICapabilities = (canManageSpaces = true) => { - return { - catalogue: {}, - management: {}, - navLinks: {}, - spaces: { - manage: canManageSpaces, - }, - } as UICapabilities; -}; - -const buildSpaces = () => { - return [ - { - id: 'default', - name: 'Default', - disabledFeatures: [], - _reserved: true, - }, - { - id: 'space_1', - name: 'Space 1', - disabledFeatures: [], - }, - { - id: 'space_2', - name: 'Space 2', - disabledFeatures: ['feature2'], - }, - ] as Space[]; -}; - -const expectReadOnlyFormButtons = (wrapper: ReactWrapper) => { - expect(wrapper.find('button[data-test-subj="roleFormReturnButton"]')).toHaveLength(1); - expect(wrapper.find('button[data-test-subj="roleFormSaveButton"]')).toHaveLength(0); -}; - -const expectSaveFormButtons = (wrapper: ReactWrapper) => { - expect(wrapper.find('button[data-test-subj="roleFormReturnButton"]')).toHaveLength(0); - expect(wrapper.find('button[data-test-subj="roleFormSaveButton"]')).toHaveLength(1); -}; - -describe('', () => { - describe('with spaces enabled', () => { - it('can render a reserved role', () => { - const role: Role = { - name: 'superuser', - metadata: { - _reserved: true, - }, - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: ['*'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const spaces: Space[] = buildSpaces(); - const uiCapabilities: UICapabilities = buildUICapabilities(); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(1); - expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); - expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); - expectReadOnlyFormButtons(wrapper); - }); - - it('can render a user defined role', () => { - const role: Role = { - name: 'my custom role', - metadata: {}, - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: ['*'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const spaces: Space[] = buildSpaces(); - const uiCapabilities: UICapabilities = buildUICapabilities(); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0); - expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); - expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); - expectSaveFormButtons(wrapper); - }); - - it('can render when creating a new role', () => { - // @ts-ignore - const role: Role = { - metadata: {}, - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const spaces: Space[] = buildSpaces(); - const uiCapabilities: UICapabilities = buildUICapabilities(); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); - expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); - expectSaveFormButtons(wrapper); - }); - - it('can render when cloning an existing role', () => { - const role: Role = { - metadata: { - _reserved: false, - }, - name: '', - elasticsearch: { - cluster: ['all', 'manage'], - indices: [ - { - names: ['foo*'], - privileges: ['all'], - field_security: { - except: ['f'], - grant: ['b*'], - }, - }, - ], - run_as: ['elastic'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const spaces: Space[] = buildSpaces(); - const uiCapabilities: UICapabilities = buildUICapabilities(); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); - expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); - expectSaveFormButtons(wrapper); - }); - - it('renders an auth error when not authorized to manage spaces', () => { - const role: Role = { - name: 'my custom role', - metadata: {}, - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: ['*'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const spaces: Space[] = buildSpaces(); - const uiCapabilities: UICapabilities = buildUICapabilities(false); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0); - - expect( - wrapper.find('EuiCallOut[data-test-subj="userCannotManageSpacesCallout"]') - ).toHaveLength(1); - - expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); - expectSaveFormButtons(wrapper); - }); - - it('renders a partial read-only view when there is a transform error', () => { - const role: Role = { - name: 'my custom role', - metadata: {}, - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: ['*'], - }, - kibana: [], - _transform_error: ['kibana'], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const spaces: Space[] = buildSpaces(); - const uiCapabilities: UICapabilities = buildUICapabilities(false); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find(TransformErrorSection)).toHaveLength(1); - expectReadOnlyFormButtons(wrapper); - }); - }); - - describe('with spaces disabled', () => { - it('can render a reserved role', () => { - const role: Role = { - name: 'superuser', - metadata: { - _reserved: true, - }, - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: ['*'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const uiCapabilities: UICapabilities = buildUICapabilities(); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(1); - expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); - expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); - expectReadOnlyFormButtons(wrapper); - }); - - it('can render a user defined role', () => { - const role: Role = { - name: 'my custom role', - metadata: {}, - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: ['*'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const uiCapabilities: UICapabilities = buildUICapabilities(); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0); - expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); - expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); - expectSaveFormButtons(wrapper); - }); - - it('can render when creating a new role', () => { - // @ts-ignore - const role: Role = { - metadata: {}, - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const uiCapabilities: UICapabilities = buildUICapabilities(); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); - expectSaveFormButtons(wrapper); - }); - - it('can render when cloning an existing role', () => { - const role: Role = { - metadata: { - _reserved: false, - }, - name: '', - elasticsearch: { - cluster: ['all', 'manage'], - indices: [ - { - names: ['foo*'], - privileges: ['all'], - field_security: { - except: ['f'], - grant: ['b*'], - }, - }, - ], - run_as: ['elastic'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const uiCapabilities: UICapabilities = buildUICapabilities(); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); - expectSaveFormButtons(wrapper); - }); - - it('does not care if user cannot manage spaces', () => { - const role: Role = { - name: 'my custom role', - metadata: {}, - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: ['*'], - }, - kibana: [ - { - spaces: ['*'], - base: ['all'], - feature: {}, - }, - ], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const uiCapabilities: UICapabilities = buildUICapabilities(false); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0); - - expect( - wrapper.find('EuiCallOut[data-test-subj="userCannotManageSpacesCallout"]') - ).toHaveLength(0); - - expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); - expectSaveFormButtons(wrapper); - }); - - it('renders a partial read-only view when there is a transform error', () => { - const role: Role = { - name: 'my custom role', - metadata: {}, - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: ['*'], - }, - kibana: [], - _transform_error: ['kibana'], - }; - - const features: Feature[] = buildFeatures(); - const mockHttpClient = jest.fn(); - const indexPatterns: string[] = ['foo*', 'bar*']; - const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges(); - const builtinESPrivileges = buildBuiltinESPrivileges(); - const uiCapabilities: UICapabilities = buildUICapabilities(false); - - const wrapper = mountWithIntl( - - ); - - expect(wrapper.find(TransformErrorSection)).toHaveLength(1); - expectReadOnlyFormButtons(wrapper); - }); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.tsx b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.tsx deleted file mode 100644 index 2ba012afa689dc..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.tsx +++ /dev/null @@ -1,409 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - EuiButton, - EuiButtonEmpty, - EuiFieldText, - EuiFlexGroup, - EuiFlexItem, - EuiForm, - EuiFormRow, - EuiPanel, - EuiSpacer, - EuiText, - EuiTitle, -} from '@elastic/eui'; -import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; -import { get } from 'lodash'; -import React, { ChangeEvent, Component, Fragment, HTMLProps } from 'react'; -import { UICapabilities } from 'ui/capabilities'; -import { toastNotifications } from 'ui/notify'; -import { Space } from '../../../../../../spaces/common/model/space'; -import { Feature } from '../../../../../../../../plugins/features/public'; -import { - KibanaPrivileges, - RawKibanaPrivileges, - Role, - BuiltinESPrivileges, -} from '../../../../../common/model'; -import { - isReadOnlyRole, - isReservedRole, - copyRole, - prepareRoleClone, -} from '../../../../lib/role_utils'; -import { deleteRole, saveRole } from '../../../../objects'; -import { ROLES_PATH } from '../../management_urls'; -import { RoleValidationResult, RoleValidator } from '../lib/validate_role'; -import { DeleteRoleButton } from './delete_role_button'; -import { ElasticsearchPrivileges, KibanaPrivilegesRegion } from './privileges'; -import { ReservedRoleBadge } from './reserved_role_badge'; - -interface Props { - action: 'edit' | 'clone'; - role: Role; - runAsUsers: string[]; - indexPatterns: string[]; - httpClient: any; - allowDocumentLevelSecurity: boolean; - allowFieldLevelSecurity: boolean; - kibanaPrivileges: RawKibanaPrivileges; - builtinESPrivileges: BuiltinESPrivileges; - spaces?: Space[]; - spacesEnabled: boolean; - intl: InjectedIntl; - uiCapabilities: UICapabilities; - features: Feature[]; -} - -interface State { - role: Role; - formError: RoleValidationResult | null; -} - -class EditRolePageUI extends Component { - private validator: RoleValidator; - - constructor(props: Props) { - super(props); - - this.validator = new RoleValidator({ shouldValidate: false }); - - let role: Role; - if (props.action === 'clone') { - role = prepareRoleClone(props.role); - } else { - role = copyRole(props.role); - } - - this.state = { - role, - formError: null, - }; - } - - public componentDidMount() { - if (this.props.action === 'clone' && isReservedRole(this.props.role)) { - this.backToRoleList(); - } - } - - public render() { - const description = this.props.spacesEnabled ? ( - - ) : ( - - ); - - return ( -
    - - {this.getFormTitle()} - - - - {description} - - {isReservedRole(this.state.role) && ( - - - -

    - -

    -
    -
    - )} - - - - {this.getRoleName()} - - {this.getElasticsearchPrivileges()} - - {this.getKibanaPrivileges()} - - - - {this.getFormButtons()} -
    -
    - ); - } - - private getFormTitle = () => { - let titleText; - const props: HTMLProps = { - tabIndex: 0, - }; - if (isReservedRole(this.state.role)) { - titleText = ( - - ); - props['aria-describedby'] = 'reservedRoleDescription'; - } else if (this.editingExistingRole()) { - titleText = ( - - ); - } else { - titleText = ( - - ); - } - - return ( - -

    - {titleText} -

    -
    - ); - }; - - private getActionButton = () => { - if (this.editingExistingRole() && !isReadOnlyRole(this.state.role)) { - return ( - - - - ); - } - - return null; - }; - - private getRoleName = () => { - return ( - - - } - helpText={ - !isReservedRole(this.state.role) && this.editingExistingRole() ? ( - - ) : ( - undefined - ) - } - {...this.validator.validateRoleName(this.state.role)} - > - - - - ); - }; - - private onNameChange = (e: ChangeEvent) => { - const rawValue = e.target.value; - const name = rawValue.replace(/\s/g, '_'); - - this.setState({ - role: { - ...this.state.role, - name, - }, - }); - }; - - private getElasticsearchPrivileges() { - return ( -
    - - -
    - ); - } - - private onRoleChange = (role: Role) => { - this.setState({ - role, - }); - }; - - private getKibanaPrivileges = () => { - return ( -
    - - -
    - ); - }; - - private getFormButtons = () => { - if (isReadOnlyRole(this.state.role)) { - return this.getReturnToRoleListButton(); - } - - return ( - - {this.getSaveButton()} - {this.getCancelButton()} - - {this.getActionButton()} - - ); - }; - - private getReturnToRoleListButton = () => { - return ( - - - - ); - }; - - private getSaveButton = () => { - const saveText = this.editingExistingRole() ? ( - - ) : ( - - ); - - return ( - - {saveText} - - ); - }; - - private getCancelButton = () => { - return ( - - - - ); - }; - - private editingExistingRole = () => { - return !!this.props.role.name && this.props.action === 'edit'; - }; - - private saveRole = () => { - this.validator.enableValidation(); - - const result = this.validator.validateForSave(this.state.role); - if (result.isInvalid) { - this.setState({ - formError: result, - }); - } else { - this.setState({ - formError: null, - }); - - const { httpClient, intl, spacesEnabled } = this.props; - - saveRole(httpClient, this.state.role, spacesEnabled) - .then(() => { - toastNotifications.addSuccess( - intl.formatMessage({ - id: 'xpack.security.management.editRole.roleSuccessfullySavedNotificationMessage', - defaultMessage: 'Saved role', - }) - ); - this.backToRoleList(); - }) - .catch((error: any) => { - toastNotifications.addDanger(get(error, 'data.message')); - }); - } - }; - - private handleDeleteRole = () => { - const { httpClient, role, intl } = this.props; - - deleteRole(httpClient, role.name) - .then(() => { - toastNotifications.addSuccess( - intl.formatMessage({ - id: 'xpack.security.management.editRole.roleSuccessfullyDeletedNotificationMessage', - defaultMessage: 'Deleted role', - }) - ); - this.backToRoleList(); - }) - .catch((error: any) => { - toastNotifications.addDanger(get(error, 'data.message')); - }); - }; - - private backToRoleList = () => { - window.location.hash = ROLES_PATH; - }; -} - -export const EditRolePage = injectI18n(EditRolePageUI); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.test.tsx b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.test.tsx deleted file mode 100644 index 5ba3d1daf61acb..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.test.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { RoleValidator } from '../../../lib/validate_role'; -import { ClusterPrivileges } from './cluster_privileges'; -import { ElasticsearchPrivileges } from './elasticsearch_privileges'; -import { IndexPrivileges } from './index_privileges'; - -test('it renders without crashing', () => { - const props = { - role: { - name: '', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }, - editable: true, - httpClient: jest.fn(), - onChange: jest.fn(), - runAsUsers: [], - indexPatterns: [], - allowDocumentLevelSecurity: true, - allowFieldLevelSecurity: true, - validator: new RoleValidator(), - builtinESPrivileges: { - cluster: ['all', 'manage', 'monitor'], - index: ['all', 'read', 'write', 'index'], - }, - }; - const wrapper = shallowWithIntl(); - expect(wrapper).toMatchSnapshot(); -}); - -test('it renders ClusterPrivileges', () => { - const props = { - role: { - name: '', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }, - editable: true, - httpClient: jest.fn(), - onChange: jest.fn(), - runAsUsers: [], - indexPatterns: [], - allowDocumentLevelSecurity: true, - allowFieldLevelSecurity: true, - validator: new RoleValidator(), - builtinESPrivileges: { - cluster: ['all', 'manage', 'monitor'], - index: ['all', 'read', 'write', 'index'], - }, - }; - const wrapper = mountWithIntl(); - expect(wrapper.find(ClusterPrivileges)).toHaveLength(1); -}); - -test('it renders IndexPrivileges', () => { - const props = { - role: { - name: '', - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - }, - editable: true, - httpClient: jest.fn(), - onChange: jest.fn(), - runAsUsers: [], - indexPatterns: [], - allowDocumentLevelSecurity: true, - allowFieldLevelSecurity: true, - validator: new RoleValidator(), - builtinESPrivileges: { - cluster: ['all', 'manage', 'monitor'], - index: ['all', 'read', 'write', 'index'], - }, - }; - const wrapper = mountWithIntl(); - expect(wrapper.find(IndexPrivileges)).toHaveLength(1); -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.test.tsx b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.test.tsx deleted file mode 100644 index 783d2f9893b4cb..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.test.tsx +++ /dev/null @@ -1,74 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { RoleValidator } from '../../../lib/validate_role'; -import { IndexPrivilegeForm } from './index_privilege_form'; -import { IndexPrivileges } from './index_privileges'; - -// the IndexPrivileges post-mount hook kicks off some promises; -// we need to wait for those promises to resolve to ensure any errors are properly caught -const flushPromises = () => new Promise(setImmediate); - -test('it renders without crashing', async () => { - const props = { - role: { - name: '', - kibana: [], - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - }, - httpClient: jest.fn(), - onChange: jest.fn(), - indexPatterns: [], - editable: true, - allowDocumentLevelSecurity: true, - allowFieldLevelSecurity: true, - validator: new RoleValidator(), - availableIndexPrivileges: ['all', 'read', 'write', 'index'], - }; - const wrapper = shallowWithIntl(); - await flushPromises(); - expect(wrapper).toMatchSnapshot(); -}); - -test('it renders a IndexPrivilegeForm for each privilege on the role', async () => { - const props = { - role: { - name: '', - kibana: [], - elasticsearch: { - cluster: [], - indices: [ - { - names: ['foo*'], - privileges: ['all'], - query: '*', - field_security: { - grant: ['some_field'], - }, - }, - ], - run_as: [], - }, - }, - httpClient: jest.fn(), - onChange: jest.fn(), - indexPatterns: [], - editable: true, - allowDocumentLevelSecurity: true, - allowFieldLevelSecurity: true, - validator: new RoleValidator(), - availableIndexPrivileges: ['all', 'read', 'write', 'index'], - }; - const wrapper = mountWithIntl(); - await flushPromises(); - expect(wrapper.find(IndexPrivilegeForm)).toHaveLength(1); -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/edit_role.html b/x-pack/legacy/plugins/security/public/views/management/edit_role/edit_role.html deleted file mode 100644 index ca4073dcad6f5c..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/edit_role.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    - diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/index.js b/x-pack/legacy/plugins/security/public/views/management/edit_role/index.js deleted file mode 100644 index 27c9beb4ba8284..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/index.js +++ /dev/null @@ -1,176 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import _ from 'lodash'; -import routes from 'ui/routes'; -import { capabilities } from 'ui/capabilities'; -import { kfetch } from 'ui/kfetch'; -import { fatalError, toastNotifications } from 'ui/notify'; -import { npStart } from 'ui/new_platform'; -import template from 'plugins/security/views/management/edit_role/edit_role.html'; -import 'plugins/security/services/shield_role'; -import 'plugins/security/services/shield_indices'; -import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; -import { UserAPIClient } from '../../../lib/api'; -import { ROLES_PATH, CLONE_ROLES_PATH, EDIT_ROLES_PATH } from '../management_urls'; -import { getEditRoleBreadcrumbs, getCreateRoleBreadcrumbs } from '../breadcrumbs'; - -import { EditRolePage } from './components'; - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { I18nContext } from 'ui/i18n'; -import { i18n } from '@kbn/i18n'; - -const routeDefinition = action => ({ - template, - k7Breadcrumbs: ($injector, $route) => - $injector.invoke( - action === 'edit' && $route.current.params.name - ? getEditRoleBreadcrumbs - : getCreateRoleBreadcrumbs - ), - resolve: { - role($route, ShieldRole, Promise, kbnUrl) { - const name = $route.current.params.name; - - let role; - - if (name != null) { - role = ShieldRole.get({ name }).$promise.catch(response => { - if (response.status === 404) { - toastNotifications.addDanger({ - title: i18n.translate('xpack.security.management.roles.roleNotFound', { - defaultMessage: 'No "{roleName}" role found.', - values: { roleName: name }, - }), - }); - kbnUrl.redirect(ROLES_PATH); - } else { - return fatalError(response); - } - }); - } else { - role = Promise.resolve( - new ShieldRole({ - elasticsearch: { - cluster: [], - indices: [], - run_as: [], - }, - kibana: [], - _unrecognized_applications: [], - }) - ); - } - - return role.then(res => res.toJSON()); - }, - users() { - return new UserAPIClient().getUsers().then(users => _.map(users, 'username')); - }, - indexPatterns() { - return npStart.plugins.data.indexPatterns.getTitles(); - }, - spaces(spacesEnabled) { - if (spacesEnabled) { - return kfetch({ method: 'get', pathname: '/api/spaces/space' }); - } - return []; - }, - kibanaPrivileges() { - return kfetch({ - method: 'get', - pathname: '/api/security/privileges', - query: { includeActions: true }, - }); - }, - builtinESPrivileges() { - return kfetch({ method: 'get', pathname: '/internal/security/esPrivileges/builtin' }); - }, - features() { - return kfetch({ method: 'get', pathname: '/api/features' }).catch(e => { - // TODO: This check can be removed once all of these `resolve` entries are moved out of Angular and into the React app. - const unauthorizedForFeatures = _.get(e, 'body.statusCode') === 404; - if (unauthorizedForFeatures) { - return []; - } - throw e; - }); - }, - }, - controllerAs: 'editRole', - controller($injector, $scope, $http, enableSpaceAwarePrivileges) { - const $route = $injector.get('$route'); - const role = $route.current.locals.role; - - const allowDocumentLevelSecurity = xpackInfo.get( - 'features.security.allowRoleDocumentLevelSecurity' - ); - const allowFieldLevelSecurity = xpackInfo.get('features.security.allowRoleFieldLevelSecurity'); - if (role.elasticsearch.indices.length === 0) { - const emptyOption = { - names: [], - privileges: [], - }; - - if (allowFieldLevelSecurity) { - emptyOption.field_security = { - grant: ['*'], - except: [], - }; - } - - if (allowDocumentLevelSecurity) { - emptyOption.query = ''; - } - - role.elasticsearch.indices.push(emptyOption); - } - - const { - users, - indexPatterns, - spaces, - kibanaPrivileges, - builtinESPrivileges, - features, - } = $route.current.locals; - - $scope.$$postDigest(async () => { - const domNode = document.getElementById('editRoleReactRoot'); - - render( - - - , - domNode - ); - - // unmount react on controller destroy - $scope.$on('$destroy', () => { - unmountComponentAtNode(domNode); - }); - }); - }, -}); - -routes.when(`${CLONE_ROLES_PATH}/:name`, routeDefinition('clone')); -routes.when(`${EDIT_ROLES_PATH}/:name?`, routeDefinition('edit')); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/_index.scss b/x-pack/legacy/plugins/security/public/views/management/edit_user/_index.scss deleted file mode 100644 index c5da74aa3f785c..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_user/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './users'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.test.tsx deleted file mode 100644 index 639646ce48e224..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.test.tsx +++ /dev/null @@ -1,156 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { act } from '@testing-library/react'; -import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { EditUserPage } from './edit_user_page'; -import React from 'react'; -import { securityMock } from '../../../../../../../../plugins/security/public/mocks'; -import { UserAPIClient } from '../../../../lib/api'; -import { User, Role } from '../../../../../common/model'; -import { ReactWrapper } from 'enzyme'; -import { mockAuthenticatedUser } from '../../../../../../../../plugins/security/common/model/authenticated_user.mock'; - -jest.mock('ui/kfetch'); - -const createUser = (username: string) => { - const user: User = { - username, - full_name: 'my full name', - email: 'foo@bar.com', - roles: ['idk', 'something'], - enabled: true, - }; - - if (username === 'reserved_user') { - user.metadata = { - _reserved: true, - }; - } - - return user; -}; - -const buildClient = () => { - const apiClient = new UserAPIClient(); - - apiClient.getUser = jest - .fn() - .mockImplementation(async (username: string) => createUser(username)); - - apiClient.getRoles = jest.fn().mockImplementation(() => { - return Promise.resolve([ - { - name: 'role 1', - elasticsearch: { - cluster: ['all'], - indices: [], - run_as: [], - }, - kibana: [], - }, - { - name: 'role 2', - elasticsearch: { - cluster: [], - indices: [], - run_as: ['bar'], - }, - kibana: [], - }, - ] as Role[]); - }); - - return apiClient; -}; - -function buildSecuritySetup() { - const securitySetupMock = securityMock.createSetup(); - securitySetupMock.authc.getCurrentUser.mockResolvedValue( - mockAuthenticatedUser(createUser('current_user')) - ); - return securitySetupMock; -} - -function expectSaveButton(wrapper: ReactWrapper) { - expect(wrapper.find('EuiButton[data-test-subj="userFormSaveButton"]')).toHaveLength(1); -} - -function expectMissingSaveButton(wrapper: ReactWrapper) { - expect(wrapper.find('EuiButton[data-test-subj="userFormSaveButton"]')).toHaveLength(0); -} - -describe('EditUserPage', () => { - it('allows reserved users to be viewed', async () => { - const apiClient = buildClient(); - const securitySetup = buildSecuritySetup(); - const wrapper = mountWithIntl( - path} - intl={null as any} - /> - ); - - await waitForRender(wrapper); - - expect(apiClient.getUser).toBeCalledTimes(1); - expect(securitySetup.authc.getCurrentUser).toBeCalledTimes(1); - - expectMissingSaveButton(wrapper); - }); - - it('allows new users to be created', async () => { - const apiClient = buildClient(); - const securitySetup = buildSecuritySetup(); - const wrapper = mountWithIntl( - path} - intl={null as any} - /> - ); - - await waitForRender(wrapper); - - expect(apiClient.getUser).toBeCalledTimes(0); - expect(securitySetup.authc.getCurrentUser).toBeCalledTimes(0); - - expectSaveButton(wrapper); - }); - - it('allows existing users to be edited', async () => { - const apiClient = buildClient(); - const securitySetup = buildSecuritySetup(); - const wrapper = mountWithIntl( - path} - intl={null as any} - /> - ); - - await waitForRender(wrapper); - - expect(apiClient.getUser).toBeCalledTimes(1); - expect(securitySetup.authc.getCurrentUser).toBeCalledTimes(1); - - expectSaveButton(wrapper); - }); -}); - -async function waitForRender(wrapper: ReactWrapper) { - await act(async () => { - await nextTick(); - wrapper.update(); - }); -} diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.html b/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.html deleted file mode 100644 index 4fa2768480874a..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    - diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.js b/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.js deleted file mode 100644 index ab218022c6ee64..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.js +++ /dev/null @@ -1,58 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import routes from 'ui/routes'; -import template from 'plugins/security/views/management/edit_user/edit_user.html'; -import 'angular-resource'; -import 'ui/angular_ui_select'; -import 'plugins/security/services/shield_role'; -import { EDIT_USERS_PATH } from '../management_urls'; -import { EditUserPage } from './components'; -import { UserAPIClient } from '../../../lib/api'; -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { I18nContext } from 'ui/i18n'; -import { npSetup } from 'ui/new_platform'; -import { getEditUserBreadcrumbs, getCreateUserBreadcrumbs } from '../breadcrumbs'; - -const renderReact = (elem, changeUrl, username) => { - render( - - - , - elem - ); -}; - -routes.when(`${EDIT_USERS_PATH}/:username?`, { - template, - k7Breadcrumbs: ($injector, $route) => - $injector.invoke( - $route.current.params.username ? getEditUserBreadcrumbs : getCreateUserBreadcrumbs - ), - controllerAs: 'editUser', - controller($scope, $route, kbnUrl) { - $scope.$on('$destroy', () => { - const elem = document.getElementById('editUserReactRoot'); - if (elem) { - unmountComponentAtNode(elem); - } - }); - $scope.$$postDigest(() => { - const elem = document.getElementById('editUserReactRoot'); - const username = $route.current.params.username; - const changeUrl = url => { - kbnUrl.change(url); - $scope.$apply(); - }; - renderReact(elem, changeUrl, username); - }); - }, -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/index.js b/x-pack/legacy/plugins/security/public/views/management/index.js deleted file mode 100644 index 0ed6fe09ef80a4..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/index.js +++ /dev/null @@ -1,7 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import './management'; diff --git a/x-pack/legacy/plugins/security/public/views/management/management.js b/x-pack/legacy/plugins/security/public/views/management/management.js deleted file mode 100644 index f0369f232aeba8..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/management.js +++ /dev/null @@ -1,134 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import 'plugins/security/views/management/change_password_form/change_password_form'; -import 'plugins/security/views/management/password_form/password_form'; -import 'plugins/security/views/management/users_grid/users'; -import 'plugins/security/views/management/roles_grid/roles'; -import 'plugins/security/views/management/api_keys_grid/api_keys'; -import 'plugins/security/views/management/edit_user/edit_user'; -import 'plugins/security/views/management/edit_role/index'; -import 'plugins/security/views/management/role_mappings/role_mappings_grid'; -import 'plugins/security/views/management/role_mappings/edit_role_mapping'; -import routes from 'ui/routes'; -import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; -import { ROLES_PATH, USERS_PATH, API_KEYS_PATH, ROLE_MAPPINGS_PATH } from './management_urls'; - -import { management } from 'ui/management'; -import { npSetup } from 'ui/new_platform'; -import { i18n } from '@kbn/i18n'; -import { toastNotifications } from 'ui/notify'; - -routes - .defaults(/^\/management\/security(\/|$)/, { - resolve: { - showLinks(kbnUrl, Promise) { - if (!xpackInfo.get('features.security.showLinks')) { - toastNotifications.addDanger({ - title: xpackInfo.get('features.security.linksMessage'), - }); - kbnUrl.redirect('/management'); - return Promise.halt(); - } - }, - }, - }) - .defaults(/\/management/, { - resolve: { - securityManagementSection: function() { - const showSecurityLinks = xpackInfo.get('features.security.showLinks'); - const showRoleMappingsManagementLink = xpackInfo.get( - 'features.security.showRoleMappingsManagement' - ); - - function deregisterSecurity() { - management.deregister('security'); - } - - function deregisterRoleMappingsManagement() { - if (management.hasItem('security')) { - const security = management.getSection('security'); - if (security.hasItem('roleMappings')) { - security.deregister('roleMappings'); - } - } - } - - function ensureSecurityRegistered() { - const registerSecurity = () => - management.register('security', { - display: i18n.translate('xpack.security.management.securityTitle', { - defaultMessage: 'Security', - }), - order: 100, - icon: 'securityApp', - }); - const getSecurity = () => management.getSection('security'); - - const security = management.hasItem('security') ? getSecurity() : registerSecurity(); - - if (!security.hasItem('users')) { - security.register('users', { - name: 'securityUsersLink', - order: 10, - display: i18n.translate('xpack.security.management.usersTitle', { - defaultMessage: 'Users', - }), - url: `#${USERS_PATH}`, - }); - } - - if (!security.hasItem('roles')) { - security.register('roles', { - name: 'securityRolesLink', - order: 20, - display: i18n.translate('xpack.security.management.rolesTitle', { - defaultMessage: 'Roles', - }), - url: `#${ROLES_PATH}`, - }); - } - - if (!security.hasItem('apiKeys')) { - security.register('apiKeys', { - name: 'securityApiKeysLink', - order: 30, - display: i18n.translate('xpack.security.management.apiKeysTitle', { - defaultMessage: 'API Keys', - }), - url: `#${API_KEYS_PATH}`, - }); - } - - if (showRoleMappingsManagementLink && !security.hasItem('roleMappings')) { - security.register('roleMappings', { - name: 'securityRoleMappingLink', - order: 30, - display: i18n.translate('xpack.security.management.roleMappingsTitle', { - defaultMessage: 'Role Mappings', - }), - url: `#${ROLE_MAPPINGS_PATH}`, - }); - } - } - - if (!showSecurityLinks) { - deregisterSecurity(); - } else { - if (!showRoleMappingsManagementLink) { - deregisterRoleMappingsManagement(); - } - - // getCurrentUser will reject if there is no authenticated user, so we prevent them from - // seeing the security management screens. - return npSetup.plugins.security.authc - .getCurrentUser() - .then(ensureSecurityRegistered) - .catch(deregisterSecurity); - } - }, - }, - }); diff --git a/x-pack/legacy/plugins/security/public/views/management/management_urls.ts b/x-pack/legacy/plugins/security/public/views/management/management_urls.ts deleted file mode 100644 index 881740c0b2895b..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/management_urls.ts +++ /dev/null @@ -1,24 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export const MANAGEMENT_PATH = '/management'; -export const SECURITY_PATH = `${MANAGEMENT_PATH}/security`; -export const ROLES_PATH = `${SECURITY_PATH}/roles`; -export const EDIT_ROLES_PATH = `${ROLES_PATH}/edit`; -export const CLONE_ROLES_PATH = `${ROLES_PATH}/clone`; -export const USERS_PATH = `${SECURITY_PATH}/users`; -export const EDIT_USERS_PATH = `${USERS_PATH}/edit`; -export const API_KEYS_PATH = `${SECURITY_PATH}/api_keys`; -export const ROLE_MAPPINGS_PATH = `${SECURITY_PATH}/role_mappings`; -export const CREATE_ROLE_MAPPING_PATH = `${ROLE_MAPPINGS_PATH}/edit`; - -export const getEditRoleHref = (roleName: string) => - `#${EDIT_ROLES_PATH}/${encodeURIComponent(roleName)}`; - -export const getCreateRoleMappingHref = () => `#${CREATE_ROLE_MAPPING_PATH}`; - -export const getEditRoleMappingHref = (roleMappingName: string) => - `#${CREATE_ROLE_MAPPING_PATH}/${encodeURIComponent(roleMappingName)}`; diff --git a/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.html b/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.html deleted file mode 100644 index 72956992100f5e..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.html +++ /dev/null @@ -1,53 +0,0 @@ - - -
    - - - - -
    -
    - - -
    - - - - -
    -
    -
    diff --git a/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.js b/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.js deleted file mode 100644 index edcccdb5e6e697..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.js +++ /dev/null @@ -1,24 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { uiModules } from 'ui/modules'; -import template from './password_form.html'; - -const module = uiModules.get('security', ['kibana']); -module.directive('kbnPasswordForm', function() { - return { - template, - scope: { - password: '=', - }, - restrict: 'E', - replace: true, - controllerAs: 'passwordController', - controller: function() { - this.confirmation = null; - }, - }; -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.test.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.test.tsx deleted file mode 100644 index b826d68053e276..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.test.tsx +++ /dev/null @@ -1,301 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { DeleteProvider } from '.'; -import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api'; -import { RoleMapping } from '../../../../../../common/model'; -import { EuiConfirmModal } from '@elastic/eui'; -import { findTestSubject } from 'test_utils/find_test_subject'; -import { act } from '@testing-library/react'; -import { toastNotifications } from 'ui/notify'; - -jest.mock('ui/notify', () => { - return { - toastNotifications: { - addError: jest.fn(), - addSuccess: jest.fn(), - addDanger: jest.fn(), - }, - }; -}); - -describe('DeleteProvider', () => { - beforeEach(() => { - jest.resetAllMocks(); - }); - - it('allows a single role mapping to be deleted', async () => { - const props = { - roleMappingsAPI: ({ - deleteRoleMappings: jest.fn().mockReturnValue( - Promise.resolve([ - { - name: 'delete-me', - success: true, - }, - ]) - ), - } as unknown) as RoleMappingsAPI, - }; - - const roleMappingsToDelete = [ - { - name: 'delete-me', - }, - ] as RoleMapping[]; - - const onSuccess = jest.fn(); - - const wrapper = mountWithIntl( - - {onDelete => ( - - )} - - ); - - await act(async () => { - wrapper.find('#invoker').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - const { title, confirmButtonText } = wrapper.find(EuiConfirmModal).props(); - expect(title).toMatchInlineSnapshot(`"Delete role mapping 'delete-me'?"`); - expect(confirmButtonText).toMatchInlineSnapshot(`"Delete role mapping"`); - - await act(async () => { - findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['delete-me']); - - const notifications = toastNotifications as jest.Mocked; - expect(notifications.addError).toHaveBeenCalledTimes(0); - expect(notifications.addDanger).toHaveBeenCalledTimes(0); - expect(notifications.addSuccess).toHaveBeenCalledTimes(1); - expect(notifications.addSuccess.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data-test-subj": "deletedRoleMappingSuccessToast", - "title": "Deleted role mapping 'delete-me'", - }, - ] - `); - }); - - it('allows multiple role mappings to be deleted', async () => { - const props = { - roleMappingsAPI: ({ - deleteRoleMappings: jest.fn().mockReturnValue( - Promise.resolve([ - { - name: 'delete-me', - success: true, - }, - { - name: 'delete-me-too', - success: true, - }, - ]) - ), - } as unknown) as RoleMappingsAPI, - }; - - const roleMappingsToDelete = [ - { - name: 'delete-me', - }, - { - name: 'delete-me-too', - }, - ] as RoleMapping[]; - - const onSuccess = jest.fn(); - - const wrapper = mountWithIntl( - - {onDelete => ( - - )} - - ); - - await act(async () => { - wrapper.find('#invoker').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - const { title, confirmButtonText } = wrapper.find(EuiConfirmModal).props(); - expect(title).toMatchInlineSnapshot(`"Delete 2 role mappings?"`); - expect(confirmButtonText).toMatchInlineSnapshot(`"Delete role mappings"`); - - await act(async () => { - findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith([ - 'delete-me', - 'delete-me-too', - ]); - const notifications = toastNotifications as jest.Mocked; - expect(notifications.addError).toHaveBeenCalledTimes(0); - expect(notifications.addDanger).toHaveBeenCalledTimes(0); - expect(notifications.addSuccess).toHaveBeenCalledTimes(1); - expect(notifications.addSuccess.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data-test-subj": "deletedRoleMappingSuccessToast", - "title": "Deleted 2 role mappings", - }, - ] - `); - }); - - it('handles mixed success/failure conditions', async () => { - const props = { - roleMappingsAPI: ({ - deleteRoleMappings: jest.fn().mockReturnValue( - Promise.resolve([ - { - name: 'delete-me', - success: true, - }, - { - name: 'i-wont-work', - success: false, - error: new Error('something went wrong. sad.'), - }, - ]) - ), - } as unknown) as RoleMappingsAPI, - }; - - const roleMappingsToDelete = [ - { - name: 'delete-me', - }, - { - name: 'i-wont-work', - }, - ] as RoleMapping[]; - - const onSuccess = jest.fn(); - - const wrapper = mountWithIntl( - - {onDelete => ( - - )} - - ); - - await act(async () => { - wrapper.find('#invoker').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - await act(async () => { - findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith([ - 'delete-me', - 'i-wont-work', - ]); - - const notifications = toastNotifications as jest.Mocked; - expect(notifications.addError).toHaveBeenCalledTimes(0); - expect(notifications.addSuccess).toHaveBeenCalledTimes(1); - expect(notifications.addSuccess.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data-test-subj": "deletedRoleMappingSuccessToast", - "title": "Deleted role mapping 'delete-me'", - }, - ] - `); - - expect(notifications.addDanger).toHaveBeenCalledTimes(1); - expect(notifications.addDanger.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "Error deleting role mapping 'i-wont-work'", - ] - `); - }); - - it('handles errors calling the API', async () => { - const props = { - roleMappingsAPI: ({ - deleteRoleMappings: jest.fn().mockImplementation(() => { - throw new Error('AHHHHH'); - }), - } as unknown) as RoleMappingsAPI, - }; - - const roleMappingsToDelete = [ - { - name: 'delete-me', - }, - ] as RoleMapping[]; - - const onSuccess = jest.fn(); - - const wrapper = mountWithIntl( - - {onDelete => ( - - )} - - ); - - await act(async () => { - wrapper.find('#invoker').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - await act(async () => { - findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['delete-me']); - - const notifications = toastNotifications as jest.Mocked; - expect(notifications.addDanger).toHaveBeenCalledTimes(0); - expect(notifications.addSuccess).toHaveBeenCalledTimes(0); - - expect(notifications.addError).toHaveBeenCalledTimes(1); - expect(notifications.addError.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - [Error: AHHHHH], - Object { - "title": "Error deleting role mappings", - }, - ] - `); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/_index.scss b/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/_index.scss deleted file mode 100644 index 80e08ebcf12267..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './components/rule_editor_panel/index'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.test.tsx deleted file mode 100644 index 375a8d9f374a86..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.test.tsx +++ /dev/null @@ -1,341 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { findTestSubject } from 'test_utils/find_test_subject'; - -// brace/ace uses the Worker class, which is not currently provided by JSDOM. -// This is not required for the tests to pass, but it rather suppresses lengthy -// warnings in the console which adds unnecessary noise to the test output. -import 'test_utils/stub_web_worker'; - -import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api'; -import { EditRoleMappingPage } from '.'; -import { NoCompatibleRealms, SectionLoading, PermissionDenied } from '../../components'; -import { VisualRuleEditor } from './rule_editor_panel/visual_rule_editor'; -import { JSONRuleEditor } from './rule_editor_panel/json_rule_editor'; -import { EuiComboBox } from '@elastic/eui'; - -jest.mock('../../../../../lib/roles_api', () => { - return { - RolesApi: { - getRoles: () => Promise.resolve([{ name: 'foo_role' }, { name: 'bar role' }]), - }, - }; -}); - -describe('EditRoleMappingPage', () => { - it('allows a role mapping to be created', async () => { - const roleMappingsAPI = ({ - saveRoleMapping: jest.fn().mockResolvedValue(null), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - canUseInlineScripts: true, - canUseStoredScripts: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - - await nextTick(); - wrapper.update(); - - findTestSubject(wrapper, 'roleMappingFormNameInput').simulate('change', { - target: { value: 'my-role-mapping' }, - }); - - (wrapper - .find(EuiComboBox) - .filter('[data-test-subj="roleMappingFormRoleComboBox"]') - .props() as any).onChange([{ label: 'foo_role' }]); - - findTestSubject(wrapper, 'roleMappingsAddRuleButton').simulate('click'); - - findTestSubject(wrapper, 'saveRoleMappingButton').simulate('click'); - - expect(roleMappingsAPI.saveRoleMapping).toHaveBeenCalledWith({ - name: 'my-role-mapping', - enabled: true, - roles: ['foo_role'], - role_templates: [], - rules: { - all: [{ field: { username: '*' } }], - }, - metadata: {}, - }); - }); - - it('allows a role mapping to be updated', async () => { - const roleMappingsAPI = ({ - saveRoleMapping: jest.fn().mockResolvedValue(null), - getRoleMapping: jest.fn().mockResolvedValue({ - name: 'foo', - role_templates: [ - { - template: { id: 'foo' }, - }, - ], - enabled: true, - rules: { - any: [{ field: { 'metadata.someCustomOption': [false, true, 'asdf'] } }], - }, - metadata: { - foo: 'bar', - bar: 'baz', - }, - }), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - canUseInlineScripts: true, - canUseStoredScripts: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl( - - ); - - await nextTick(); - wrapper.update(); - - findTestSubject(wrapper, 'switchToRolesButton').simulate('click'); - - (wrapper - .find(EuiComboBox) - .filter('[data-test-subj="roleMappingFormRoleComboBox"]') - .props() as any).onChange([{ label: 'foo_role' }]); - - findTestSubject(wrapper, 'roleMappingsAddRuleButton').simulate('click'); - wrapper.find('button[id="addRuleOption"]').simulate('click'); - - findTestSubject(wrapper, 'saveRoleMappingButton').simulate('click'); - - expect(roleMappingsAPI.saveRoleMapping).toHaveBeenCalledWith({ - name: 'foo', - enabled: true, - roles: ['foo_role'], - role_templates: [], - rules: { - any: [ - { field: { 'metadata.someCustomOption': [false, true, 'asdf'] } }, - { field: { username: '*' } }, - ], - }, - metadata: { - foo: 'bar', - bar: 'baz', - }, - }); - }); - - it('renders a permission denied message when unauthorized to manage role mappings', async () => { - const roleMappingsAPI = ({ - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: false, - hasCompatibleRealms: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - expect(wrapper.find(SectionLoading)).toHaveLength(1); - expect(wrapper.find(PermissionDenied)).toHaveLength(0); - - await nextTick(); - wrapper.update(); - - expect(wrapper.find(SectionLoading)).toHaveLength(0); - expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); - expect(wrapper.find(PermissionDenied)).toHaveLength(1); - }); - - it('renders a warning when there are no compatible realms enabled', async () => { - const roleMappingsAPI = ({ - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: false, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - expect(wrapper.find(SectionLoading)).toHaveLength(1); - expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); - - await nextTick(); - wrapper.update(); - - expect(wrapper.find(SectionLoading)).toHaveLength(0); - expect(wrapper.find(NoCompatibleRealms)).toHaveLength(1); - }); - - it('renders a warning when editing a mapping with a stored role template, when stored scripts are disabled', async () => { - const roleMappingsAPI = ({ - getRoleMapping: jest.fn().mockResolvedValue({ - name: 'foo', - role_templates: [ - { - template: { id: 'foo' }, - }, - ], - enabled: true, - rules: { - field: { username: '*' }, - }, - }), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - canUseInlineScripts: true, - canUseStoredScripts: false, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl( - - ); - - expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0); - expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0); - - await nextTick(); - wrapper.update(); - - expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0); - expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(1); - }); - - it('renders a warning when editing a mapping with an inline role template, when inline scripts are disabled', async () => { - const roleMappingsAPI = ({ - getRoleMapping: jest.fn().mockResolvedValue({ - name: 'foo', - role_templates: [ - { - template: { source: 'foo' }, - }, - ], - enabled: true, - rules: { - field: { username: '*' }, - }, - }), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - canUseInlineScripts: false, - canUseStoredScripts: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl( - - ); - - expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0); - expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0); - - await nextTick(); - wrapper.update(); - - expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(1); - expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0); - }); - - it('renders the visual editor by default for simple rule sets', async () => { - const roleMappingsAPI = ({ - getRoleMapping: jest.fn().mockResolvedValue({ - name: 'foo', - roles: ['superuser'], - enabled: true, - rules: { - all: [ - { - field: { - username: '*', - }, - }, - { - field: { - dn: null, - }, - }, - { - field: { - realm: ['ldap', 'pki', null, 12], - }, - }, - ], - }, - }), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - canUseInlineScripts: true, - canUseStoredScripts: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl( - - ); - - await nextTick(); - wrapper.update(); - - expect(wrapper.find(VisualRuleEditor)).toHaveLength(1); - expect(wrapper.find(JSONRuleEditor)).toHaveLength(0); - }); - - it('renders the JSON editor by default for complex rule sets', async () => { - const createRule = (depth: number): Record => { - if (depth > 0) { - const rule = { - all: [ - { - field: { - username: '*', - }, - }, - ], - } as Record; - - const subRule = createRule(depth - 1); - if (subRule) { - rule.all.push(subRule); - } - - return rule; - } - return null as any; - }; - - const roleMappingsAPI = ({ - getRoleMapping: jest.fn().mockResolvedValue({ - name: 'foo', - roles: ['superuser'], - enabled: true, - rules: createRule(10), - }), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - canUseInlineScripts: true, - canUseStoredScripts: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl( - - ); - - await nextTick(); - wrapper.update(); - - expect(wrapper.find(VisualRuleEditor)).toHaveLength(0); - expect(wrapper.find(JSONRuleEditor)).toHaveLength(1); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/edit_role_mapping.html b/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/edit_role_mapping.html deleted file mode 100644 index ca8ab9c35c49ba..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/edit_role_mapping.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    - diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/index.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/index.tsx deleted file mode 100644 index b064a4dc50a228..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/index.tsx +++ /dev/null @@ -1,45 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import routes from 'ui/routes'; -import { I18nContext } from 'ui/i18n'; -import { npSetup } from 'ui/new_platform'; -import { RoleMappingsAPI } from '../../../../lib/role_mappings_api'; -// @ts-ignore -import template from './edit_role_mapping.html'; -import { CREATE_ROLE_MAPPING_PATH } from '../../management_urls'; -import { getEditRoleMappingBreadcrumbs } from '../../breadcrumbs'; -import { EditRoleMappingPage } from './components'; - -routes.when(`${CREATE_ROLE_MAPPING_PATH}/:name?`, { - template, - k7Breadcrumbs: getEditRoleMappingBreadcrumbs, - controller($scope, $route) { - $scope.$$postDigest(() => { - const domNode = document.getElementById('editRoleMappingReactRoot'); - - const { name } = $route.current.params; - - render( - - - , - domNode - ); - - // unmount react on controller destroy - $scope.$on('$destroy', () => { - if (domNode) { - unmountComponentAtNode(domNode); - } - }); - }); - }, -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.test.tsx deleted file mode 100644 index 259cdc71e25a22..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.test.tsx +++ /dev/null @@ -1,182 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { RoleMappingsGridPage } from '.'; -import { SectionLoading, PermissionDenied, NoCompatibleRealms } from '../../components'; -import { EmptyPrompt } from './empty_prompt'; -import { findTestSubject } from 'test_utils/find_test_subject'; -import { EuiLink } from '@elastic/eui'; -import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api'; -import { act } from '@testing-library/react'; - -describe('RoleMappingsGridPage', () => { - it('renders an empty prompt when no role mappings exist', async () => { - const roleMappingsAPI = ({ - getRoleMappings: jest.fn().mockResolvedValue([]), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - expect(wrapper.find(SectionLoading)).toHaveLength(1); - expect(wrapper.find(EmptyPrompt)).toHaveLength(0); - - await nextTick(); - wrapper.update(); - - expect(wrapper.find(SectionLoading)).toHaveLength(0); - expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); - expect(wrapper.find(EmptyPrompt)).toHaveLength(1); - }); - - it('renders a permission denied message when unauthorized to manage role mappings', async () => { - const roleMappingsAPI = ({ - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: false, - hasCompatibleRealms: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - expect(wrapper.find(SectionLoading)).toHaveLength(1); - expect(wrapper.find(PermissionDenied)).toHaveLength(0); - - await nextTick(); - wrapper.update(); - - expect(wrapper.find(SectionLoading)).toHaveLength(0); - expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); - expect(wrapper.find(PermissionDenied)).toHaveLength(1); - }); - - it('renders a warning when there are no compatible realms enabled', async () => { - const roleMappingsAPI = ({ - getRoleMappings: jest.fn().mockResolvedValue([ - { - name: 'some realm', - enabled: true, - roles: [], - rules: { field: { username: '*' } }, - }, - ]), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: false, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - expect(wrapper.find(SectionLoading)).toHaveLength(1); - expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); - - await nextTick(); - wrapper.update(); - - expect(wrapper.find(SectionLoading)).toHaveLength(0); - expect(wrapper.find(NoCompatibleRealms)).toHaveLength(1); - }); - - it('renders links to mapped roles', async () => { - const roleMappingsAPI = ({ - getRoleMappings: jest.fn().mockResolvedValue([ - { - name: 'some realm', - enabled: true, - roles: ['superuser'], - rules: { field: { username: '*' } }, - }, - ]), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - await nextTick(); - wrapper.update(); - - const links = findTestSubject(wrapper, 'roleMappingRoles').find(EuiLink); - expect(links).toHaveLength(1); - expect(links.at(0).props()).toMatchObject({ - href: '#/management/security/roles/edit/superuser', - }); - }); - - it('describes the number of mapped role templates', async () => { - const roleMappingsAPI = ({ - getRoleMappings: jest.fn().mockResolvedValue([ - { - name: 'some realm', - enabled: true, - role_templates: [{}, {}], - rules: { field: { username: '*' } }, - }, - ]), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - }), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - await nextTick(); - wrapper.update(); - - const templates = findTestSubject(wrapper, 'roleMappingRoles'); - expect(templates).toHaveLength(1); - expect(templates.text()).toEqual(`2 role templates defined`); - }); - - it('allows role mappings to be deleted, refreshing the grid after', async () => { - const roleMappingsAPI = ({ - getRoleMappings: jest.fn().mockResolvedValue([ - { - name: 'some-realm', - enabled: true, - roles: ['superuser'], - rules: { field: { username: '*' } }, - }, - ]), - checkRoleMappingFeatures: jest.fn().mockResolvedValue({ - canManageRoleMappings: true, - hasCompatibleRealms: true, - }), - deleteRoleMappings: jest.fn().mockReturnValue( - Promise.resolve([ - { - name: 'some-realm', - success: true, - }, - ]) - ), - } as unknown) as RoleMappingsAPI; - - const wrapper = mountWithIntl(); - await nextTick(); - wrapper.update(); - - expect(roleMappingsAPI.getRoleMappings).toHaveBeenCalledTimes(1); - expect(roleMappingsAPI.deleteRoleMappings).not.toHaveBeenCalled(); - - findTestSubject(wrapper, `deleteRoleMappingButton-some-realm`).simulate('click'); - expect(findTestSubject(wrapper, 'deleteRoleMappingConfirmationModal')).toHaveLength(1); - - await act(async () => { - findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); - await nextTick(); - wrapper.update(); - }); - - expect(roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['some-realm']); - // Expect an additional API call to refresh the grid - expect(roleMappingsAPI.getRoleMappings).toHaveBeenCalledTimes(2); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/index.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/index.tsx deleted file mode 100644 index 9e925d0fa6dc0a..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/index.tsx +++ /dev/null @@ -1,40 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import routes from 'ui/routes'; -import { I18nContext } from 'ui/i18n'; -import { npSetup } from 'ui/new_platform'; -import { RoleMappingsAPI } from '../../../../lib/role_mappings_api'; -// @ts-ignore -import template from './role_mappings.html'; -import { ROLE_MAPPINGS_PATH } from '../../management_urls'; -import { getRoleMappingBreadcrumbs } from '../../breadcrumbs'; -import { RoleMappingsGridPage } from './components'; - -routes.when(ROLE_MAPPINGS_PATH, { - template, - k7Breadcrumbs: getRoleMappingBreadcrumbs, - controller($scope) { - $scope.$$postDigest(() => { - const domNode = document.getElementById('roleMappingsGridReactRoot'); - - render( - - - , - domNode - ); - - // unmount react on controller destroy - $scope.$on('$destroy', () => { - if (domNode) { - unmountComponentAtNode(domNode); - } - }); - }); - }, -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/role_mappings.html b/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/role_mappings.html deleted file mode 100644 index cff3b821d132c0..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/role_mappings.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    - diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/services/documentation_links.ts b/x-pack/legacy/plugins/security/public/views/management/role_mappings/services/documentation_links.ts deleted file mode 100644 index 36351f49890a1c..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/services/documentation_links.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; - -class DocumentationLinksService { - private esDocBasePath = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}`; - - public getRoleMappingDocUrl() { - return `${this.esDocBasePath}/mapping-roles.html`; - } - - public getRoleMappingAPIDocUrl() { - return `${this.esDocBasePath}/security-api-put-role-mapping.html`; - } - - public getRoleMappingTemplateDocUrl() { - return `${this.esDocBasePath}/security-api-put-role-mapping.html#_role_templates`; - } - - public getRoleMappingFieldRulesDocUrl() { - return `${this.esDocBasePath}/role-mapping-resources.html#mapping-roles-rule-field`; - } -} - -export const documentationLinks = new DocumentationLinksService(); diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/confirm_delete.tsx b/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/confirm_delete.tsx deleted file mode 100644 index 34784b4b2accb6..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/confirm_delete.tsx +++ /dev/null @@ -1,171 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - EuiButton, - EuiButtonEmpty, - EuiModal, - EuiModalBody, - EuiModalFooter, - EuiModalHeader, - EuiModalHeaderTitle, - EuiOverlayMask, - EuiText, -} from '@elastic/eui'; -import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; -import React, { Component, Fragment } from 'react'; -import { toastNotifications } from 'ui/notify'; -import { RolesApi } from '../../../../../lib/roles_api'; - -interface Props { - rolesToDelete: string[]; - intl: InjectedIntl; - callback: (rolesToDelete: string[], errors: string[]) => void; - onCancel: () => void; -} - -interface State { - deleteInProgress: boolean; -} - -class ConfirmDeleteUI extends Component { - constructor(props: Props) { - super(props); - this.state = { - deleteInProgress: false, - }; - } - - public render() { - const { rolesToDelete, intl } = this.props; - const moreThanOne = rolesToDelete.length > 1; - const title = intl.formatMessage( - { - id: 'xpack.security.management.roles.deleteRoleTitle', - defaultMessage: 'Delete role{value, plural, one {{roleName}} other {s}}', - }, - { value: rolesToDelete.length, roleName: ` ${rolesToDelete[0]}` } - ); - - // This is largely the same as the built-in EuiConfirmModal component, but we needed the ability - // to disable the buttons since this could be a long-running operation - - return ( - - - - - {title} - - - - - {moreThanOne ? ( - -

    - -

    -
      - {rolesToDelete.map(roleName => ( -
    • {roleName}
    • - ))} -
    -
    - ) : null} -

    - -

    -
    -
    - - - - - - - - - -
    -
    - ); - } - - private onConfirmDelete = () => { - this.setState( - { - deleteInProgress: true, - }, - () => { - this.deleteRoles(); - } - ); - }; - - private deleteRoles = async () => { - const { rolesToDelete, callback } = this.props; - const errors: string[] = []; - const deleteOperations = rolesToDelete.map(roleName => { - const deleteRoleTask = async () => { - try { - await RolesApi.deleteRole(roleName); - toastNotifications.addSuccess( - this.props.intl.formatMessage( - { - id: - 'xpack.security.management.roles.confirmDelete.roleSuccessfullyDeletedNotificationMessage', - defaultMessage: 'Deleted role {roleName}', - }, - { roleName } - ) - ); - } catch (e) { - errors.push(roleName); - toastNotifications.addDanger( - this.props.intl.formatMessage( - { - id: - 'xpack.security.management.roles.confirmDelete.roleDeletingErrorNotificationMessage', - defaultMessage: 'Error deleting role {roleName}', - }, - { roleName } - ) - ); - } - }; - - return deleteRoleTask(); - }); - - await Promise.all(deleteOperations); - - callback(rolesToDelete, errors); - }; -} - -export const ConfirmDelete = injectI18n(ConfirmDeleteUI); diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.test.tsx deleted file mode 100644 index 6da2f2442d488b..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.test.tsx +++ /dev/null @@ -1,121 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -let mockSimulate403 = false; -const mock403 = () => ({ body: { statusCode: 403 } }); -jest.mock('../../../../lib/roles_api', () => { - return { - RolesApi: { - async getRoles() { - if (mockSimulate403) { - throw mock403(); - } - return [ - { - name: 'test-role-1', - elasticsearch: { cluster: [], indices: [], run_as: [] }, - kibana: { global: [], space: {} }, - }, - { - name: 'reserved-role', - elasticsearch: { cluster: [], indices: [], run_as: [] }, - kibana: { global: [], space: {} }, - metadata: { - _reserved: true, - }, - }, - { - name: 'disabled-role', - elasticsearch: { cluster: [], indices: [], run_as: [] }, - kibana: { global: [], space: {} }, - transient_metadata: { - enabled: false, - }, - }, - ]; - }, - }, - }; -}); - -import { EuiIcon } from '@elastic/eui'; -import { ReactWrapper } from 'enzyme'; -import React from 'react'; -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { PermissionDenied } from './permission_denied'; -import { RolesGridPage } from './roles_grid_page'; - -const waitForRender = async ( - wrapper: ReactWrapper, - condition: (wrapper: ReactWrapper) => boolean -) => { - return new Promise((resolve, reject) => { - const interval = setInterval(async () => { - await Promise.resolve(); - wrapper.update(); - if (condition(wrapper)) { - resolve(); - } - }, 10); - - setTimeout(() => { - clearInterval(interval); - reject(new Error('waitForRender timeout after 2000ms')); - }, 2000); - }); -}; - -describe('', () => { - beforeEach(() => { - mockSimulate403 = false; - }); - - it(`renders reserved roles as such`, async () => { - const wrapper = mountWithIntl(); - const initialIconCount = wrapper.find(EuiIcon).length; - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(EuiIcon).length > initialIconCount; - }); - - expect(wrapper.find(PermissionDenied)).toHaveLength(0); - expect(wrapper.find('EuiIcon[data-test-subj="reservedRole"]')).toHaveLength(1); - expect(wrapper.find('EuiCheckbox[title="Role is reserved"]')).toHaveLength(1); - }); - - it('renders permission denied if required', async () => { - mockSimulate403 = true; - const wrapper = mountWithIntl(); - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(PermissionDenied).length > 0; - }); - expect(wrapper.find(PermissionDenied)).toMatchSnapshot(); - }); - - it('renders role actions as appropriate', async () => { - const wrapper = mountWithIntl(); - const initialIconCount = wrapper.find(EuiIcon).length; - - await waitForRender(wrapper, updatedWrapper => { - return updatedWrapper.find(EuiIcon).length > initialIconCount; - }); - - expect(wrapper.find(PermissionDenied)).toHaveLength(0); - expect( - wrapper.find('EuiButtonIcon[data-test-subj="edit-role-action-test-role-1"]') - ).toHaveLength(1); - expect( - wrapper.find('EuiButtonIcon[data-test-subj="edit-role-action-disabled-role"]') - ).toHaveLength(1); - - expect( - wrapper.find('EuiButtonIcon[data-test-subj="clone-role-action-test-role-1"]') - ).toHaveLength(1); - expect( - wrapper.find('EuiButtonIcon[data-test-subj="clone-role-action-disabled-role"]') - ).toHaveLength(1); - }); -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.html b/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.html deleted file mode 100644 index 0552b655afafd9..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    - diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.js b/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.js deleted file mode 100644 index e9c42824711b31..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import routes from 'ui/routes'; -import template from 'plugins/security/views/management/roles_grid/roles.html'; -import { ROLES_PATH } from '../management_urls'; -import { getRolesBreadcrumbs } from '../breadcrumbs'; -import { I18nContext } from 'ui/i18n'; -import { RolesGridPage } from './components'; - -routes.when(ROLES_PATH, { - template, - k7Breadcrumbs: getRolesBreadcrumbs, - controller($scope) { - $scope.$$postDigest(() => { - const domNode = document.getElementById('rolesGridReactRoot'); - - render( - - - , - domNode - ); - - // unmount react on controller destroy - $scope.$on('$destroy', () => { - unmountComponentAtNode(domNode); - }); - }); - }, -}); diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/index.ts b/x-pack/legacy/plugins/security/public/views/management/users_grid/components/index.ts deleted file mode 100644 index 03721f5ce93b1f..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/index.ts +++ /dev/null @@ -1,7 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { UsersListPage } from './users_list_page'; diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.test.tsx deleted file mode 100644 index bdc0df9bae67c3..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.test.tsx +++ /dev/null @@ -1,70 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { UserAPIClient } from '../../../../lib/api'; -import { User } from '../../../../../common/model'; -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { UsersListPage } from './users_list_page'; -import React from 'react'; -import { ReactWrapper } from 'enzyme'; - -jest.mock('ui/kfetch'); - -describe('UsersListPage', () => { - it('renders the list of users', async () => { - const apiClient = new UserAPIClient(); - apiClient.getUsers = jest.fn().mockImplementation(() => { - return Promise.resolve([ - { - username: 'foo', - email: 'foo@bar.net', - full_name: 'foo bar', - roles: ['kibana_user'], - enabled: true, - }, - { - username: 'reserved', - email: 'reserved@bar.net', - full_name: '', - roles: ['superuser'], - enabled: true, - metadata: { - _reserved: true, - }, - }, - ]); - }); - - const wrapper = mountWithIntl(); - - await waitForRender(wrapper); - - expect(apiClient.getUsers).toBeCalledTimes(1); - expect(wrapper.find('EuiInMemoryTable')).toHaveLength(1); - expect(wrapper.find('EuiTableRow')).toHaveLength(2); - }); - - it('renders a forbidden message if user is not authorized', async () => { - const apiClient = new UserAPIClient(); - apiClient.getUsers = jest.fn().mockImplementation(() => { - return Promise.reject({ body: { statusCode: 403 } }); - }); - - const wrapper = mountWithIntl(); - - await waitForRender(wrapper); - - expect(apiClient.getUsers).toBeCalledTimes(1); - expect(wrapper.find('[data-test-subj="permissionDeniedMessage"]')).toHaveLength(1); - expect(wrapper.find('EuiInMemoryTable')).toHaveLength(0); - }); -}); - -async function waitForRender(wrapper: ReactWrapper) { - await Promise.resolve(); - await Promise.resolve(); - wrapper.update(); -} diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.tsx b/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.tsx deleted file mode 100644 index df8522e5f32f91..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.tsx +++ /dev/null @@ -1,319 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component, Fragment } from 'react'; -import { - EuiButton, - EuiIcon, - EuiLink, - EuiFlexGroup, - EuiInMemoryTable, - EuiPageContent, - EuiTitle, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiPageContentBody, - EuiEmptyPrompt, - EuiBasicTableColumn, -} from '@elastic/eui'; -import { toastNotifications } from 'ui/notify'; -import { injectI18n, FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; -import { ConfirmDeleteUsers } from '../../../../components/management/users'; -import { User } from '../../../../../common/model'; -import { UserAPIClient } from '../../../../lib/api'; - -interface Props { - intl: InjectedIntl; - apiClient: UserAPIClient; -} - -interface State { - users: User[]; - selection: User[]; - showDeleteConfirmation: boolean; - permissionDenied: boolean; - filter: string; -} - -class UsersListPageUI extends Component { - constructor(props: Props) { - super(props); - this.state = { - users: [], - selection: [], - showDeleteConfirmation: false, - permissionDenied: false, - filter: '', - }; - } - - public componentDidMount() { - this.loadUsers(); - } - - public render() { - const { users, filter, permissionDenied, showDeleteConfirmation, selection } = this.state; - const { intl } = this.props; - if (permissionDenied) { - return ( - - - - - - } - body={ -

    - -

    - } - /> -
    -
    - ); - } - const path = '#/management/security/'; - const columns: Array> = [ - { - field: 'full_name', - name: intl.formatMessage({ - id: 'xpack.security.management.users.fullNameColumnName', - defaultMessage: 'Full Name', - }), - sortable: true, - truncateText: true, - render: (fullName: string) => { - return
    {fullName}
    ; - }, - }, - { - field: 'username', - name: intl.formatMessage({ - id: 'xpack.security.management.users.userNameColumnName', - defaultMessage: 'User Name', - }), - sortable: true, - truncateText: true, - render: (username: string) => ( - - {username} - - ), - }, - { - field: 'email', - name: intl.formatMessage({ - id: 'xpack.security.management.users.emailAddressColumnName', - defaultMessage: 'Email Address', - }), - sortable: true, - truncateText: true, - render: (email: string) => { - return
    {email}
    ; - }, - }, - { - field: 'roles', - name: intl.formatMessage({ - id: 'xpack.security.management.users.rolesColumnName', - defaultMessage: 'Roles', - }), - render: (rolenames: string[]) => { - const roleLinks = rolenames.map((rolename, index) => { - return ( - - {rolename} - {index === rolenames.length - 1 ? null : ', '} - - ); - }); - return
    {roleLinks}
    ; - }, - }, - { - field: 'metadata', - name: intl.formatMessage({ - id: 'xpack.security.management.users.reservedColumnName', - defaultMessage: 'Reserved', - }), - sortable: ({ metadata }: User) => Boolean(metadata && metadata._reserved), - width: '100px', - align: 'right', - description: intl.formatMessage({ - id: 'xpack.security.management.users.reservedColumnDescription', - defaultMessage: - 'Reserved users are built-in and cannot be removed. Only the password can be changed.', - }), - render: (metadata: User['metadata']) => - metadata && metadata._reserved ? ( - - ) : null, - }, - ]; - const pagination = { - initialPageSize: 20, - pageSizeOptions: [10, 20, 50, 100], - }; - - const selectionConfig = { - itemId: 'username', - selectable: (user: User) => !(user.metadata && user.metadata._reserved), - selectableMessage: (selectable: boolean) => (!selectable ? 'User is a system user' : ''), - onSelectionChange: (updatedSelection: User[]) => - this.setState({ selection: updatedSelection }), - }; - const search = { - toolsLeft: this.renderToolsLeft(), - box: { - incremental: true, - }, - onChange: (query: any) => { - this.setState({ - filter: query.queryText, - }); - }, - }; - const sorting = { - sort: { - field: 'full_name', - direction: 'asc', - }, - } as const; - const rowProps = () => { - return { - 'data-test-subj': 'userRow', - }; - }; - const usersToShow = filter - ? users.filter(({ username, roles, full_name: fullName = '', email = '' }) => { - const normalized = `${username} ${roles.join(' ')} ${fullName} ${email}`.toLowerCase(); - const normalizedQuery = filter.toLowerCase(); - return normalized.indexOf(normalizedQuery) !== -1; - }) - : users; - return ( -
    - - - - -

    - -

    -
    -
    - - - - - -
    - - {showDeleteConfirmation ? ( - user.username)} - callback={this.handleDelete} - apiClient={this.props.apiClient} - /> - ) : null} - - { - - } - -
    -
    - ); - } - - private handleDelete = (usernames: string[], errors: string[]) => { - const { users } = this.state; - this.setState({ - selection: [], - showDeleteConfirmation: false, - users: users.filter(({ username }) => { - return !usernames.includes(username) || errors.includes(username); - }), - }); - }; - - private async loadUsers() { - try { - const users = await this.props.apiClient.getUsers(); - this.setState({ users }); - } catch (e) { - if (e.body.statusCode === 403) { - this.setState({ permissionDenied: true }); - } else { - toastNotifications.addDanger( - this.props.intl.formatMessage( - { - id: 'xpack.security.management.users.fetchingUsersErrorMessage', - defaultMessage: 'Error fetching users: {message}', - }, - { message: e.body.message } - ) - ); - } - } - } - - private renderToolsLeft() { - const { selection } = this.state; - if (selection.length === 0) { - return; - } - const numSelected = selection.length; - return ( - this.setState({ showDeleteConfirmation: true })} - > - - - ); - } - - private onCancelDelete = () => { - this.setState({ showDeleteConfirmation: false }); - }; -} - -export const UsersListPage = injectI18n(UsersListPageUI); diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/users.html b/x-pack/legacy/plugins/security/public/views/management/users_grid/users.html deleted file mode 100644 index 3dce7326d001ae..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/users_grid/users.html +++ /dev/null @@ -1,3 +0,0 @@ - -
    - diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/users.js b/x-pack/legacy/plugins/security/public/views/management/users_grid/users.js deleted file mode 100644 index 8d4e0526251d76..00000000000000 --- a/x-pack/legacy/plugins/security/public/views/management/users_grid/users.js +++ /dev/null @@ -1,47 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import routes from 'ui/routes'; -import template from 'plugins/security/views/management/users_grid/users.html'; -import { SECURITY_PATH, USERS_PATH } from '../management_urls'; -import { UsersListPage } from './components'; -import { UserAPIClient } from '../../../lib/api'; -import { I18nContext } from 'ui/i18n'; -import { getUsersBreadcrumbs } from '../breadcrumbs'; - -routes.when(SECURITY_PATH, { - redirectTo: USERS_PATH, -}); - -const renderReact = (elem, changeUrl) => { - render( - - - , - elem - ); -}; - -routes.when(USERS_PATH, { - template, - k7Breadcrumbs: getUsersBreadcrumbs, - controller($scope, $http, kbnUrl) { - $scope.$on('$destroy', () => { - const elem = document.getElementById('usersReactRoot'); - if (elem) unmountComponentAtNode(elem); - }); - $scope.$$postDigest(() => { - const elem = document.getElementById('usersReactRoot'); - const changeUrl = url => { - kbnUrl.change(url); - $scope.$apply(); - }; - renderReact(elem, $http, changeUrl); - }); - }, -}); diff --git a/x-pack/legacy/plugins/security/public/views/overwritten_session/overwritten_session.tsx b/x-pack/legacy/plugins/security/public/views/overwritten_session/overwritten_session.tsx index fb39c517e1c2ca..4c79c499cc0e6a 100644 --- a/x-pack/legacy/plugins/security/public/views/overwritten_session/overwritten_session.tsx +++ b/x-pack/legacy/plugins/security/public/views/overwritten_session/overwritten_session.tsx @@ -11,8 +11,7 @@ import { render } from 'react-dom'; import chrome from 'ui/chrome'; import { I18nContext } from 'ui/i18n'; import { npSetup } from 'ui/new_platform'; -import { SecurityPluginSetup } from '../../../../../../plugins/security/public'; -import { AuthenticatedUser } from '../../../common/model'; +import { AuthenticatedUser, SecurityPluginSetup } from '../../../../../../plugins/security/public'; import { AuthenticationStatePage } from '../../components/authentication_state_page'; chrome diff --git a/x-pack/legacy/plugins/siem/common/constants.ts b/x-pack/legacy/plugins/siem/common/constants.ts index e67b533e46bce1..0d9e092e21d829 100644 --- a/x-pack/legacy/plugins/siem/common/constants.ts +++ b/x-pack/legacy/plugins/siem/common/constants.ts @@ -36,7 +36,7 @@ export const ENABLE_NEWS_FEED_SETTING = 'siem:enableNewsFeed'; export const NEWS_FEED_URL_SETTING = 'siem:newsFeedUrl'; /** The default value for News feed widget */ -export const NEWS_FEED_URL_SETTING_DEFAULT = 'https://feeds.elastic.co/kibana'; // TODO: replace this with the real feed URL +export const NEWS_FEED_URL_SETTING_DEFAULT = 'https://feeds.elastic.co/security-solution'; /** * Id for the signals alerting type @@ -60,7 +60,8 @@ export const DETECTION_ENGINE_PREPACKAGED_URL = `${DETECTION_ENGINE_RULES_URL}/p export const DETECTION_ENGINE_PRIVILEGES_URL = `${DETECTION_ENGINE_URL}/privileges`; export const DETECTION_ENGINE_INDEX_URL = `${DETECTION_ENGINE_URL}/index`; export const DETECTION_ENGINE_TAGS_URL = `${DETECTION_ENGINE_URL}/tags`; -export const DETECTION_ENGINE_RULES_STATUS = `${DETECTION_ENGINE_URL}/rules/_find_statuses`; +export const DETECTION_ENGINE_RULES_STATUS_URL = `${DETECTION_ENGINE_RULES_URL}/_find_statuses`; +export const DETECTION_ENGINE_PREPACKAGED_RULES_STATUS_URL = `${DETECTION_ENGINE_RULES_URL}/prepackaged/_status`; /** * Default signals index key for kibana.dev.yml diff --git a/x-pack/legacy/plugins/siem/cypress/README.md b/x-pack/legacy/plugins/siem/cypress/README.md index c9e0d4e18f78f7..a57fe0d361b8ff 100644 --- a/x-pack/legacy/plugins/siem/cypress/README.md +++ b/x-pack/legacy/plugins/siem/cypress/README.md @@ -22,29 +22,29 @@ automatically when you submit a PR. Smoke Tests are located in `siem/cypress/integration/smoke_tests` -## Test Helpers +## Structure -_Test helpers_ are functions that may be re-used across tests. +### Tasks -- Reusable code and CSS selectors should be added to -`siem/cypress/integration/lib`, as described below. +_Tasks_ are functions that my be re-used across tests. Inside the _tasks_ folder there are some other folders that represents +the page to which we will perform the actions. For each folder we are going to create a file for each one of the sections that + has the page. -### Reusable Test Helper Functions and CSS Selectors +i.e. +- tasks + - hosts + - events.ts -The `cypress/integration/lib` directory contains code intended to be re-used -across many different tests. Add reusable test helper functions and CSS -selectors to directories under `cypress/integration/lib`. +### Screens -- Files named `helpers.ts` (e.g. `siem/cypress/integration/lib/login/helpers.ts`) -contain functions (e.g. `login`) that may be imported and invoked from multiple tests. +In _screens_ folder we are going to find all the elements we want to interact in our tests. Inside _screens_ fonder there +are some other folders that represents the page that contains the elements the tests are going to interact with. For each +folder we are going to create a file for each one of the sections that the page has. -- Files named `selectors.ts` export CSS selectors for re-use. For example, -`siem/cypress/integration/lib/login/selectors.ts` exports the following selector -that matches the Username text area in the Kibana login page: - -```sh -export const USERNAME = '[data-test-subj="loginUsername"]'; -``` +i.e. +- tasks + - hosts + - events.ts ## Mock Data diff --git a/x-pack/legacy/plugins/siem/cypress/fixtures/overview.json b/x-pack/legacy/plugins/siem/cypress/fixtures/overview.json index cc1996909562d2..893661a6930434 100644 --- a/x-pack/legacy/plugins/siem/cypress/fixtures/overview.json +++ b/x-pack/legacy/plugins/siem/cypress/fixtures/overview.json @@ -29,7 +29,8 @@ "endgameRegistry": 396, "endgameSecurity": 397, "filebeatSystemModule": 890, - "winlogbeat": 100, + "winlogbeatSecurity": 70, + "winlogbeatMWSysmonOperational": 30, "__typename": "OverviewHostData" }, "__typename": "Source" diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/fields_browser/helpers.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/fields_browser/helpers.ts index 405c8eb34d6fc7..b02eda513cba39 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/fields_browser/helpers.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/fields_browser/helpers.ts @@ -4,18 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - FIELDS_BROWSER_CONTAINER, - FIELDS_BROWSER_FILTER_INPUT, - TIMELINE_FIELDS_BUTTON, -} from './selectors'; +import { FIELDS_BROWSER_CONTAINER, FIELDS_BROWSER_FILTER_INPUT } from './selectors'; import { assertAtLeastOneEventMatchesSearch, executeKQL, hostExistsQuery, toggleTimelineVisibility, } from '../timeline/helpers'; -import { TIMELINE_DATA_PROVIDERS } from '../timeline/selectors'; +import { TIMELINE_DATA_PROVIDERS, TIMELINE_FIELDS_BUTTON } from '../timeline/selectors'; /** Opens the timeline's Field Browser */ export const openTimelineFieldsBrowser = () => { diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/overview/selectors.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/overview/selectors.ts index a8af321ff9832d..95facc89744009 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/overview/selectors.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/overview/selectors.ts @@ -61,9 +61,13 @@ export const STAT_USER = { value: '789', domId: '[data-test-subj="host-stat-auditbeatUser"]', }; -export const STAT_WINLOGBEAT = { - value: '100', - domId: '[data-test-subj="host-stat-winlogbeat"]', +export const STAT_WINLOGBEAT_SECURITY = { + value: '70', + domId: '[data-test-subj="host-stat-winlogbeatSecurity"]', +}; +export const STAT_WINLOGBEAT_MWSYSMON_OPERATIONAL = { + value: '30', + domId: '[data-test-subj="host-stat-winlogbeatMWSysmonOperational"]', }; export const HOST_STATS = [ @@ -81,7 +85,8 @@ export const HOST_STATS = [ STAT_PACKAGE, STAT_PROCESS, STAT_USER, - STAT_WINLOGBEAT, + STAT_WINLOGBEAT_SECURITY, + STAT_WINLOGBEAT_MWSYSMON_OPERATIONAL, ]; // Network Stats diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts index 0ec0c506cbb1ad..5515c1f7d58e25 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts @@ -7,6 +7,9 @@ /** A data provider rendered in the timeline's data providers drop area */ export const DATA_PROVIDER = '[data-test-subj="providerContainer"]'; +export const TIMELINE_FIELDS_BUTTON = + '[data-test-subj="timeline"] [data-test-subj="show-field-browser"]'; + /** Data providers are dropped and rendered in this area of the timeline */ export const TIMELINE_DATA_PROVIDERS = '[data-test-subj="dataProviders"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts index 1450ee8dc8abf6..bf141a9f0a0bfe 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts @@ -9,25 +9,31 @@ import { FIELDS_BROWSER_CONTAINER, FIELDS_BROWSER_SELECTED_CATEGORY_TITLE, FIELDS_BROWSER_TITLE, -} from '../../lib/fields_browser/selectors'; + FIELDS_BROWSER_CHECKBOX, +} from '../../../screens/hosts/fields_browser'; import { HOSTS_PAGE } from '../../lib/urls'; -import { loginAndWaitForPage, DEFAULT_TIMEOUT } from '../../lib/util/helpers'; +import { loginAndWaitForPage } from '../../../tasks/login'; +import { openEventsViewerFieldsBrowser, filterSearchBar } from '../../lib/events_viewer/helpers'; +import { closeFieldsBrowser } from '../../../tasks/hosts/fields_browsers'; +import { openEvents } from '../../../tasks/hosts/main'; import { - clickOutsideFieldsBrowser, - openEventsViewerFieldsBrowser, - filterSearchBar, -} from '../../lib/events_viewer/helpers'; + closeModal, + opensInspectQueryModal, + waitsForEventsToBeLoaded, + addsHostGeoCityNameToHeader, + addsHostGeoCountryNameToHeader, + resetFields, +} from '../../../tasks/hosts/events'; + import { - CLOSE_MODAL, - EVENTS_VIEWER_PANEL, HEADER_SUBTITLE, INSPECT_MODAL, - INSPECT_QUERY, LOAD_MORE, LOCAL_EVENTS_COUNT, -} from '../../lib/events_viewer/selectors'; -import { SERVER_SIDE_EVENT_COUNT } from '../../lib/timeline/selectors'; -import { clickEventsTab } from '../../lib/hosts/helpers'; + HOST_GEO_CITY_NAME_HEADER, + HOST_GEO_COUNTRY_NAME_HEADER, +} from '../../../screens/hosts/events'; +import { DEFAULT_TIMEOUT } from '../../lib/util/helpers'; const defaultHeadersInDefaultEcsCategory = [ { id: '@timestamp' }, @@ -43,7 +49,7 @@ describe('Events Viewer', () => { context('Fields rendering', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); - clickEventsTab(); + openEvents(); }); beforeEach(() => { @@ -51,7 +57,7 @@ describe('Events Viewer', () => { }); afterEach(() => { - clickOutsideFieldsBrowser(); + closeFieldsBrowser(); cy.get(FIELDS_BROWSER_CONTAINER).should('not.exist'); }); @@ -69,7 +75,7 @@ describe('Events Viewer', () => { it('displays a checked checkbox for all of the default events viewer columns that are also in the default ECS category', () => { defaultHeadersInDefaultEcsCategory.forEach(header => - cy.get(`[data-test-subj="field-${header.id}-checkbox"]`).should('be.checked') + cy.get(FIELDS_BROWSER_CHECKBOX(header.id)).should('be.checked') ); }); }); @@ -77,26 +83,17 @@ describe('Events Viewer', () => { context('Events viewer query modal', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); - clickEventsTab(); + openEvents(); }); after(() => { - cy.get(CLOSE_MODAL).click(); + closeModal(); cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('not.exist'); }); it('launches the inspect query modal when the inspect button is clicked', () => { - // wait for data to load - cy.get(SERVER_SIDE_EVENT_COUNT, { timeout: DEFAULT_TIMEOUT }) - .should('exist') - .invoke('text', { timeout: DEFAULT_TIMEOUT }) - .should('not.equal', '0'); - - cy.get(INSPECT_QUERY, { timeout: DEFAULT_TIMEOUT }) - .should('exist') - .trigger('mousemove', { force: true }) - .click({ force: true }); - + waitsForEventsToBeLoaded(); + opensInspectQueryModal(); cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('exist'); }); }); @@ -104,7 +101,7 @@ describe('Events Viewer', () => { context('Events viewer fields behaviour', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); - clickEventsTab(); + openEvents(); }); beforeEach(() => { @@ -113,89 +110,55 @@ describe('Events Viewer', () => { it('adds a field to the events viewer when the user clicks the checkbox', () => { const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.city_name'; filterFieldsBrowser(filterInput); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="field-${toggleField}-checkbox"]`).check({ - force: true, - }); - - clickOutsideFieldsBrowser(); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( - 'exist' - ); + cy.get(HOST_GEO_CITY_NAME_HEADER).should('not.exist'); + addsHostGeoCityNameToHeader(); + closeFieldsBrowser(); + cy.get(HOST_GEO_CITY_NAME_HEADER).should('exist'); }); it('resets all fields in the events viewer when `Reset Fields` is clicked', () => { const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.country_name'; filterFieldsBrowser(filterInput); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="field-${toggleField}-checkbox"]`).check({ - force: true, - }); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="reset-fields"]`).click({ force: true }); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); + cy.get(HOST_GEO_COUNTRY_NAME_HEADER).should('not.exist'); + addsHostGeoCountryNameToHeader(); + resetFields(); + cy.get(HOST_GEO_COUNTRY_NAME_HEADER).should('not.exist'); }); }); context('Events behaviour', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); - clickEventsTab(); + openEvents(); }); it('filters the events by applying filter criteria from the search bar at the top of the page', () => { const filterInput = '4bf34c1c-eaa9-46de-8921-67a4ccc49829'; // this will never match real data - + waitsForEventsToBeLoaded(); cy.get(HEADER_SUBTITLE) .invoke('text') - .then(text1 => { - cy.get(HEADER_SUBTITLE) - .invoke('text', { timeout: DEFAULT_TIMEOUT }) - .should('not.equal', 'Showing: 0 events'); - + .then(initialNumberOfEvents => { filterSearchBar(filterInput); - cy.get(HEADER_SUBTITLE) .invoke('text') - .should(text2 => { - expect(text1).not.to.eq(text2); - }); + .should('not.equal', initialNumberOfEvents); }); }); it('loads more events when the load more button is clicked', () => { - cy.get(LOCAL_EVENTS_COUNT, { timeout: DEFAULT_TIMEOUT }) + const defaultNumberOfLoadedEvents = '25'; + cy.get(LOCAL_EVENTS_COUNT) .invoke('text') - .then(text1 => { - cy.get(LOCAL_EVENTS_COUNT) - .invoke('text') - .should('equal', '25'); + .should('equal', defaultNumberOfLoadedEvents); - cy.get(LOAD_MORE).click({ force: true }); + cy.get(LOAD_MORE).click({ force: true }); - cy.get(LOCAL_EVENTS_COUNT) - .invoke('text') - .should(text2 => { - expect(text1).not.to.eq(text2); - }); - }); + cy.get(LOCAL_EVENTS_COUNT) + .invoke('text') + .should('not.equal', defaultNumberOfLoadedEvents); }); }); }); diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts index d1289732b6d7db..2889d78891a062 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts @@ -4,27 +4,40 @@ * you may not use this file except in compliance with the Elastic License. */ -import { drag, drop } from '../../lib/drag_n_drop/helpers'; -import { - clearFieldsBrowser, - clickOutsideFieldsBrowser, - openTimelineFieldsBrowser, - populateTimeline, - filterFieldsBrowser, -} from '../../lib/fields_browser/helpers'; +import { HOSTS_PAGE } from '../../lib/urls'; + +import { loginAndWaitForPage, DEFAULT_TIMEOUT } from '../../../tasks/login'; + import { + FIELDS_BROWSER_TITLE, + FIELDS_BROWSER_SELECTED_CATEGORY_TITLE, + FIELDS_BROWSER_SELECTED_CATEGORY_COUNT, FIELDS_BROWSER_CATEGORIES_COUNT, - FIELDS_BROWSER_CONTAINER, - FIELDS_BROWSER_FIELDS_COUNT, - FIELDS_BROWSER_FILTER_INPUT, FIELDS_BROWSER_HOST_CATEGORIES_COUNT, - FIELDS_BROWSER_SELECTED_CATEGORY_COUNT, - FIELDS_BROWSER_SELECTED_CATEGORY_TITLE, FIELDS_BROWSER_SYSTEM_CATEGORIES_COUNT, - FIELDS_BROWSER_TITLE, -} from '../../lib/fields_browser/selectors'; -import { HOSTS_PAGE } from '../../lib/urls'; -import { loginAndWaitForPage, DEFAULT_TIMEOUT } from '../../lib/util/helpers'; + FIELDS_BROWSER_FIELDS_COUNT, + FIELDS_BROWSER_MESSAGE_HEADER, + FIELDS_BROWSER_HOST_GEO_CITY_NAME_HEADER, + FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_HEADER, + FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER, +} from '../../../screens/timeline/fields_browser'; + +import { + openTimeline, + populateTimeline, + openTimelineFieldsBrowser, +} from '../../../tasks/timeline/main'; + +import { + clearFieldsBrowser, + filterFieldsBrowser, + closeFieldsBrowser, + removesMessageField, + addsHostGeoCityNameToTimeline, + addsHostGeoCountryNameToTimelineDraggingIt, + addsHostGeoContinentNameToTimeline, + resetFields, +} from '../../../tasks/timeline/fields_browser'; const defaultHeaders = [ { id: '@timestamp' }, @@ -41,6 +54,7 @@ describe('Fields Browser', () => { context('Fields Browser rendering', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); + openTimeline(); populateTimeline(); openTimelineFieldsBrowser(); }); @@ -78,7 +92,7 @@ describe('Fields Browser', () => { filterFieldsBrowser(filterInput); - cy.get(FIELDS_BROWSER_CATEGORIES_COUNT) + cy.get(FIELDS_BROWSER_CATEGORIES_COUNT, { timeout: DEFAULT_TIMEOUT }) .invoke('text') .should('eq', '2 categories'); }); @@ -88,18 +102,13 @@ describe('Fields Browser', () => { filterFieldsBrowser(filterInput); - cy.get(FIELDS_BROWSER_FILTER_INPUT, { timeout: DEFAULT_TIMEOUT }).should( - 'not.have.class', - 'euiFieldSearch-isLoading' - ); - cy.get(FIELDS_BROWSER_HOST_CATEGORIES_COUNT) .invoke('text') .then(hostCategoriesCount => { cy.get(FIELDS_BROWSER_SYSTEM_CATEGORIES_COUNT) .invoke('text') .then(systemCategoriesCount => { - cy.get(FIELDS_BROWSER_FIELDS_COUNT) + cy.get(FIELDS_BROWSER_FIELDS_COUNT, { timeout: DEFAULT_TIMEOUT }) .invoke('text') .should('eq', `${+hostCategoriesCount + +systemCategoriesCount} fields`); }); @@ -120,6 +129,7 @@ describe('Fields Browser', () => { context('Editing the timeline', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); + openTimeline(); populateTimeline(); openTimelineFieldsBrowser(); }); @@ -130,31 +140,17 @@ describe('Fields Browser', () => { }); it('removes the message field from the timeline when the user un-checks the field', () => { - const toggleField = 'message'; - - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'exist' - ); + cy.get(FIELDS_BROWSER_MESSAGE_HEADER).should('exist'); - cy.get( - `[data-test-subj="timeline"] [data-test-subj="field-${toggleField}-checkbox"]` - ).uncheck({ - force: true, - }); + removesMessageField(); + closeFieldsBrowser(); - clickOutsideFieldsBrowser(); - - cy.get(FIELDS_BROWSER_CONTAINER).should('not.exist'); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); + cy.get(FIELDS_BROWSER_MESSAGE_HEADER).should('not.exist'); }); it('selects a search results label with the expected count of categories matching the filter input', () => { const category = 'host'; - - filterFieldsBrowser(`${category}.`); + filterFieldsBrowser(category); cy.get(FIELDS_BROWSER_SELECTED_CATEGORY_TITLE) .invoke('text') @@ -163,75 +159,47 @@ describe('Fields Browser', () => { it('adds a field to the timeline when the user clicks the checkbox', () => { const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.city_name'; filterFieldsBrowser(filterInput); + cy.get(FIELDS_BROWSER_HOST_GEO_CITY_NAME_HEADER).should('not.exist'); + addsHostGeoCityNameToTimeline(); + closeFieldsBrowser(); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="field-${toggleField}-checkbox"]`).check({ - force: true, - }); - - clickOutsideFieldsBrowser(); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`, { + cy.get(FIELDS_BROWSER_HOST_GEO_CITY_NAME_HEADER, { timeout: DEFAULT_TIMEOUT, }).should('exist'); }); it('adds a field to the timeline when the user drags and drops a field', () => { const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.country_name'; filterFieldsBrowser(filterInput); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get( - `[data-test-subj="timeline"] [data-test-subj="field-name-${toggleField}"]` - ).then(field => drag(field)); + cy.get(FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_HEADER).should('not.exist'); - cy.get(`[data-test-subj="timeline"] [data-test-subj="headers-group"]`).then(headersDropArea => - drop(headersDropArea) - ); + addsHostGeoCountryNameToTimelineDraggingIt(); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`, { + cy.get(FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_HEADER, { timeout: DEFAULT_TIMEOUT, }).should('exist'); }); it('resets all fields in the timeline when `Reset Fields` is clicked', () => { const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.continent_name'; filterFieldsBrowser(filterInput); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="field-${toggleField}-checkbox"]`).check({ - force: true, - }); + cy.get(FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER).should('not.exist'); - clickOutsideFieldsBrowser(); + addsHostGeoContinentNameToTimeline(); + closeFieldsBrowser(); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'exist' - ); + cy.get(FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER).should('exist'); openTimelineFieldsBrowser(); + resetFields(); - cy.get('[data-test-subj="timeline"] [data-test-subj="reset-fields"]').click({ force: true }); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); + cy.get(FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER).should('not.exist'); }); }); }); diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts index afeb8c3c13a4fd..142729189e49b3 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts @@ -99,7 +99,7 @@ describe('ml conditional links', () => { loginAndWaitForPage(mlNetworkSingleIpNullKqlQuery); cy.url().should( 'include', - '/app/siem#/network/ip/127.0.0.1?timerange=(global:(linkTo:!(timeline),timerange:(from:1566990000000,kind:absolute,to:1567000799999)),timeline:(linkTo:!(global),timerange:(from:1566990000000,kind:absolute,to:1567000799999)))' + '/app/siem#/network/ip/127.0.0.1/source?timerange=(global:(linkTo:!(timeline),timerange:(from:1566990000000,kind:absolute,to:1567000799999)),timeline:(linkTo:!(global),timerange:(from:1566990000000,kind:absolute,to:1567000799999)))' ); }); @@ -107,7 +107,7 @@ describe('ml conditional links', () => { loginAndWaitForPage(mlNetworkSingleIpKqlQuery); cy.url().should( 'include', - "/app/siem#/network/ip/127.0.0.1?query=(language:kuery,query:'(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)')&timerange=(global:(linkTo:!(timeline),timerange:(from:1566990000000,kind:absolute,to:1567000799999)),timeline:(linkTo:!(global),timerange:(from:1566990000000,kind:absolute,to:1567000799999)))" + "/app/siem#/network/ip/127.0.0.1/source?query=(language:kuery,query:'(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)')&timerange=(global:(linkTo:!(timeline),timerange:(from:1566990000000,kind:absolute,to:1567000799999)),timeline:(linkTo:!(global),timerange:(from:1566990000000,kind:absolute,to:1567000799999)))" ); }); diff --git a/x-pack/legacy/plugins/siem/cypress/screens/hosts/events.ts b/x-pack/legacy/plugins/siem/cypress/screens/hosts/events.ts new file mode 100644 index 00000000000000..034c1453fc979d --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/screens/hosts/events.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const EVENTS_VIEWER_PANEL = '[data-test-subj="events-viewer-panel"]'; + +export const CLOSE_MODAL = '[data-test-subj="modal-inspect-close"]'; + +export const HEADER_SUBTITLE = `${EVENTS_VIEWER_PANEL} [data-test-subj="header-panel-subtitle"]`; + +export const INSPECT_MODAL = '[data-test-subj="modal-inspect-euiModal"]'; + +export const INSPECT_QUERY = `${EVENTS_VIEWER_PANEL} [data-test-subj="inspect-icon-button"]`; + +export const LOAD_MORE = `${EVENTS_VIEWER_PANEL} [data-test-subj="TimelineMoreButton"]`; + +export const LOCAL_EVENTS_COUNT = `${EVENTS_VIEWER_PANEL} [data-test-subj="local-events-count"]`; + +export const SERVER_SIDE_EVENT_COUNT = '[data-test-subj="server-side-event-count"]'; + +export const HOST_GEO_CITY_NAME_HEADER = '[data-test-subj="header-text-host.geo.city_name"]'; + +export const HOST_GEO_CITY_NAME_CHECKBOX = '[data-test-subj="field-host.geo.city_name-checkbox"]'; + +export const HOST_GEO_COUNTRY_NAME_HEADER = '[data-test-subj="header-text-host.geo.country_name"]'; + +export const HOST_GEO_COUNTRY_NAME_CHECKBOX = + '[data-test-subj="field-host.geo.country_name-checkbox"]'; + +export const FIELDS_BROWSER_CONTAINER = '[data-test-subj="fields-browser-container"]'; + +export const EVENTS_VIEWER_FIELDS_BUTTON = `${EVENTS_VIEWER_PANEL} [data-test-subj="show-field-browser-gear"]`; + +export const RESET_FIELDS = `${EVENTS_VIEWER_PANEL} [data-test-subj="reset-fields"]`; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/hosts/fields_browser.ts b/x-pack/legacy/plugins/siem/cypress/screens/hosts/fields_browser.ts new file mode 100644 index 00000000000000..252fa7d44a7c79 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/screens/hosts/fields_browser.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** Clicking this button in the timeline opens the Fields browser */ + +/** The title displayed in the fields browser (i.e. Customize Columns) */ +export const FIELDS_BROWSER_TITLE = '[data-test-subj="field-browser-title"]'; + +/** Contains the body of the fields browser */ +export const FIELDS_BROWSER_CONTAINER = '[data-test-subj="fields-browser-container"]'; + +/** The title of the selected category in the right-hand side of the fields browser */ +export const FIELDS_BROWSER_SELECTED_CATEGORY_TITLE = '[data-test-subj="selected-category-title"]'; + +export const FIELDS_BROWSER_CHECKBOX = (id: string) => { + return `[data-test-subj="field-${id}-checkbox`; +}; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/hosts/main.ts b/x-pack/legacy/plugins/siem/cypress/screens/hosts/main.ts new file mode 100644 index 00000000000000..e80ecdac272cd3 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/screens/hosts/main.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; + * you may not use this file except in compliance with the Elastic License. + */ + +export const EVENTS_TAB = '[data-test-subj="navigation-events"]'; + +export const KQL_SEARCH_BAR = '[data-test-subj="queryInput"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/timeline/fields_browser.ts b/x-pack/legacy/plugins/siem/cypress/screens/timeline/fields_browser.ts new file mode 100644 index 00000000000000..aa63aaf89f98be --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/screens/timeline/fields_browser.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const FIELDS_BROWSER_TITLE = '[data-test-subj="field-browser-title"]'; + +/** Typing in this input filters the Field Browser */ +export const FIELDS_BROWSER_FILTER_INPUT = '[data-test-subj="field-search"]'; + +/** The title of the selected category in the right-hand side of the fields browser */ +export const FIELDS_BROWSER_SELECTED_CATEGORY_TITLE = '[data-test-subj="selected-category-title"]'; + +export const FIELDS_BROWSER_SELECTED_CATEGORY_COUNT = + '[data-test-subj="selected-category-count-badge"]'; + +export const FIELDS_BROWSER_CATEGORIES_COUNT = '[data-test-subj="categories-count"]'; + +export const FIELDS_BROWSER_HOST_CATEGORIES_COUNT = '[data-test-subj="host-category-count"]'; + +export const FIELDS_BROWSER_SYSTEM_CATEGORIES_COUNT = '[data-test-subj="system-category-count"]'; + +export const FIELDS_BROWSER_FIELDS_COUNT = '[data-test-subj="fields-count"]'; + +/** Contains the body of the fields browser */ +export const FIELDS_BROWSER_CONTAINER = '[data-test-subj="fields-browser-container"]'; + +export const FIELDS_BROWSER_MESSAGE_HEADER = + '[data-test-subj="timeline"] [data-test-subj="header-text-message"]'; + +export const FIELDS_BROWSER_MESSAGE_CHECKBOX = + '[data-test-subj="timeline"] [data-test-subj="field-message-checkbox"]'; + +export const FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_HEADER = + '[data-test-subj="header-text-host.geo.country_name"]'; + +export const FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_CHECKBOX = + '[data-test-subj="field-host.geo.country_name-checkbox"]'; + +export const FIELDS_BROWSER_DRAGGABLE_HOST_GEO_COUNTRY_NAME_HEADER = + '[data-test-subj="timeline"] [data-test-subj="field-name-host.geo.country_name"]'; + +export const FIELDS_BROWSER_HOST_GEO_CITY_NAME_HEADER = + '[data-test-subj="header-text-host.geo.city_name"]'; + +export const FIELDS_BROWSER_HOST_GEO_CITY_NAME_CHECKBOX = + '[data-test-subj="field-host.geo.city_name-checkbox"]'; + +export const FIELDS_BROWSER_HEADER_DROP_AREA = + '[data-test-subj="timeline"] [data-test-subj="headers-group"]'; + +export const FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER = + '[data-test-subj="header-text-host.geo.continent_name"]'; + +export const FIELDS_BROWSER_HOST_GEO_CONTINENT_NAME_CHECKBOX = + '[data-test-subj="field-host.geo.continent_name-checkbox"]'; + +export const FIELDS_BROWSER_RESET_FIELDS = + '[data-test-subj="timeline"] [data-test-subj="reset-fields"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts b/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts new file mode 100644 index 00000000000000..cf3267d2b650ee --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** The `Timeline ^` button that toggles visibility of the Timeline */ +export const TIMELINE_TOGGLE_BUTTON = '[data-test-subj="flyoutOverlay"]'; + +/** Contains the KQL bar for searching or filtering in the timeline */ +export const SEARCH_OR_FILTER_CONTAINER = + '[data-test-subj="timeline-search-or-filter-search-container"]'; + +export const TIMELINE_FIELDS_BUTTON = + '[data-test-subj="timeline"] [data-test-subj="show-field-browser"]'; + +/** The total server-side count of the events matching the timeline's search criteria */ +export const SERVER_SIDE_EVENT_COUNT = '[data-test-subj="server-side-event-count"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/hosts/events.ts b/x-pack/legacy/plugins/siem/cypress/tasks/hosts/events.ts new file mode 100644 index 00000000000000..d84d62f82d2e62 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/hosts/events.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DEFAULT_TIMEOUT } from '../../integration/lib/util/helpers'; +import { + EVENTS_VIEWER_FIELDS_BUTTON, + CLOSE_MODAL, + INSPECT_QUERY, + SERVER_SIDE_EVENT_COUNT, + HOST_GEO_CITY_NAME_CHECKBOX, + HOST_GEO_COUNTRY_NAME_CHECKBOX, + FIELDS_BROWSER_CONTAINER, + RESET_FIELDS, + LOAD_MORE, +} from '../../screens/hosts/events'; + +export const closeModal = () => { + cy.get(CLOSE_MODAL, { timeout: DEFAULT_TIMEOUT }).click(); +}; + +export const opensInspectQueryModal = () => { + cy.get(INSPECT_QUERY, { timeout: DEFAULT_TIMEOUT }) + .should('exist') + .trigger('mousemove', { force: true }) + .click({ force: true }); +}; + +export const waitsForEventsToBeLoaded = () => { + cy.get(SERVER_SIDE_EVENT_COUNT, { timeout: DEFAULT_TIMEOUT }) + .should('exist') + .invoke('text', { timeout: DEFAULT_TIMEOUT }) + .should('not.equal', '0'); +}; + +export const addsHostGeoCityNameToHeader = () => { + cy.get(HOST_GEO_CITY_NAME_CHECKBOX).check({ + force: true, + }); +}; + +export const addsHostGeoCountryNameToHeader = () => { + cy.get(HOST_GEO_COUNTRY_NAME_CHECKBOX).check({ + force: true, + }); +}; + +export const resetFields = () => { + cy.get(RESET_FIELDS).click({ force: true }); +}; + +export const openEventsViewerFieldsBrowser = () => { + cy.get(EVENTS_VIEWER_FIELDS_BUTTON, { timeout: DEFAULT_TIMEOUT }).click({ force: true }); + + cy.get(SERVER_SIDE_EVENT_COUNT, { timeout: DEFAULT_TIMEOUT }) + .invoke('text') + .should('not.equal', '0'); + + cy.get(FIELDS_BROWSER_CONTAINER).should('exist'); +}; + +export const loadMoreEvents = () => { + cy.get(LOAD_MORE).click({ force: true }); +}; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/hosts/fields_browsers.ts b/x-pack/legacy/plugins/siem/cypress/tasks/hosts/fields_browsers.ts new file mode 100644 index 00000000000000..ae3ed2010a0aed --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/hosts/fields_browsers.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DEFAULT_TIMEOUT } from '../../integration/lib/util/helpers'; +import { KQL_SEARCH_BAR } from '../../screens/hosts/main'; + +export const closeFieldsBrowser = () => { + cy.get(KQL_SEARCH_BAR, { timeout: DEFAULT_TIMEOUT }).click(); +}; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/hosts/main.ts b/x-pack/legacy/plugins/siem/cypress/tasks/hosts/main.ts new file mode 100644 index 00000000000000..d95ae837a3de61 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/hosts/main.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DEFAULT_TIMEOUT } from '../../integration/lib/util/helpers'; + +import { EVENTS_TAB } from '../../screens/hosts/main'; + +/** Clicks the Events tab on the hosts page */ +export const openEvents = () => + cy.get(EVENTS_TAB, { timeout: DEFAULT_TIMEOUT }).click({ force: true }); diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/login.ts b/x-pack/legacy/plugins/siem/cypress/tasks/login.ts new file mode 100644 index 00000000000000..d5bf1178d5bdd2 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/login.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { login } from '../integration/lib/login/helpers'; + +/** The default time in ms to wait for a Cypress command to complete */ +export const DEFAULT_TIMEOUT = 30 * 1000; + +/** + * Authenticates with Kibana, visits the specified `url`, and waits for the + * Kibana logo to be displayed before continuing + */ +export const loginAndWaitForPage = (url: string) => { + login(); + + cy.visit(`${Cypress.config().baseUrl}${url}`); + + cy.viewport('macbook-15'); + + cy.contains('a', 'SIEM', { timeout: DEFAULT_TIMEOUT }); +}; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/timeline/fields_browser.ts b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/fields_browser.ts new file mode 100644 index 00000000000000..c78eb8f73f6505 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/fields_browser.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { drag, drop } from '../../integration/lib/drag_n_drop/helpers'; + +import { + FIELDS_BROWSER_FILTER_INPUT, + FIELDS_BROWSER_MESSAGE_CHECKBOX, + FIELDS_BROWSER_HOST_GEO_CITY_NAME_CHECKBOX, + FIELDS_BROWSER_DRAGGABLE_HOST_GEO_COUNTRY_NAME_HEADER, + FIELDS_BROWSER_HEADER_DROP_AREA, + FIELDS_BROWSER_HOST_GEO_CONTINENT_NAME_CHECKBOX, + FIELDS_BROWSER_RESET_FIELDS, +} from '../../screens/timeline/fields_browser'; +import { DEFAULT_TIMEOUT } from '../../integration/lib/util/helpers'; +import { KQL_SEARCH_BAR } from '../../screens/hosts/main'; + +export const clearFieldsBrowser = () => { + cy.get(FIELDS_BROWSER_FILTER_INPUT).type('{selectall}{backspace}'); +}; + +export const filterFieldsBrowser = (fieldName: string) => { + cy.get(FIELDS_BROWSER_FILTER_INPUT) + .type(fieldName) + .should('not.have.class', 'euiFieldSearch-isLoading'); +}; + +export const closeFieldsBrowser = () => { + cy.get(KQL_SEARCH_BAR, { timeout: DEFAULT_TIMEOUT }).click({ force: true }); +}; + +export const removesMessageField = () => { + cy.get(FIELDS_BROWSER_MESSAGE_CHECKBOX).uncheck({ + force: true, + }); +}; + +export const addsHostGeoCityNameToTimeline = () => { + cy.get(FIELDS_BROWSER_HOST_GEO_CITY_NAME_CHECKBOX).check({ + force: true, + }); +}; + +export const addsHostGeoCountryNameToTimelineDraggingIt = () => { + cy.get(FIELDS_BROWSER_DRAGGABLE_HOST_GEO_COUNTRY_NAME_HEADER).should('exist'); + cy.get(FIELDS_BROWSER_DRAGGABLE_HOST_GEO_COUNTRY_NAME_HEADER).then(field => drag(field)); + + cy.get(FIELDS_BROWSER_HEADER_DROP_AREA).then(headersDropArea => drop(headersDropArea)); +}; + +export const addsHostGeoContinentNameToTimeline = () => { + cy.get(FIELDS_BROWSER_HOST_GEO_CONTINENT_NAME_CHECKBOX).check({ + force: true, + }); +}; + +export const resetFields = () => { + cy.get(FIELDS_BROWSER_RESET_FIELDS).click({ force: true }); +}; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts new file mode 100644 index 00000000000000..51026fef757d8a --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DEFAULT_TIMEOUT } from '../../integration/lib/util/helpers'; + +import { + TIMELINE_TOGGLE_BUTTON, + SEARCH_OR_FILTER_CONTAINER, + TIMELINE_FIELDS_BUTTON, + SERVER_SIDE_EVENT_COUNT, +} from '../../screens/timeline/main'; + +export const hostExistsQuery = 'host.name: *'; + +export const openTimeline = () => { + cy.get(TIMELINE_TOGGLE_BUTTON, { timeout: DEFAULT_TIMEOUT }).click(); +}; + +export const populateTimeline = () => { + cy.get(`${SEARCH_OR_FILTER_CONTAINER} input`).type(`${hostExistsQuery} {enter}`); + cy.get(SERVER_SIDE_EVENT_COUNT, { timeout: DEFAULT_TIMEOUT }) + .invoke('text') + .should('be.above', 0); +}; + +export const openTimelineFieldsBrowser = () => { + cy.get(TIMELINE_FIELDS_BUTTON).click({ force: true }); +}; diff --git a/x-pack/legacy/plugins/siem/index.ts b/x-pack/legacy/plugins/siem/index.ts index edbb62feb580f8..cd9b7f59226b0b 100644 --- a/x-pack/legacy/plugins/siem/index.ts +++ b/x-pack/legacy/plugins/siem/index.ts @@ -32,6 +32,7 @@ import { } from './common/constants'; import { defaultIndexPattern } from './default_index_pattern'; import { initServerWithKibana } from './server/kibana.index'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export const siem = (kibana: any) => { @@ -62,6 +63,7 @@ export const siem = (kibana: any) => { order: 9000, title: APP_NAME, url: `/app/${APP_ID}`, + category: DEFAULT_APP_CATEGORIES.security, }, ], uiSettingDefaults: { @@ -151,11 +153,11 @@ export const siem = (kibana: any) => { const { config, newPlatform, plugins, route } = server; const { coreContext, env, setup } = newPlatform; const initializerContext = { ...coreContext, env } as PluginInitializerContext; - const serverFacade = { config, plugins: { alerting: plugins.alerting, + actions: newPlatform.start.plugins.actions, elasticsearch: plugins.elasticsearch, spaces: plugins.spaces, savedObjects: server.savedObjects.SavedObjectsClient, diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx index 19011019573076..65ade52ef7d3cf 100644 --- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx +++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx @@ -64,6 +64,7 @@ const AlertsTableComponent: React.FC = ({ endDate, startDate, pageFilters documentType: i18n.ALERTS_DOCUMENT_TYPE, footerText: i18n.TOTAL_COUNT_OF_ALERTS, title: i18n.ALERTS_TABLE_TITLE, + unit: i18n.UNIT, }), [] ); diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx index 0b99a8b059df79..2d10928da570ac 100644 --- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx @@ -6,6 +6,7 @@ import { noop } from 'lodash/fp'; import React, { useEffect, useCallback } from 'react'; import { EuiSpacer } from '@elastic/eui'; +import numeral from '@elastic/numeral'; import { AlertsComponentsQueryProps } from './types'; import { AlertsTable } from './alerts_table'; @@ -13,6 +14,8 @@ import * as i18n from './translations'; import { MatrixHistogramOption } from '../matrix_histogram/types'; import { MatrixHistogramContainer } from '../../containers/matrix_histogram'; import { MatrixHistogramGqlQuery } from '../../containers/matrix_histogram/index.gql_query'; +import { useUiSetting$ } from '../../lib/kibana'; +import { DEFAULT_NUMBER_FORMAT } from '../../../common/constants'; const ID = 'alertsOverTimeQuery'; export const alertsStackByOptions: MatrixHistogramOption[] = [ { @@ -37,6 +40,8 @@ export const AlertsView = ({ type, updateDateRange = noop, }: AlertsComponentsQueryProps) => { + const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); + useEffect(() => { return () => { if (deleteQuery) { @@ -46,7 +51,10 @@ export const AlertsView = ({ }, []); const getSubtitle = useCallback( - (totalCount: number) => `${i18n.SHOWING}: ${totalCount} ${i18n.UNIT(totalCount)}`, + (totalCount: number) => + `${i18n.SHOWING}: ${numeral(totalCount).format(defaultNumberFormat)} ${i18n.UNIT( + totalCount + )}`, [] ); diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts index 408c406a854be4..b0bc38bd3ebdcd 100644 --- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts +++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts @@ -7,19 +7,19 @@ import { i18n } from '@kbn/i18n'; export const ALERTS_DOCUMENT_TYPE = i18n.translate('xpack.siem.alertsView.alertsDocumentType', { - defaultMessage: 'Alerts', + defaultMessage: 'External alerts', }); export const TOTAL_COUNT_OF_ALERTS = i18n.translate('xpack.siem.alertsView.totalCountOfAlerts', { - defaultMessage: 'alerts match the search criteria', + defaultMessage: 'external alerts match the search criteria', }); export const ALERTS_TABLE_TITLE = i18n.translate('xpack.siem.alertsView.alertsTableTitle', { - defaultMessage: 'Alerts', + defaultMessage: 'External alerts', }); export const ALERTS_GRAPH_TITLE = i18n.translate('xpack.siem.alertsView.alertsGraphTitle', { - defaultMessage: 'Alert detection frequency', + defaultMessage: 'External alerts count', }); export const ALERTS_STACK_BY_MODULE = i18n.translate( @@ -36,7 +36,7 @@ export const SHOWING = i18n.translate('xpack.siem.alertsView.showing', { export const UNIT = (totalCount: number) => i18n.translate('xpack.siem.alertsView.unit', { values: { totalCount }, - defaultMessage: `{totalCount, plural, =1 {alert} other {alerts}}`, + defaultMessage: `external {totalCount, plural, =1 {alert} other {alerts}}`, }); export const ERROR_FETCHING_ALERTS_DATA = i18n.translate( diff --git a/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx b/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx index 415cbeb7c24409..8c342ad2d037fe 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx @@ -7,6 +7,8 @@ import React from 'react'; import { Chart, BarSeries, Axis, Position, ScaleType, Settings } from '@elastic/charts'; import { getOr, get, isNumber } from 'lodash/fp'; +import deepmerge from 'deepmerge'; + import { useTimeZone } from '../../hooks'; import { AutoSizer } from '../auto_sizer'; import { ChartPlaceHolder } from './chart_place_holder'; @@ -52,8 +54,7 @@ export const BarChartBaseComponent = ({ const yAxisId = `stat-items-barchart-${data[0].key}-y`; const settings = { ...chartDefaultSettings, - theme, - ...get('configs.settings', chartConfigs), + ...deepmerge(get('configs.settings', chartConfigs), { theme }), }; return chartConfigs.width && chartConfigs.height ? ( diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx index 05a33eeba14349..f0f28f1dc246cb 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx @@ -5,6 +5,7 @@ */ import { EuiPanel } from '@elastic/eui'; +import deepEqual from 'fast-deep-equal'; import { getOr, isEmpty, isEqual, union } from 'lodash/fp'; import React, { useMemo } from 'react'; import styled from 'styled-components'; @@ -34,6 +35,7 @@ import { IIndexPattern, Query, } from '../../../../../../../src/plugins/data/public'; +import { inputsModel } from '../../store'; const DEFAULT_EVENTS_VIEWER_HEIGHT = 500; @@ -67,7 +69,7 @@ interface Props { sort: Sort; timelineTypeContext: TimelineTypeContextProps; toggleColumn: (column: ColumnHeader) => void; - utilityBar?: (totalCount: number) => React.ReactNode; + utilityBar?: (refetch: inputsModel.Refetch, totalCount: number) => React.ReactNode; } const EventsViewerComponent: React.FC = ({ @@ -154,26 +156,24 @@ const EventsViewerComponent: React.FC = ({ const totalCountMinusDeleted = totalCount > 0 ? totalCount - deletedEventIds.length : 0; + const subtitle = `${ + i18n.SHOWING + }: ${totalCountMinusDeleted.toLocaleString()} ${timelineTypeContext.unit?.( + totalCountMinusDeleted + ) ?? i18n.UNIT(totalCountMinusDeleted)}`; + // TODO: Reset eventDeletedIds/eventLoadingIds on refresh/loadmore (getUpdatedAt) return ( <> {headerFilterGroup} - {utilityBar?.(totalCountMinusDeleted)} + {utilityBar?.(refetch, totalCountMinusDeleted)}
    = ({ export const EventsViewer = React.memo( EventsViewerComponent, (prevProps, nextProps) => - prevProps.browserFields === nextProps.browserFields && + isEqual(prevProps.browserFields, nextProps.browserFields) && prevProps.columns === nextProps.columns && prevProps.dataProviders === nextProps.dataProviders && prevProps.deletedEventIds === nextProps.deletedEventIds && prevProps.end === nextProps.end && - isEqual(prevProps.filters, nextProps.filters) && + deepEqual(prevProps.filters, nextProps.filters) && prevProps.height === nextProps.height && prevProps.id === nextProps.id && - prevProps.indexPattern === nextProps.indexPattern && + deepEqual(prevProps.indexPattern, nextProps.indexPattern) && prevProps.isLive === nextProps.isLive && prevProps.itemsPerPage === nextProps.itemsPerPage && prevProps.itemsPerPageOptions === nextProps.itemsPerPageOptions && diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx index 99d174d74f3f8f..d56898cae7d23d 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx @@ -5,7 +5,7 @@ */ import { isEqual } from 'lodash/fp'; -import React, { useCallback, useEffect } from 'react'; +import React, { useCallback, useMemo, useEffect } from 'react'; import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; @@ -35,7 +35,7 @@ export interface OwnProps { headerFilterGroup?: React.ReactNode; pageFilters?: esFilters.Filter[]; timelineTypeContext?: TimelineTypeContextProps; - utilityBar?: (totalCount: number) => React.ReactNode; + utilityBar?: (refetch: inputsModel.Refetch, totalCount: number) => React.ReactNode; } interface StateReduxProps { @@ -84,6 +84,10 @@ interface DispatchProps { type Props = OwnProps & StateReduxProps & DispatchProps; +const defaultTimelineTypeContext = { + loadingText: i18n.LOADING_EVENTS, +}; + const StatefulEventsViewerComponent: React.FC = ({ createTimeline, columns, @@ -99,16 +103,14 @@ const StatefulEventsViewerComponent: React.FC = ({ itemsPerPage, itemsPerPageOptions, kqlMode, - pageFilters = [], + pageFilters, query, removeColumn, start, showCheckboxes, showRowRenderers, sort, - timelineTypeContext = { - loadingText: i18n.LOADING_EVENTS, - }, + timelineTypeContext = defaultTimelineTypeContext, updateItemsPerPage, upsertColumn, utilityBar, @@ -153,18 +155,20 @@ const StatefulEventsViewerComponent: React.FC = ({ [columns, id, upsertColumn, removeColumn] ); + const globalFilters = useMemo(() => [...filters, ...(pageFilters ?? [])], [filters, pageFilters]); + return ( { const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); const getEvents = timelineSelectors.getEventsByIdSelector(); - const mapStateToProps = (state: State, { id, pageFilters = [], defaultModel }: OwnProps) => { + const mapStateToProps = (state: State, { id, defaultModel }: OwnProps) => { const input: inputsModel.InputsRange = getInputsTimeline(state); const events: TimelineModel = getEvents(state, id) ?? defaultModel; const { @@ -205,7 +209,7 @@ const makeMapStateToProps = () => { columns, dataProviders, deletedEventIds, - filters: [...getGlobalFiltersQuerySelector(state), ...pageFilters], + filters: getGlobalFiltersQuerySelector(state), id, isLive: input.policy.kind === 'interval', itemsPerPage, diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/header.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/header.tsx index 45b331f133e85e..ccf6ec67521b0b 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/header.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/header.tsx @@ -12,13 +12,16 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; -import React from 'react'; +import React, { useCallback } from 'react'; import styled from 'styled-components'; import { BrowserFields } from '../../containers/source'; +import { signalsHeaders } from '../../pages/detection_engine/components/signals/default_config'; +import { alertsHeaders } from '../alerts_viewer/default_headers'; import { defaultHeaders as eventsDefaultHeaders } from '../events_viewer/default_headers'; import { defaultHeaders } from '../timeline/body/column_headers/default_headers'; import { OnUpdateColumns } from '../timeline/events'; +import { useTimelineTypeContext } from '../timeline/timeline_context'; import { getFieldBrowserSearchInputClassName, getFieldCount, SEARCH_INPUT_WIDTH } from './helpers'; @@ -96,27 +99,44 @@ const TitleRow = React.memo<{ isEventViewer?: boolean; onOutsideClick: () => void; onUpdateColumns: OnUpdateColumns; -}>(({ isEventViewer, onOutsideClick, onUpdateColumns }) => ( - - - -

    {i18n.CUSTOMIZE_COLUMNS}

    -
    -
    - - - { - onUpdateColumns(isEventViewer ? eventsDefaultHeaders : defaultHeaders); - onOutsideClick(); - }} - > - {i18n.RESET_FIELDS} - - -
    -)); +}>(({ isEventViewer, onOutsideClick, onUpdateColumns }) => { + const timelineTypeContext = useTimelineTypeContext(); + const handleResetColumns = useCallback(() => { + let resetDefaultHeaders = defaultHeaders; + if (isEventViewer) { + if (timelineTypeContext.documentType?.toLocaleLowerCase() === 'alerts') { + resetDefaultHeaders = alertsHeaders; + } else if (timelineTypeContext.documentType?.toLocaleLowerCase() === 'signals') { + resetDefaultHeaders = signalsHeaders; + } else { + resetDefaultHeaders = eventsDefaultHeaders; + } + } + onUpdateColumns(resetDefaultHeaders); + onOutsideClick(); + }, [isEventViewer, onOutsideClick, onUpdateColumns, timelineTypeContext]); + + return ( + + + +

    {i18n.CUSTOMIZE_COLUMNS}

    +
    +
    + + + + {i18n.RESET_FIELDS} + + +
    + ); +}); TitleRow.displayName = 'TitleRow'; diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx index 528f02f0a845b7..9fb59e2034b08c 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx @@ -17,7 +17,6 @@ import { FlyoutButton } from './button'; import { Pane } from './pane'; import { timelineActions } from '../../store/actions'; import { DEFAULT_TIMELINE_WIDTH } from '../timeline/body/helpers'; -import { trackUiAction as track, METRIC_TYPE, TELEMETRY_EVENT } from '../../lib/track_usage'; /** The height in pixels of the flyout header, exported for use in height calculations */ export const flyoutHeaderHeight: number = 60; @@ -101,10 +100,7 @@ export const FlyoutComponent = React.memo( dataProviders={dataProviders!} show={!show} timelineId={timelineId} - onOpen={() => { - track(METRIC_TYPE.LOADED, TELEMETRY_EVENT.TIMELINE_OPENED); - showTimeline({ id: timelineId, show: true }); - }} + onOpen={() => showTimeline({ id: timelineId, show: true })} /> ) diff --git a/x-pack/legacy/plugins/siem/public/components/header_global/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/header_global/__snapshots__/index.test.tsx.snap index aaefb4a83ded4f..25374c63fa897d 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_global/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/header_global/__snapshots__/index.test.tsx.snap @@ -9,62 +9,11 @@ exports[`HeaderGlobal it renders 1`] = ` justifyContent="spaceBetween" wrap={true} > - - - - - - - - - - - - - - - - - - - - - - Add data - - - - + + `; diff --git a/x-pack/legacy/plugins/siem/public/components/header_global/index.tsx b/x-pack/legacy/plugins/siem/public/components/header_global/index.tsx index 5a286532fabfca..a12fab8a4f5d92 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_global/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_global/index.tsx @@ -39,55 +39,59 @@ interface HeaderGlobalProps { export const HeaderGlobal = React.memo(({ hideDetectionEngine = false }) => ( - - - - - - - + + {({ indicesExist }) => ( + <> + + + + + + + - - - {({ indicesExist }) => - indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - key !== SiemPageName.detections, navTabs) - : navTabs - } - /> - ) : ( - key === SiemPageName.overview, navTabs)} - /> - ) - } - - - - + + {indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( + key !== SiemPageName.detections, navTabs) + : navTabs + } + /> + ) : ( + key === SiemPageName.overview, navTabs)} + /> + )} + + + - - - - - + + + {indicesExistOrDataTemporarilyUnavailable(indicesExist) && ( + + + + )} - - - {i18n.BUTTON_ADD_DATA} - - - - + + + {i18n.BUTTON_ADD_DATA} + + + + + + )} + )); diff --git a/x-pack/legacy/plugins/siem/public/components/header_page/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/header_page/__snapshots__/index.test.tsx.snap index a91d8fce87dac0..a4bcf20ea1bc29 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_page/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/header_page/__snapshots__/index.test.tsx.snap @@ -16,7 +16,7 @@ exports[`HeaderPage it renders 1`] = ` > Test title - ( - ({ - backOptions, - badgeOptions, - border, - children, - draggableArguments, - isLoading, - subtitle, - subtitle2, - title, - ...rest - }) => ( -
    - - - {backOptions && ( - - - {backOptions.text} - - - )} - - -

    - {!draggableArguments ? ( - title - ) : ( - - )} - {badgeOptions && ( - <> - {' '} - {badgeOptions.beta ? ( - - ) : ( - {badgeOptions.text} - )} - - )} -

    -
    - - {subtitle && } - {subtitle2 && } - {border && isLoading && } -
    - - {children && ( - - {children} - +const HeaderPageComponent: React.FC = ({ + backOptions, + badgeOptions, + border, + children, + draggableArguments, + isLoading, + subtitle, + subtitle2, + title, + ...rest +}) => ( +
    + + + {backOptions && ( + + + {backOptions.text} + + )} - -
    - ) + + +

    + {!draggableArguments ? ( + title + ) : ( + + )} + {badgeOptions && ( + <> + {' '} + {badgeOptions.beta ? ( + + ) : ( + {badgeOptions.text} + )} + + )} +

    +
    + + {subtitle && } + {subtitle2 && } + {border && isLoading && } + + + {children && ( + + {children} + + )} +
    +
    ); -HeaderPage.displayName = 'HeaderPage'; + +export const HeaderPage = React.memo(HeaderPageComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx b/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx index 32e71b3db575f5..405a8f060948e3 100644 --- a/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx @@ -24,7 +24,12 @@ export const InspectButtonContainer = styled.div<{ show?: boolean }>` display: flex; flex-grow: 1; + > * { + max-width: 100%; + } + .${BUTTON_CLASS} { + pointer-events: none; opacity: 0; transition: opacity ${props => getOr(250, 'theme.eui.euiAnimSpeedNormal', props)} ease; } @@ -33,6 +38,7 @@ export const InspectButtonContainer = styled.div<{ show?: boolean }>` show && css` &:hover .${BUTTON_CLASS} { + pointer-events: auto; opacity: 1; } `} diff --git a/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx b/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx index 3180fc955c6906..3eda945c9224e6 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx +++ b/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx @@ -77,16 +77,16 @@ export const LinkToPage = React.memo(({ match }) => ( /> ; @@ -41,22 +42,36 @@ export const RedirectToCreateRulePage = ({ }; export const RedirectToRuleDetailsPage = ({ + match: { + params: { detailName }, + }, location: { search }, }: DetectionEngineComponentProps) => { - return ; + return ; }; -export const RedirectToEditRulePage = ({ location: { search } }: DetectionEngineComponentProps) => { +export const RedirectToEditRulePage = ({ + match: { + params: { detailName }, + }, + location: { search }, +}: DetectionEngineComponentProps) => { return ( - + ); }; -export const getDetectionEngineUrl = () => `#/link-to/${DETECTION_ENGINE_PAGE_NAME}`; +const baseDetectionEngineUrl = `#/link-to/${DETECTION_ENGINE_PAGE_NAME}`; + +export const getDetectionEngineUrl = () => `${baseDetectionEngineUrl}`; export const getDetectionEngineAlertUrl = () => - `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/${DetectionEngineTab.alerts}`; -export const getRulesUrl = () => `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/rules`; -export const getCreateRuleUrl = () => `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/rules/create-rule`; -export const getRuleDetailsUrl = () => `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/rules/rule-details`; -export const getEditRuleUrl = () => - `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/rules/rule-details/edit-rule`; + `${baseDetectionEngineUrl}/${DetectionEngineTab.alerts}`; +export const getDetectionEngineTabUrl = (tabPath: string) => `${baseDetectionEngineUrl}/${tabPath}`; +export const getRulesUrl = () => `${baseDetectionEngineUrl}/rules`; +export const getCreateRuleUrl = () => `${baseDetectionEngineUrl}/rules/create`; +export const getRuleDetailsUrl = (detailName: string) => + `${baseDetectionEngineUrl}/rules/id/${detailName}`; +export const getEditRuleUrl = (detailName: string) => + `${baseDetectionEngineUrl}/rules/id/${detailName}/edit`; diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx index cdd62c430a50cc..f8853deeaed527 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx @@ -7,18 +7,14 @@ import React, { useState, useEffect, useCallback } from 'react'; import { ScaleType } from '@elastic/charts'; -import darkTheme from '@elastic/eui/dist/eui_theme_dark.json'; -import lightTheme from '@elastic/eui/dist/eui_theme_light.json'; -import { EuiFlexGroup, EuiFlexItem, EuiLoadingContent, EuiSelect } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiSelect } from '@elastic/eui'; import { noop } from 'lodash/fp'; import * as i18n from './translations'; import { BarChart } from '../charts/barchart'; import { HeaderSection } from '../header_section'; -import { DEFAULT_DARK_MODE } from '../../../common/constants'; -import { useUiSetting$ } from '../../lib/kibana'; -import { Loader } from '../loader'; +import { MatrixLoader } from './matrix_loader'; import { Panel } from '../panel'; -import { getBarchartConfigs, getCustomChartData } from '../../components/matrix_histogram/utils'; +import { getBarchartConfigs, getCustomChartData } from './utils'; import { useQuery } from '../../containers/matrix_histogram/utils'; import { MatrixHistogramProps, @@ -31,7 +27,6 @@ import { InspectButtonContainer } from '../inspect'; export const MatrixHistogramComponent: React.FC = ({ - activePage, dataKey, defaultStackByOption, endDate, @@ -59,7 +54,6 @@ export const MatrixHistogramComponent: React.FC { const barchartConfigs = getBarchartConfigs({ from: startDate, @@ -70,20 +64,7 @@ export const MatrixHistogramComponent: React.FC(DEFAULT_DARK_MODE); - - const handleOnMouseEnter = useCallback(() => { - if (!showInspect) { - setShowInspect(true); - } - }, [showInspect, setShowInspect]); - const handleOnMouseLeave = useCallback(() => { - if (showInspect) { - setShowInspect(false); - } - }, [showInspect, setShowInspect]); - + const [isInitialLoading, setIsInitialLoading] = useState(true); const [selectedStackByOption, setSelectedStackByOption] = useState( defaultStackByOption ); @@ -127,12 +108,8 @@ export const MatrixHistogramComponent: React.FC - - = 0 ? subtitleWithCounts : null)} - > - - - {stackByOptions?.length > 1 && ( - - )} - - {headerChildren} - - - {loading ? ( - + if (hideHistogram) { + return null; + } + + return ( + + + {loading && !isInitialLoading && ( + + )} + + {isInitialLoading ? ( + <> + + + ) : ( <> + = 0 ? subtitleWithCounts : null)} + > + + + {stackByOptions?.length > 1 && ( + + )} + + {headerChildren} + + - - {loading && ( - - )} )} - ) : null; + ); }; export const MatrixHistogram = React.memo(MatrixHistogramComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/matrix_loader.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/matrix_loader.tsx new file mode 100644 index 00000000000000..769ef170898b08 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/matrix_loader.tsx @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; +import styled from 'styled-components'; + +const StyledEuiFlexGroup = styled(EuiFlexGroup)` + height: 350px; /* to avoid jump when histogram loads */ +`; + +const MatrixLoaderComponent = () => ( + + + + + +); + +export const MatrixLoader = React.memo(MatrixLoaderComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts index 48ff9c94d90995..6e932f0c873474 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts @@ -3,11 +3,22 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ScaleType, niceTimeFormatter, Position } from '@elastic/charts'; +import { ScaleType, Position } from '@elastic/charts'; import { get, groupBy, map, toPairs } from 'lodash/fp'; import { UpdateDateRange, ChartSeriesData } from '../charts/common'; import { MatrixHistogramDataTypes, MatrixHistogramMappingTypes } from './types'; +import { histogramDateTimeFormatter } from '../utils'; + +interface GetBarchartConfigsProps { + from: number; + legendPosition?: Position; + to: number; + scaleType: ScaleType; + onBrushEnd: UpdateDateRange; + yTickFormatter?: (value: number) => string; + showLegend?: boolean; +} export const getBarchartConfigs = ({ from, @@ -17,22 +28,15 @@ export const getBarchartConfigs = ({ onBrushEnd, yTickFormatter, showLegend, -}: { - from: number; - legendPosition?: Position; - to: number; - scaleType: ScaleType; - onBrushEnd: UpdateDateRange; - yTickFormatter?: (value: number) => string; - showLegend?: boolean; -}) => ({ +}: GetBarchartConfigsProps) => ({ series: { xScaleType: scaleType || ScaleType.Time, yScaleType: ScaleType.Linear, stackAccessors: ['g'], }, axis: { - xTickFormatter: scaleType === ScaleType.Time ? niceTimeFormatter([from, to]) : undefined, + xTickFormatter: + scaleType === ScaleType.Time ? histogramDateTimeFormatter([from, to]) : undefined, yTickFormatter: yTickFormatter != null ? yTickFormatter diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.tsx index 0d503e2db3d9d1..39c48413737e2b 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.tsx @@ -21,7 +21,7 @@ StaticSwitch.displayName = 'StaticSwitch'; export interface JobSwitchProps { job: SiemJob; isSiemJobsLoading: boolean; - onJobStateChange: (job: SiemJob, latestTimestampMs: number, enable: boolean) => void; + onJobStateChange: (job: SiemJob, latestTimestampMs: number, enable: boolean) => Promise; } // Based on ML Job/Datafeed States from x-pack/legacy/plugins/ml/common/constants/states.js @@ -48,9 +48,10 @@ export const JobSwitchComponent = ({ }: JobSwitchProps) => { const [isLoading, setIsLoading] = useState(false); const handleChange = useCallback( - e => { + async e => { setIsLoading(true); - onJobStateChange(job, job.latestTimestampMs || 0, e.target.checked); + await onJobStateChange(job, job.latestTimestampMs || 0, e.target.checked); + setIsLoading(false); }, [job, setIsLoading, onJobStateChange] ); @@ -58,7 +59,7 @@ export const JobSwitchComponent = ({ return ( - {isSiemJobsLoading || isLoading || isJobLoading(job.jobState, job.datafeedId) ? ( + {isSiemJobsLoading || isLoading || isJobLoading(job.jobState, job.datafeedState) ? ( ) : ( void + onJobStateChange: (job: SiemJob, latestTimestampMs: number, enable: boolean) => Promise ) => [ { name: i18n.COLUMN_JOB_NAME, @@ -92,7 +92,7 @@ const getPaginatedItems = (items: SiemJob[], pageIndex: number, pageSize: number export interface JobTableProps { isLoading: boolean; jobs: SiemJob[]; - onJobStateChange: (job: SiemJob, latestTimestampMs: number, enable: boolean) => void; + onJobStateChange: (job: SiemJob, latestTimestampMs: number, enable: boolean) => Promise; } export const JobsTableComponent = ({ isLoading, jobs, onJobStateChange }: JobTableProps) => { diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx index 307be06424ee3f..a41e84c163663c 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx @@ -11,7 +11,7 @@ import React, { useContext, useReducer, useState } from 'react'; import styled from 'styled-components'; import { useKibana } from '../../lib/kibana'; -import { METRIC_TYPE, TELEMETRY_EVENT, trackUiAction as track } from '../../lib/track_usage'; +import { METRIC_TYPE, TELEMETRY_EVENT, track } from '../../lib/telemetry'; import { errorToToaster } from '../ml/api/error_to_toaster'; import { hasMlAdminPermissions } from '../ml/permissions/has_ml_admin_permissions'; import { MlCapabilitiesContext } from '../ml/permissions/ml_capabilities_provider'; diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/breadcrumbs/index.ts b/x-pack/legacy/plugins/siem/public/components/navigation/breadcrumbs/index.ts index 9eee5b21e83f3c..91055bca066c46 100644 --- a/x-pack/legacy/plugins/siem/public/components/navigation/breadcrumbs/index.ts +++ b/x-pack/legacy/plugins/siem/public/components/navigation/breadcrumbs/index.ts @@ -10,6 +10,7 @@ import { getOr, omit } from 'lodash/fp'; import { APP_NAME } from '../../../../common/constants'; import { getBreadcrumbs as getHostDetailsBreadcrumbs } from '../../../pages/hosts/details/utils'; import { getBreadcrumbs as getIPDetailsBreadcrumbs } from '../../../pages/network/ip_details'; +import { getBreadcrumbs as getDetectionRulesBreadcrumbs } from '../../../pages/detection_engine/rules/utils'; import { SiemPageName } from '../../../pages/home/types'; import { RouteSpyState, HostRouteSpyState, NetworkRouteSpyState } from '../../../utils/route/types'; import { getOverviewUrl } from '../../link_to'; @@ -38,6 +39,9 @@ const isNetworkRoutes = (spyState: RouteSpyState): spyState is NetworkRouteSpySt const isHostsRoutes = (spyState: RouteSpyState): spyState is HostRouteSpyState => spyState != null && spyState.pageName === SiemPageName.hosts; +const isDetectionsRoutes = (spyState: RouteSpyState) => + spyState != null && spyState.pageName === SiemPageName.detections; + export const getBreadcrumbsForRoute = ( object: RouteSpyState & TabNavigationProps ): Breadcrumb[] | null => { @@ -76,6 +80,24 @@ export const getBreadcrumbsForRoute = ( ), ]; } + if (isDetectionsRoutes(spyState) && object.navTabs) { + const tempNav: SearchNavTab = { urlKey: 'detections', isDetailPage: false }; + let urlStateKeys = [getOr(tempNav, spyState.pageName, object.navTabs)]; + if (spyState.tabName != null) { + urlStateKeys = [...urlStateKeys, getOr(tempNav, spyState.tabName, object.navTabs)]; + } + + return [ + ...siemRootBreadcrumb, + ...getDetectionRulesBreadcrumbs( + spyState, + urlStateKeys.reduce( + (acc: string[], item: SearchNavTab) => [...acc, getSearch(item, object)], + [] + ) + ), + ]; + } if ( spyState != null && object.navTabs && diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/navigation/index.test.tsx index b6efc07ad8fe3b..56be39f67b1bdd 100644 --- a/x-pack/legacy/plugins/siem/public/components/navigation/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/navigation/index.test.tsx @@ -187,6 +187,7 @@ describe('SIEM Navigation', () => { query: { language: 'kuery', query: '' }, savedQuery: undefined, search: '', + state: undefined, tabName: 'authentications', timeline: { id: '', isOpen: false }, timerange: { diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx b/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx index 61ac84667d80f7..040a6e7847b772 100644 --- a/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; +import isEqual from 'lodash/fp/isEqual'; +import deepEqual from 'fast-deep-equal'; import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -16,67 +17,78 @@ import { setBreadcrumbs } from './breadcrumbs'; import { TabNavigation } from './tab_navigation'; import { SiemNavigationProps, SiemNavigationComponentProps } from './types'; -export const SiemNavigationComponent = React.memo< - SiemNavigationComponentProps & SiemNavigationProps & RouteSpyState ->( - ({ detailName, display, navTabs, pageName, pathName, search, tabName, urlState, flowTarget }) => { - useEffect(() => { - if (pathName) { - setBreadcrumbs({ - query: urlState.query, - detailName, - filters: urlState.filters, - navTabs, - pageName, - pathName, - savedQuery: urlState.savedQuery, - search, - tabName, - flowTarget, - timerange: urlState.timerange, - timeline: urlState.timeline, - }); - } - }, [pathName, search, navTabs, urlState]); +export const SiemNavigationComponent: React.FC = ({ + detailName, + display, + navTabs, + pageName, + pathName, + search, + tabName, + urlState, + flowTarget, + state, +}) => { + useEffect(() => { + if (pathName) { + setBreadcrumbs({ + query: urlState.query, + detailName, + filters: urlState.filters, + navTabs, + pageName, + pathName, + savedQuery: urlState.savedQuery, + search, + tabName, + flowTarget, + timerange: urlState.timerange, + timeline: urlState.timeline, + state, + }); + } + }, [pathName, search, navTabs, urlState, state]); - return ( - - ); - }, - (prevProps, nextProps) => { - return ( + return ( + + ); +}; + +export const SiemNavigationRedux = compose< + React.ComponentClass +>(connect(makeMapStateToProps))( + React.memo( + SiemNavigationComponent, + (prevProps, nextProps) => prevProps.pathName === nextProps.pathName && prevProps.search === nextProps.search && isEqual(prevProps.navTabs, nextProps.navTabs) && - isEqual(prevProps.urlState, nextProps.urlState) - ); - } + isEqual(prevProps.urlState, nextProps.urlState) && + deepEqual(prevProps.state, nextProps.state) + ) ); -SiemNavigationComponent.displayName = 'SiemNavigationComponent'; - -export const SiemNavigationRedux = compose< - React.ComponentClass ->(connect(makeMapStateToProps))(SiemNavigationComponent); - -export const SiemNavigation = React.memo(props => { +const SiemNavigationContainer: React.FC = props => { const [routeProps] = useRouteSpy(); const stateNavReduxProps: RouteSpyState & SiemNavigationProps = { ...routeProps, ...props, }; + return ; -}); +}; -SiemNavigation.displayName = 'SiemNavigation'; +export const SiemNavigation = SiemNavigationContainer; diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/index.tsx b/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/index.tsx index b653624ec1f67f..cebf9b90656ca3 100644 --- a/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/navigation/tab_navigation/index.tsx @@ -7,7 +7,7 @@ import { EuiTab, EuiTabs } from '@elastic/eui'; import { getOr } from 'lodash/fp'; import React, { useEffect, useState, useCallback, useMemo } from 'react'; -import { trackUiAction as track, METRIC_TYPE, TELEMETRY_EVENT } from '../../../lib/track_usage'; +import { track, METRIC_TYPE, TELEMETRY_EVENT } from '../../../lib/telemetry'; import { getSearch } from '../helpers'; import { TabNavigationProps, TabNavigationItemProps } from './types'; diff --git a/x-pack/legacy/plugins/siem/public/components/news_feed/helpers.test.ts b/x-pack/legacy/plugins/siem/public/components/news_feed/helpers.test.ts new file mode 100644 index 00000000000000..0b0e0298a0c667 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/news_feed/helpers.test.ts @@ -0,0 +1,509 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { NEWS_FEED_URL_SETTING_DEFAULT } from '../../../common/constants'; +import { rawNewsApiResponse } from '../../mock/news'; +import { rawNewsJSON } from '../../mock/raw_news'; + +import { + fetchNews, + getLocale, + getNewsFeedUrl, + getNewsItemsFromApiResponse, + removeSnapshotFromVersion, + showNewsItem, +} from './helpers'; +import { NewsItem, RawNewsApiResponse } from './types'; + +type GlobalWithFetch = NodeJS.Global & { fetch: jest.Mock }; + +describe('helpers', () => { + describe('removeSnapshotFromVersion', () => { + test('it should remove an all-caps `-SNAPSHOT`', () => { + const version = '8.0.0-SNAPSHOT'; + + expect(removeSnapshotFromVersion(version)).toEqual('8.0.0'); + }); + + test('it should remove a mixed-case `-SnApShoT`', () => { + const version = '8.0.0-SnApShoT'; + + expect(removeSnapshotFromVersion(version)).toEqual('8.0.0'); + }); + + test('it should remove all occurrences of `-SNAPSHOT`, regardless of where they appear in the version', () => { + const version = '-SNAPSHOT8.0.0-SNAPSHOT'; + + expect(removeSnapshotFromVersion(version)).toEqual('8.0.0'); + }); + + test('it should NOT transform a version when it does not contain a `-SNAPSHOT`', () => { + const version = '8.0.0'; + + expect(removeSnapshotFromVersion(version)).toEqual('8.0.0'); + }); + + test('it should NOT transform a version if it omits the dash in `SNAPSHOT`', () => { + const version = '8.0.0SNAPSHOT'; + + expect(removeSnapshotFromVersion(version)).toEqual('8.0.0SNAPSHOT'); + }); + + test('it should NOT transform a version if has only a partial `-SNAPSHOT`', () => { + const version = '8.0.0-SNAP'; + + expect(removeSnapshotFromVersion(version)).toEqual('8.0.0-SNAP'); + }); + + test('it should NOT transform an undefined version', () => { + const version = undefined; + + expect(removeSnapshotFromVersion(version)).toBeUndefined(); + }); + + test('it should NOT transform an empty version', () => { + const version = ''; + + expect(removeSnapshotFromVersion(version)).toEqual(''); + }); + }); + + describe('getNewsFeedUrl', () => { + const getKibanaVersion = () => '8.0.0'; + + test('it combines the (default) base URL from settings and the Kibana version to return the expected URL', () => { + expect( + getNewsFeedUrl({ newsFeedUrlSetting: NEWS_FEED_URL_SETTING_DEFAULT, getKibanaVersion }) + ).toEqual('https://feeds.elastic.co/security-solution/v8.0.0.json'); + }); + + test('it combines a URL with extra whitespace and the Kibana version to return the expected URL', () => { + const withExtraWhitespace = ` ${NEWS_FEED_URL_SETTING_DEFAULT} `; + + expect(getNewsFeedUrl({ newsFeedUrlSetting: withExtraWhitespace, getKibanaVersion })).toEqual( + 'https://feeds.elastic.co/security-solution/v8.0.0.json' + ); + }); + + test('it combines a URL with a trailing slash and the Kibana version to return the expected URL', () => { + const withTrailingSlash = `${NEWS_FEED_URL_SETTING_DEFAULT}/`; + + expect(getNewsFeedUrl({ newsFeedUrlSetting: withTrailingSlash, getKibanaVersion })).toEqual( + 'https://feeds.elastic.co/security-solution/v8.0.0.json' + ); + }); + + test('it combines a URL with a trailing slash plus whitespace and the Kibana version to return the expected URL', () => { + const withTrailingSlashPlusWhitespace = ` ${NEWS_FEED_URL_SETTING_DEFAULT}/ `; + + expect( + getNewsFeedUrl({ newsFeedUrlSetting: withTrailingSlashPlusWhitespace, getKibanaVersion }) + ).toEqual('https://feeds.elastic.co/security-solution/v8.0.0.json'); + }); + + test('it combines a URL and a Kibana version with a `-SNAPSHOT` to return the expected URL', () => { + const getKibanaVersionWithSnapshot = () => '8.0.0-SNAPSHOT'; + + expect( + getNewsFeedUrl({ + newsFeedUrlSetting: NEWS_FEED_URL_SETTING_DEFAULT, + getKibanaVersion: getKibanaVersionWithSnapshot, + }) + ).toEqual('https://feeds.elastic.co/security-solution/v8.0.0.json'); + }); + }); + + describe('getLocale', () => { + const fallback = 'wowzers'; + + test('it returns language specified in the document', () => { + const lang = 'ja'; + + document.documentElement.lang = lang; + + expect(getLocale(fallback)).toEqual(lang); + }); + + test('it returns the fallback when the language in the document is an empty string', () => { + document.documentElement.lang = ''; + + expect(getLocale(fallback)).toEqual(fallback); + }); + }); + + describe('getNewsItemsFromApiResponse', () => { + const expectedNewsItems: NewsItem[] = [ + { + description: + "There's an awesome community of Elastic SIEM users out there. Join the discussion about configuring, learning, and using the Elastic SIEM app, and detecting threats!", + expireOn: expect.any(Date), + hash: '5a35c984a9cdc1c6a25913f3d0b99b1aefc7257bc3b936c39db9fa0435edeed0', + imageUrl: + 'https://aws1.discourse-cdn.com/elastic/original/3X/f/8/f8c3d0b9971cfcd0be349d973aa5799f71d280cc.png?blade=securitysolutionfeed', + linkUrl: 'https://discuss.elastic.co/c/siem?blade=securitysolutionfeed', + publishOn: expect.any(Date), + title: 'Got SIEM Questions?', + }, + { + description: + 'Elastic Security combines the threat hunting and analytics of Elastic SIEM with the prevention and response provided by Elastic Endpoint Security.', + expireOn: expect.any(Date), + hash: 'edcb2d396ffdd80bfd5a97fbc0dc9f4b73477f9be556863fe0a1caf086679420', + imageUrl: + 'https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1caa35177420c61b/5d0d0394d8ff351753cbf2c5/illustrated-screenshot-hero-siem.png?blade=securitysolutionfeed', + linkUrl: + 'https://www.elastic.co/blog/elastic-security-7-5-0-released?blade=securitysolutionfeed', + publishOn: expect.any(Date), + title: 'Elastic Security 7.5.0 released', + }, + { + description: + 'At Elastic, we’re bringing endpoint protection and SIEM together into the same experience to streamline how you secure your organization.', + expireOn: expect.any(Date), + hash: 'ec970adc85e9eede83f77e4cc6a6fea00cd7822cbe48a71dc2c5f1df10939196', + imageUrl: + 'https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd0eb8689eafe398a/5d970ecc1970e80e85277925/illustration-endpoint-hero.png?blade=securitysolutionfeed', + linkUrl: + 'https://www.elastic.co/webinars/elastic-endpoint-security-overview-security-starts-at-the-endpoint?blade=securitysolutionfeed', + publishOn: expect.any(Date), + title: 'Elastic Endpoint Security Overview Webinar', + }, + { + description: + 'For small businesses and homes, having access to effective security analytics can come at a high cost of either time or money. Well, until now!', + expireOn: expect.any(Date), + hash: 'aa243fd5845356a5ccd54a7a11b208ed307e0d88158873b1fcf7d1164b739bac', + imageUrl: + 'https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt024c26b7636cb24f/5daf4e293a326d6df6c0e025/home-siem-blog-1-map.jpg?blade=securitysolutionfeed', + linkUrl: + 'https://www.elastic.co/blog/elastic-siem-for-small-business-and-home-1-getting-started?blade=securitysolutionfeed', + publishOn: expect.any(Date), + title: 'Trying Elastic SIEM at Home?', + }, + { + description: + 'Elastic is excited to announce the introduction of Elastic Endpoint Security, based on Elastic’s acquisition of Endgame, a pioneer and industry-recognized leader in endpoint threat prevention, detection, and response.', + expireOn: expect.any(Date), + hash: '3c64576c9749d33ff98726d641cdf2fb2bfde3dd9a6f99ff2573ac8d8c5b2c02', + imageUrl: + 'https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt1f87637fb7870298/5d9fe27bf8ca980f8717f6f8/screenshot-resolver-trickbot-enrichments-showing-defender-shutdown-endgame-2-optimized.png?blade=securitysolutionfeed', + linkUrl: + 'https://www.elastic.co/blog/introducing-elastic-endpoint-security?blade=securitysolutionfeed', + publishOn: expect.any(Date), + title: 'Introducing Elastic Endpoint Security', + }, + { + description: + 'Elastic SIEM is powered by Elastic Common Schema. With ECS, analytics content such as dashboards, rules, and machine learning jobs can be applied more broadly, searches can be crafted more narrowly, and field names are easier to remember.', + expireOn: expect.any(Date), + hash: 'b8a0d3d21e9638bde891ab5eb32594b3d7a3daacc7f0900c6dd506d5d7b42410', + imageUrl: + 'https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt71256f06dc672546/5c98d595975fd58f4d12646d/ecs-intro-dashboard-1360.jpg?blade=securitysolutionfeed', + linkUrl: + 'https://www.elastic.co/blog/introducing-the-elastic-common-schema?blade=securitysolutionfeed', + publishOn: expect.any(Date), + title: 'What is Elastic Common Schema (ECS)?', + }, + ]; + + test('it returns an empty collection of news items when the response is undefined', () => { + expect(getNewsItemsFromApiResponse(undefined)).toEqual([]); + }); + + test('it returns an empty collection of news items when the response is null', () => { + expect(getNewsItemsFromApiResponse(null)).toEqual([]); + }); + + test('it returns an empty collection of news items when the response items are undefined', () => { + expect(getNewsItemsFromApiResponse({ items: undefined })).toEqual([]); + }); + + test('it returns an empty collection of news items when the response items are null', () => { + expect(getNewsItemsFromApiResponse({ items: null })).toEqual([]); + }); + + test('it returns the expected news items when the browser language matches the i18n values in the response', () => { + const lang = 'en'; + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(rawNewsApiResponse)).toEqual(expectedNewsItems); + }); + + test('it returns the expected news items when an ALL CAPS the browser language matches the i18n values in the response', () => { + const allCapsLang = 'EN'; + + document.documentElement.lang = allCapsLang; + + expect(getNewsItemsFromApiResponse(rawNewsApiResponse)).toEqual(expectedNewsItems); + }); + + test('it returns the expected news items when the browser language does NOT match the i18n values in the response', () => { + const nonMatchingLang = 'ja'; + + document.documentElement.lang = nonMatchingLang; + + expect(getNewsItemsFromApiResponse(rawNewsApiResponse)).toEqual(expectedNewsItems); + }); + + test('it returns the expected news items when the browser language is an empty string', () => { + const emptyLang = ''; + + document.documentElement.lang = emptyLang; + + expect(getNewsItemsFromApiResponse(rawNewsApiResponse)).toEqual(expectedNewsItems); + }); + + test('it returns the expected news item when parsing a raw JSON response', () => { + const lang = 'en'; + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(JSON.parse(rawNewsJSON))).toEqual(expectedNewsItems); + }); + + describe('translated items', () => { + const translatedDescription = + 'Elastic SIEMユーザーの素晴らしいコミュニティがそこにあります。 Elastic SIEMアプリの設定、学習、使用、および脅威の検出に関するディスカッションに参加してください!'; + const translatedImageUrl = 'https://aws1.discourse-cdn.com/elastic/translated-image-url'; + const translatedLinkUrl = 'https://discuss.elastic.co/translated-link-url'; + const translatedTitle = 'SIEMに関する質問はありますか?'; + + const withNonDefaultTranslations: RawNewsApiResponse = { + items: [ + { + title: { en: 'Got SIEM Questions?', ja: translatedTitle }, + description: { + en: + "There's an awesome community of Elastic SIEM users out there. Join the discussion about configuring, learning, and using the Elastic SIEM app, and detecting threats!", + ja: translatedDescription, + }, + link_text: null, + link_url: { + en: 'https://discuss.elastic.co/c/siem?blade=securitysolutionfeed', + ja: translatedLinkUrl, + }, + languages: null, + badge: { en: '7.6' }, + image_url: { + en: + 'https://aws1.discourse-cdn.com/elastic/original/3X/f/8/f8c3d0b9971cfcd0be349d973aa5799f71d280cc.png?blade=securitysolutionfeed', + ja: translatedImageUrl, + }, + publish_on: new Date('2020-01-01T00:00:00'), + expire_on: new Date('2020-12-31T00:00:00'), + }, + ], + }; + + test('it returns a translated description when the browser language matches additional translated content', () => { + const lang = 'ja'; // an additional translation for this language is provided in the response + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(withNonDefaultTranslations)[0].description).toEqual( + translatedDescription + ); + }); + + test('it returns a translated imageUrl when the browser language matches additional translated content', () => { + const lang = 'ja'; // a translation for this language is provided in the response + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(withNonDefaultTranslations)[0].imageUrl).toEqual( + translatedImageUrl + ); + }); + + test('it returns a translated linkUrl when the browser language matches additional translated content', () => { + const lang = 'ja'; // a translation for this language is provided in the response + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(withNonDefaultTranslations)[0].linkUrl).toEqual( + translatedLinkUrl + ); + }); + + test('it returns a translated title when the browser language matches additional translated content', () => { + const lang = 'ja'; // a translation for this language is provided in the response + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(withNonDefaultTranslations)[0].title).toEqual( + translatedTitle + ); + }); + + test('it returns the default translated title when the browser language matches additional translated content', () => { + const lang = 'fr'; // no translation for this language + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(withNonDefaultTranslations)[0].title).toEqual( + 'Got SIEM Questions?' + ); + }); + + test('it returns the default translated title when the browser language is an empty string', () => { + const lang = ''; // just an empty string + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(withNonDefaultTranslations)[0].title).toEqual( + 'Got SIEM Questions?' + ); + }); + }); + + test('it generates a news item hash when an item does NOT include it', () => { + const lang = 'en'; + + const itemHasNoHash: RawNewsApiResponse = { + items: [ + { + title: { en: 'Got SIEM Questions?' }, + description: { + en: 'some description', + }, + link_text: null, + link_url: { en: 'https://example.com/link-url' }, + languages: null, + badge: { en: '7.6' }, + image_url: { + en: 'https://example.com/image-url', + }, + publish_on: new Date('2020-01-01T00:00:00'), + expire_on: new Date('2020-12-31T00:00:00'), + }, + ], + }; + + document.documentElement.lang = lang; + + expect(getNewsItemsFromApiResponse(itemHasNoHash)[0].hash.length).toBeGreaterThan(0); + }); + }); + + describe('fetchNews', () => { + const newsFeedUrl = 'https://feeds.elastic.co/security-solution/v8.0.0.json'; + + afterAll(() => { + delete (global as GlobalWithFetch).fetch; + }); + + test('it returns the raw API response from the news feed', async () => { + (global as GlobalWithFetch).fetch = jest.fn().mockImplementationOnce(() => + Promise.resolve({ + ok: true, + json: () => { + return rawNewsApiResponse; + }, + }) + ); + + expect(await fetchNews({ newsFeedUrl })).toEqual(rawNewsApiResponse); + }); + + test('it throws if the response from the news feed is not ok', async () => { + (global as GlobalWithFetch).fetch = jest.fn().mockImplementationOnce(() => + Promise.resolve({ + ok: false, + json: () => { + return rawNewsApiResponse; + }, + }) + ); + + await expect(fetchNews({ newsFeedUrl })).rejects.toThrow('Network Error: undefined'); + }); + }); + + describe('showNewsItem', () => { + const MOCK_DATE_NOW = 1579848101395; // 2020-01-24T06:41:41.395Z + + let dateNowSpy: { mockRestore: () => void }; + + beforeAll(() => { + dateNowSpy = jest.spyOn(Date, 'now').mockImplementation(() => MOCK_DATE_NOW); + }); + + afterAll(() => { + dateNowSpy.mockRestore(); + }); + + test('it should return true when the article has already been published, and will expire in the future', () => { + const alreadyPublishedAndNotExpired: NewsItem = { + description: 'description', + expireOn: new Date(MOCK_DATE_NOW + 1000), + hash: '5a35c984a9cdc1c6a25913f3d0b99b1aefc7257bc3b936c39db9fa0435edeed0', + imageUrl: 'https://example.com', + linkUrl: 'https://example.com', + publishOn: new Date(MOCK_DATE_NOW - 1000), + title: 'Show this post', + }; + + expect(showNewsItem(alreadyPublishedAndNotExpired)).toEqual(true); + }); + + test('it should return false when the article was published exactly "now", and will expire in the future', () => { + const publishedJustNowAndNotExpired: NewsItem = { + description: 'description', + expireOn: new Date(MOCK_DATE_NOW + 1000), + hash: '5a35c984a9cdc1c6a25913f3d0b99b1aefc7257bc3b936c39db9fa0435edeed0', + imageUrl: 'https://example.com', + linkUrl: 'https://example.com', + publishOn: new Date(MOCK_DATE_NOW), + title: 'Do NOT show this post', + }; + + expect(showNewsItem(publishedJustNowAndNotExpired)).toEqual(false); + }); + + test('it should return false when the article has not been published yet, and has not expired yet', () => { + const notPublishedAndNotExpired: NewsItem = { + description: 'description', + expireOn: new Date(MOCK_DATE_NOW + 5000), + hash: '5a35c984a9cdc1c6a25913f3d0b99b1aefc7257bc3b936c39db9fa0435edeed0', + imageUrl: 'https://example.com', + linkUrl: 'https://example.com', + publishOn: new Date(MOCK_DATE_NOW + 1000), + title: 'Do NOT show this post', + }; + + expect(showNewsItem(notPublishedAndNotExpired)).toEqual(false); + }); + + test('it should return false when the article was published in the past, and will expire exactly now', () => { + const alreadyPublishedAndExpiredNow: NewsItem = { + description: 'description', + expireOn: new Date(MOCK_DATE_NOW), + hash: '5a35c984a9cdc1c6a25913f3d0b99b1aefc7257bc3b936c39db9fa0435edeed0', + imageUrl: 'https://example.com', + linkUrl: 'https://example.com', + publishOn: new Date(MOCK_DATE_NOW - 1000), + title: 'Do NOT show this post', + }; + + expect(showNewsItem(alreadyPublishedAndExpiredNow)).toEqual(false); + }); + + test('it should return false when the article was published in the past, and it already expired', () => { + const articleJustExpired: NewsItem = { + description: 'description', + expireOn: new Date(MOCK_DATE_NOW - 1000), + hash: '5a35c984a9cdc1c6a25913f3d0b99b1aefc7257bc3b936c39db9fa0435edeed0', + imageUrl: 'https://example.com', + linkUrl: 'https://example.com', + publishOn: new Date(MOCK_DATE_NOW - 5000), + title: 'Do NOT show this post', + }; + + expect(showNewsItem(articleJustExpired)).toEqual(false); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/news_feed/helpers.ts b/x-pack/legacy/plugins/siem/public/components/news_feed/helpers.ts index 497127cdfba3d2..0cb5015872dece 100644 --- a/x-pack/legacy/plugins/siem/public/components/news_feed/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/components/news_feed/helpers.ts @@ -12,9 +12,19 @@ import { NewsItem, RawNewsApiItem, RawNewsApiResponse } from './types'; import { throwIfNotOk } from '../../hooks/api/api'; /** - * Combines the URL specified with the `newsFeedUrlSetting` with the Kibana - * version returned from `getKibanaVersion` to form a complete path to the - * news (specific to the current version of Kibana) + * Removes the `-SNAPSHOT` that is sometimes appended to the Kibana version, + * (e.g. `8.0.0-SNAPSHOT`), which is typically only seen in non-production + * environments + */ +export const removeSnapshotFromVersion = (kibanaVersion?: string) => + kibanaVersion?.replace(/-SNAPSHOT/gi, '') ?? kibanaVersion; + +/** + * Combines the URL specified in the `newsFeedUrlSetting`, e.g. + * `https://feeds.elastic.co/security-solution` with the Kibana version + * returned from `getKibanaVersion` (e.g. `8.0.0`) to form a complete path to + * the news specific to the current version of Kibana, (e.g. + * `https://feeds.elastic.co/security-solution/v8.0.0.json`) */ export const getNewsFeedUrl = ({ newsFeedUrlSetting, @@ -22,16 +32,26 @@ export const getNewsFeedUrl = ({ }: { newsFeedUrlSetting: string; getKibanaVersion: () => string; -}) => [newsFeedUrlSetting, `v${getKibanaVersion()}.json`].join('/'); +}) => + [ + newsFeedUrlSetting?.trim().replace(/\/$/, ''), + `v${removeSnapshotFromVersion(getKibanaVersion())}.json`, + ].join('/'); +/** Fall back to this language when extracting i18n news items from the feed */ export const NEWS_FEED_FALLBACK_LANGUAGE = 'en'; /** * Returns the current locale of the browser as specified in the `document`, * or the value of `fallback` if the locale could not be retrieved */ -export const getLocale = (fallback: string): string => - document.documentElement.lang?.toLowerCase() ?? fallback; // use the `lang` attribute of the `html` tag +export const getLocale = (fallback: string): string => { + if (document.documentElement.lang === '') { + return fallback; + } + + return document.documentElement.lang ?? fallback; // use the `lang` attribute of the `html` tag +}; const NO_NEWS_ITEMS: NewsItem[] = []; @@ -39,7 +59,7 @@ const NO_NEWS_ITEMS: NewsItem[] = []; * Transforms a `RawNewsApiResponse` from the news feed API to a collection of * `NewsItem`s */ -export const getNewsItemsFromApiResponse = (response?: RawNewsApiResponse): NewsItem[] => { +export const getNewsItemsFromApiResponse = (response?: RawNewsApiResponse | null): NewsItem[] => { const locale = getLocale(NEWS_FEED_FALLBACK_LANGUAGE); if (response == null || response.items == null) { @@ -53,7 +73,7 @@ export const getNewsItemsFromApiResponse = (response?: RawNewsApiResponse): News get(locale, x.description) ?? get(NEWS_FEED_FALLBACK_LANGUAGE, x.description) ?? '', expireOn: new Date(x.expire_on ?? ''), hash: x.hash ?? uuid.v4(), - imageUrl: x.image_url ?? null, + imageUrl: get(locale, x.image_url) ?? get(NEWS_FEED_FALLBACK_LANGUAGE, x.image_url) ?? null, linkUrl: get(locale, x.link_url) ?? get(NEWS_FEED_FALLBACK_LANGUAGE, x.link_url) ?? '', publishOn: new Date(x.publish_on ?? ''), title: get(locale, x.title) ?? get(NEWS_FEED_FALLBACK_LANGUAGE, x.title) ?? '', @@ -82,8 +102,8 @@ export const fetchNews = async ({ }; /** - * Returns false if `now` is before the `NewsItem` `publishOn` date, or - * after the `expireOn` date + * Returns true when "now" is after the publishOn date and before the expireOn + * date */ export const showNewsItem = ({ publishOn, expireOn }: NewsItem): boolean => - !moment().isBefore(publishOn) && !moment().isAfter(expireOn); + moment(Date.now()).isAfter(publishOn) && moment(Date.now()).isBefore(expireOn); diff --git a/x-pack/legacy/plugins/siem/public/components/news_feed/types.ts b/x-pack/legacy/plugins/siem/public/components/news_feed/types.ts index 2ee5a4c3c02aab..d38e525a723897 100644 --- a/x-pack/legacy/plugins/siem/public/components/news_feed/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/news_feed/types.ts @@ -26,7 +26,7 @@ export interface RawNewsApiItem { description?: { [lang: string]: string | null } | null; expire_on?: Date | null; hash?: string | null; - image_url?: string | null; + image_url?: { [lang: string]: string | null } | null; languages?: string[] | null; link_text?: { [lang: string]: string | null } | null; link_url?: { [lang: string]: string | null } | null; @@ -38,5 +38,5 @@ export interface RawNewsApiItem { * Defines the shape of a raw response from the News API */ export interface RawNewsApiResponse { - items?: RawNewsApiItem[]; + items?: RawNewsApiItem[] | null; } diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx index e069e64c66a926..31d8467025f96e 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx @@ -42,76 +42,78 @@ export interface OwnProps { const OverviewHostStatsManage = manageQuery(OverviewHostStats); type OverviewHostProps = OwnProps; -export const OverviewHost = React.memo( - ({ endDate, filterQuery, startDate, setQuery }) => { - const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); - return ( - - - - - {({ overviewHost, loading, id, inspect, refetch }) => { - const hostEventsCount = getOverviewHostStats(overviewHost).reduce( - (total, stat) => total + stat.count, - 0 - ); - const formattedHostEventsCount = numeral(hostEventsCount).format( - defaultNumberFormat - ); +const OverviewHostComponent: React.FC = ({ + endDate, + filterQuery, + startDate, + setQuery, +}) => { + const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); - return ( - <> - - } - title={ - - } - > - - - - + return ( + + + + + {({ overviewHost, loading, id, inspect, refetch }) => { + const hostEventsCount = getOverviewHostStats(overviewHost).reduce( + (total, stat) => total + stat.count, + 0 + ); + const formattedHostEventsCount = numeral(hostEventsCount).format(defaultNumberFormat); - - - ); - }} - - - - - ); - } -); + return ( + <> + + } + title={ + + } + > + + + + -OverviewHost.displayName = 'OverviewHost'; + + + ); + }} + + + + + ); +}; + +export const OverviewHost = React.memo(OverviewHostComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host_stats/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host_stats/__snapshots__/index.test.tsx.snap index 21a4568e241335..ea2e8d90b89dce 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host_stats/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host_stats/__snapshots__/index.test.tsx.snap @@ -245,8 +245,8 @@ exports[`Overview Host Stat Data rendering it renders the default OverviewHostSt > @@ -602,7 +602,7 @@ exports[`Overview Host Stat Data rendering it renders the default OverviewHostSt > + + + + + + + + + + + + id: 'filebeatSystemModule', }, { - count: data.winlogbeat ?? 0, + count: data.winlogbeatSecurity ?? 0, title: ( - + + ), + id: 'winlogbeatSecurity', + }, + { + count: data.winlogbeatMWSysmonOperational ?? 0, + title: ( + ), - id: 'winlogbeat', + id: 'winlogbeatMWSysmonOperational', }, ]; @@ -152,7 +165,10 @@ const hostStatGroups: StatGroup[] = [ { groupId: 'endgame', name: ( - + ), statIds: [ 'endgameDns', @@ -179,7 +195,7 @@ const hostStatGroups: StatGroup[] = [ defaultMessage="Winlogbeat" /> ), - statIds: ['winlogbeat'], + statIds: ['winlogbeatSecurity', 'winlogbeatMWSysmonOperational'], }, ]; diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host_stats/mock.ts b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host_stats/mock.ts index c7adb13657760c..60e653caab8c10 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host_stats/mock.ts +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host_stats/mock.ts @@ -22,6 +22,7 @@ export const mockData: { OverviewHost: OverviewHostData } = { endgameRegistry: 39161718, endgameSecurity: 39202122, filebeatSystemModule: 568, - winlogbeat: 296999, + winlogbeatSecurity: 195929, + winlogbeatMWSysmonOperational: 101070, }, }; diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/types.ts b/x-pack/legacy/plugins/siem/public/components/page/overview/types.ts index 9333aa386dbc06..e260f2843692dd 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/types.ts @@ -28,7 +28,8 @@ export type OverviewStatId = | 'packetbeatDNS' | 'packetbeatFlow' | 'packetbeatTLS' - | 'winlogbeat'; + | 'winlogbeatSecurity' + | 'winlogbeatMWSysmonOperational'; export interface FormattedStat { count: number; diff --git a/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap index a05fb513dd7ef1..69596ba8f33250 100644 --- a/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap @@ -49,7 +49,7 @@ exports[`Stat Items Component disable charts it renders the default widget 1`] = show={true} >
    ( diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/column_header.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/column_header.tsx index ccaeeff972a812..9df805bddcc827 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/column_header.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/column_header.tsx @@ -30,6 +30,7 @@ export interface ColumnHeader { format?: string; id: ColumnId; label?: string; + linkField?: string; placeholder?: string; type?: string; width: number; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/data_driven_columns/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/data_driven_columns/index.test.tsx index 36427015260a7f..098bd3108dba16 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/data_driven_columns/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/data_driven_columns/index.test.tsx @@ -23,6 +23,7 @@ describe('Columns', () => { columnHeaders={headersSansTimestamp} columnRenderers={columnRenderers} data={mockTimelineData[0].data} + ecsData={mockTimelineData[0].ecs} onColumnResized={jest.fn()} timelineId="test" /> diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/data_driven_columns/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/data_driven_columns/index.tsx index 37b6e302150560..416c72cfbc2554 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/data_driven_columns/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/data_driven_columns/index.tsx @@ -6,7 +6,8 @@ import React from 'react'; -import { TimelineNonEcsData } from '../../../../graphql/types'; +import { getOr } from 'lodash/fp'; +import { Ecs, TimelineNonEcsData } from '../../../../graphql/types'; import { OnColumnResized } from '../../events'; import { EventsTd, EventsTdContent, EventsTdGroupData } from '../../styles'; import { ColumnHeader } from '../column_headers/column_header'; @@ -18,12 +19,13 @@ interface Props { columnHeaders: ColumnHeader[]; columnRenderers: ColumnRenderer[]; data: TimelineNonEcsData[]; + ecsData: Ecs; onColumnResized: OnColumnResized; timelineId: string; } export const DataDrivenColumns = React.memo( - ({ _id, columnHeaders, columnRenderers, data, timelineId }) => { + ({ _id, columnHeaders, columnRenderers, data, ecsData, timelineId }) => { // Passing the styles directly to the component because the width is // being calculated and is recommended by Styled Components for performance // https://github.com/styled-components/styled-components/issues/134#issuecomment-312415291 @@ -36,6 +38,7 @@ export const DataDrivenColumns = React.memo( columnName: header.id, eventId: _id, field: header, + linkValues: getOr([], header.linkField ?? '', ecsData), timelineId, truncate: true, values: getMappedNonEcsValue({ diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/event_column_view.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/event_column_view.tsx index 1036c6b53b4c1d..74476c3dc1d617 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/event_column_view.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/event_column_view.tsx @@ -127,6 +127,7 @@ export const EventColumnView = React.memo( columnHeaders={columnHeaders} columnRenderers={columnRenderers} data={data} + ecsData={ecsData} onColumnResized={onColumnResized} timelineId={timelineId} /> diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/index.tsx index 9361a46dddff45..6b2e105ad05664 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/index.tsx @@ -31,6 +31,7 @@ interface Props { browserFields: BrowserFields; columnHeaders: ColumnHeader[]; columnRenderers: ColumnRenderer[]; + containerElementRef: HTMLDivElement; data: TimelineItem[]; eventIdToNoteIds: Readonly>; getNotesByIds: (noteIds: string[]) => Note[]; @@ -53,61 +54,62 @@ interface Props { // Passing the styles directly to the component because the width is // being calculated and is recommended by Styled Components for performance // https://github.com/styled-components/styled-components/issues/134#issuecomment-312415291 -export const Events = React.memo( - ({ - actionsColumnWidth, - addNoteToEvent, - browserFields, - columnHeaders, - columnRenderers, - data, - eventIdToNoteIds, - getNotesByIds, - id, - isEventViewer = false, - loadingEventIds, - onColumnResized, - onPinEvent, - onRowSelected, - onUpdateColumns, - onUnPinEvent, - pinnedEventIds, - rowRenderers, - selectedEventIds, - showCheckboxes, - toggleColumn, - updateNote, - }) => ( - - {data.map((event, i) => ( - - ))} - - ) +const EventsComponent: React.FC = ({ + actionsColumnWidth, + addNoteToEvent, + browserFields, + columnHeaders, + columnRenderers, + containerElementRef, + data, + eventIdToNoteIds, + getNotesByIds, + id, + isEventViewer = false, + loadingEventIds, + onColumnResized, + onPinEvent, + onRowSelected, + onUpdateColumns, + onUnPinEvent, + pinnedEventIds, + rowRenderers, + selectedEventIds, + showCheckboxes, + toggleColumn, + updateNote, +}) => ( + + {data.map((event, i) => ( + + ))} + ); -Events.displayName = 'Events'; + +export const Events = React.memo(EventsComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx index 6c43d9a63029c2..5704b6030e7d19 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx @@ -35,6 +35,7 @@ import { StatefulEventChild } from './stateful_event_child'; interface Props { actionsColumnWidth: number; + containerElementRef: HTMLDivElement; addNoteToEvent: AddNoteToEvent; browserFields: BrowserFields; columnHeaders: ColumnHeader[]; @@ -115,6 +116,7 @@ const StatefulEventComponent: React.FC = ({ actionsColumnWidth, addNoteToEvent, browserFields, + containerElementRef, columnHeaders, columnRenderers, event, @@ -201,6 +203,7 @@ const StatefulEventComponent: React.FC = ({ {({ isVisible }) => { @@ -279,7 +282,7 @@ const StatefulEventComponent: React.FC = ({ } else { // Height place holder for visibility detection as well as re-rendering sections. const height = - divElement.current != null + divElement.current != null && divElement.current.clientHeight ? `${divElement.current.clientHeight}px` : DEFAULT_ROW_HEIGHT; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx index c4ad532f76fc42..f00da482669278 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useMemo } from 'react'; +import React, { useMemo, useRef } from 'react'; import { BrowserFields } from '../../../containers/source'; import { TimelineItem, TimelineNonEcsData } from '../../../graphql/types'; @@ -95,6 +95,7 @@ export const Body = React.memo( toggleColumn, updateNote, }) => { + const containerElementRef = useRef(null); const timelineTypeContext = useTimelineTypeContext(); const additionalActionWidth = timelineTypeContext.timelineActions?.reduce((acc, v) => acc + v.width, 0) ?? 0; @@ -112,7 +113,7 @@ export const Body = React.memo( return ( <> - + ( /> React.ReactNode; } diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/constants.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/constants.tsx index f22c338f2d8797..0330fb458e3640 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/constants.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/constants.tsx @@ -8,3 +8,4 @@ export const DATE_FIELD_TYPE = 'date'; export const HOST_NAME_FIELD_NAME = 'host.name'; export const IP_FIELD_TYPE = 'ip'; export const MESSAGE_FIELD_NAME = 'message'; +export const SIGNAL_RULE_NAME_FIELD_NAME = 'signal.rule.name'; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/formatted_field.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/formatted_field.tsx index 888029600d8609..010a328d2993dd 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/formatted_field.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/formatted_field.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiToolTip, EuiLink } from '@elastic/eui'; import { isNumber, isString, isEmpty } from 'lodash/fp'; import React from 'react'; @@ -15,6 +15,7 @@ import { getOrEmptyTagFromValue, getEmptyTagValue } from '../../../empty_value'; import { FormattedDate } from '../../../formatted_date'; import { FormattedIp } from '../../../formatted_ip'; import { HostDetailsLink } from '../../../links'; +import { getRuleDetailsUrl } from '../../../link_to/redirect_to_detection_engine'; import { Port, PORT_NAMES } from '../../../port'; import { TruncatableText } from '../../../truncatable_text'; import { @@ -22,6 +23,7 @@ import { HOST_NAME_FIELD_NAME, IP_FIELD_TYPE, MESSAGE_FIELD_NAME, + SIGNAL_RULE_NAME_FIELD_NAME, } from './constants'; // simple black-list to prevent dragging and dropping fields such as message name @@ -35,7 +37,8 @@ const FormattedFieldValueComponent: React.FC<{ fieldType: string; truncate?: boolean; value: string | number | undefined | null; -}> = ({ contextId, eventId, fieldFormat, fieldName, fieldType, truncate, value }) => { + linkValue?: string | null | undefined; +}> = ({ contextId, eventId, fieldFormat, fieldName, fieldType, truncate, value, linkValue }) => { if (fieldType === IP_FIELD_TYPE) { return ( {value} ); + } else if (fieldName === SIGNAL_RULE_NAME_FIELD_NAME) { + const ruleName = `${value}`; + const ruleId = linkValue; + + return isString(value) && ruleName.length > 0 && ruleId != null ? ( + + + {value} + + + ) : ( + getEmptyTagValue() + ); } else { const contentValue = getOrEmptyTagFromValue(value); const content = truncate ? {contentValue} : contentValue; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/plain_column_renderer.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/plain_column_renderer.tsx index 70485c41f3b889..deeec05bc07074 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/plain_column_renderer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/plain_column_renderer.tsx @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { head } from 'lodash/fp'; import React from 'react'; import { TimelineNonEcsData } from '../../../../graphql/types'; @@ -27,6 +28,7 @@ export const plainColumnRenderer: ColumnRenderer = { timelineId, truncate, values, + linkValues, }: { columnName: string; eventId: string; @@ -34,6 +36,7 @@ export const plainColumnRenderer: ColumnRenderer = { timelineId: string; truncate?: boolean; values: string[] | undefined | null; + linkValues?: string[] | null | undefined; }) => values != null ? values.map(value => ( @@ -46,6 +49,7 @@ export const plainColumnRenderer: ColumnRenderer = { fieldType={field.type || ''} value={parseValue(value)} truncate={truncate} + linkValue={head(linkValues)} /> )) : getEmptyTagValue(), diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx index bb8b04f6e304ef..a224e0355b5d35 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx @@ -166,7 +166,7 @@ const StatefulTimelineComponent = React.memo( updateItemsPerPage, upsertColumn, }) => { - const [loading, signalIndexExists, signalIndexName] = useSignalIndex(); + const { loading, signalIndexExists, signalIndexName } = useSignalIndex(); const indexToAdd = useMemo(() => { if (signalIndexExists && signalIndexName != null && ['signal', 'all'].includes(eventType)) { @@ -268,6 +268,7 @@ const StatefulTimelineComponent = React.memo( columns={columns} dataProviders={dataProviders!} end={end} + eventType={eventType} filters={filters} flyoutHeaderHeight={flyoutHeaderHeight} flyoutHeight={flyoutHeight} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_super_select/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_super_select/index.tsx index 009ab141e958e2..b8280aedd12fa5 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_super_select/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_super_select/index.tsx @@ -73,6 +73,7 @@ const MyEuiFlexGroup = styled(EuiFlexGroup)` interface SearchTimelineSuperSelectProps { isDisabled: boolean; + hideUntitled?: boolean; timelineId: string | null; timelineTitle: string | null; onTimelineChange: (timelineTitle: string, timelineId: string | null) => void; @@ -101,6 +102,7 @@ const POPOVER_HEIGHT = 260; const TIMELINE_ITEM_HEIGHT = 50; const SearchTimelineSuperSelectComponent: React.FC = ({ isDisabled, + hideUntitled = false, timelineId, timelineTitle, onTimelineChange, @@ -287,7 +289,11 @@ const SearchTimelineSuperSelectComponent: React.FC !hideUntitled || t.title !== '').length, + totalCount + ), } as unknown) as ListProps, }} renderOption={renderTimelineOption} @@ -308,18 +314,20 @@ const SearchTimelineSuperSelectComponent: React.FC - ({ - description: t.description, - favorite: t.favorite, - label: t.title, - id: t.savedObjectId, - key: `${t.title}-${index}`, - title: t.title, - checked: t.savedObjectId === timelineId ? 'on' : undefined, - } as Option) - ), + ...timelines + .filter(t => !hideUntitled || t.title !== '') + .map( + (t, index) => + ({ + description: t.description, + favorite: t.favorite, + label: t.title, + id: t.savedObjectId, + key: `${t.title}-${index}`, + title: t.title, + checked: t.savedObjectId === timelineId ? 'on' : undefined, + } as Option) + ), ]} > {(list, search) => ( diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx index 0be5e69abea382..f7c0d0b4757347 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx @@ -54,6 +54,7 @@ describe('Timeline', () => { id="foo" dataProviders={mockDataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -92,6 +93,7 @@ describe('Timeline', () => { id="foo" dataProviders={mockDataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -133,6 +135,7 @@ describe('Timeline', () => { id="foo" dataProviders={mockDataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -174,6 +177,7 @@ describe('Timeline', () => { id="foo" dataProviders={mockDataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -220,6 +224,7 @@ describe('Timeline', () => { id="foo" dataProviders={mockDataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -268,6 +273,7 @@ describe('Timeline', () => { id="foo" dataProviders={mockDataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -324,6 +330,7 @@ describe('Timeline', () => { id="foo" dataProviders={mockDataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -384,6 +391,7 @@ describe('Timeline', () => { id="foo" dataProviders={mockDataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -447,6 +455,7 @@ describe('Timeline', () => { id="foo" dataProviders={dataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -500,6 +509,7 @@ describe('Timeline', () => { id="foo" dataProviders={dataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -559,6 +569,7 @@ describe('Timeline', () => { id="foo" dataProviders={dataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} @@ -622,6 +633,7 @@ describe('Timeline', () => { id="foo" dataProviders={dataProviders} end={endDate} + eventType="raw" filters={[]} flyoutHeight={testFlyoutHeight} flyoutHeaderHeight={flyoutHeaderHeight} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index ece5b4fa18d1c4..11886b45b0bec2 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -13,7 +13,7 @@ import { BrowserFields } from '../../containers/source'; import { TimelineQuery } from '../../containers/timeline'; import { Direction } from '../../graphql/types'; import { useKibana } from '../../lib/kibana'; -import { KqlMode } from '../../store/timeline/model'; +import { KqlMode, EventType } from '../../store/timeline/model'; import { AutoSizer } from '../auto_sizer'; import { ColumnHeader } from './body/column_headers/column_header'; import { defaultHeaders } from './body/column_headers/default_headers'; @@ -60,6 +60,7 @@ interface Props { columns: ColumnHeader[]; dataProviders: DataProvider[]; end: number; + eventType: EventType; filters: esFilters.Filter[]; flyoutHeaderHeight: number; flyoutHeight: number; @@ -92,6 +93,7 @@ export const TimelineComponent = ({ columns, dataProviders, end, + eventType, filters, flyoutHeaderHeight, flyoutHeight, @@ -159,6 +161,7 @@ export const TimelineComponent = ({ {combinedQueries != null ? ( c.id)} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline_context.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline_context.tsx index 611452cc7ccd13..15759c2efff0b5 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline_context.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline_context.tsx @@ -23,6 +23,7 @@ export interface TimelineTypeContextProps { selectAll?: boolean; timelineActions?: TimelineAction[]; title?: string; + unit?: (totalCount: number) => string; } const initTimelineType: TimelineTypeContextProps = { documentType: undefined, @@ -32,6 +33,7 @@ const initTimelineType: TimelineTypeContextProps = { selectAll: false, timelineActions: [], title: undefined, + unit: undefined, }; export const TimelineTypeContext = createContext(initTimelineType); export const useTimelineTypeContext = () => useContext(TimelineTypeContext); diff --git a/x-pack/legacy/plugins/siem/public/components/utils.ts b/x-pack/legacy/plugins/siem/public/components/utils.ts new file mode 100644 index 00000000000000..42dd5b7c011aae --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/utils.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { niceTimeFormatByDay, timeFormatter } from '@elastic/charts'; +import moment from 'moment-timezone'; + +export const getDaysDiff = (minDate: moment.Moment, maxDate: moment.Moment) => { + const diff = maxDate.diff(minDate, 'days'); + + if (diff <= 1 && !minDate.isSame(maxDate)) { + return 2; // to return proper pattern from niceTimeFormatByDay + } + + return diff; +}; + +export const histogramDateTimeFormatter = (domain: [number, number] | null, fixedDiff?: number) => { + const diff = fixedDiff ?? getDaysDiff(moment(domain![0]), moment(domain![1])); + const format = niceTimeFormatByDay(diff); + return timeFormatter(format); +}; diff --git a/x-pack/legacy/plugins/siem/public/components/wrapper_page/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/wrapper_page/__snapshots__/index.test.tsx.snap index 1eef27bcc0a874..5ade447994a1ec 100644 --- a/x-pack/legacy/plugins/siem/public/components/wrapper_page/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/wrapper_page/__snapshots__/index.test.tsx.snap @@ -1,39 +1,39 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`WrapperPage it renders 1`] = ` - +

    Test page

    -
    + `; exports[`WrapperPage restrict width custom max width when restrictWidth is number 1`] = ` -

    Test page

    -
    + `; exports[`WrapperPage restrict width custom max width when restrictWidth is string 1`] = ` -

    Test page

    -
    + `; exports[`WrapperPage restrict width default max width when restrictWidth is true 1`] = ` -

    Test page

    -
    + `; diff --git a/x-pack/legacy/plugins/siem/public/components/wrapper_page/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/wrapper_page/index.test.tsx index 788ea14f4bd22d..23cae15004e39f 100644 --- a/x-pack/legacy/plugins/siem/public/components/wrapper_page/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/wrapper_page/index.test.tsx @@ -20,7 +20,7 @@ describe('WrapperPage', () => { ); - expect(wrapper.find('WrapperPage')).toMatchSnapshot(); + expect(wrapper.find('Memo(WrapperPageComponent)')).toMatchSnapshot(); }); describe('restrict width', () => { @@ -33,7 +33,7 @@ describe('WrapperPage', () => { ); - expect(wrapper.find('WrapperPage')).toMatchSnapshot(); + expect(wrapper.find('Memo(WrapperPageComponent)')).toMatchSnapshot(); }); test('custom max width when restrictWidth is number', () => { @@ -45,7 +45,7 @@ describe('WrapperPage', () => { ); - expect(wrapper.find('WrapperPage')).toMatchSnapshot(); + expect(wrapper.find('Memo(WrapperPageComponent)')).toMatchSnapshot(); }); test('custom max width when restrictWidth is string', () => { @@ -57,7 +57,7 @@ describe('WrapperPage', () => { ); - expect(wrapper.find('WrapperPage')).toMatchSnapshot(); + expect(wrapper.find('Memo(WrapperPageComponent)')).toMatchSnapshot(); }); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/wrapper_page/index.tsx b/x-pack/legacy/plugins/siem/public/components/wrapper_page/index.tsx index d777c8d6c9eabd..bac0357def942d 100644 --- a/x-pack/legacy/plugins/siem/public/components/wrapper_page/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/wrapper_page/index.tsx @@ -37,29 +37,32 @@ interface WrapperPageProps { style?: Record; } -export const WrapperPage = React.memo( - ({ children, className, restrictWidth, style }) => { - const classes = classNames(className, { - siemWrapperPage: true, - 'siemWrapperPage--restrictWidthDefault': - restrictWidth && typeof restrictWidth === 'boolean' && restrictWidth === true, - 'siemWrapperPage--restrictWidthCustom': restrictWidth && typeof restrictWidth !== 'boolean', - }); +const WrapperPageComponent: React.FC = ({ + children, + className, + restrictWidth, + style, +}) => { + const classes = classNames(className, { + siemWrapperPage: true, + 'siemWrapperPage--restrictWidthDefault': + restrictWidth && typeof restrictWidth === 'boolean' && restrictWidth === true, + 'siemWrapperPage--restrictWidthCustom': restrictWidth && typeof restrictWidth !== 'boolean', + }); - let customStyle: WrapperPageProps['style']; + let customStyle: WrapperPageProps['style']; - if (restrictWidth && typeof restrictWidth !== 'boolean') { - const value = typeof restrictWidth === 'number' ? `${restrictWidth}px` : restrictWidth; - customStyle = { ...style, maxWidth: value }; - } - - return ( - - {children} - - - ); + if (restrictWidth && typeof restrictWidth !== 'boolean') { + const value = typeof restrictWidth === 'number' ? `${restrictWidth}px` : restrictWidth; + customStyle = { ...style, maxWidth: value }; } -); -WrapperPage.displayName = 'WrapperPage'; + return ( + + {children} + + + ); +}; + +export const WrapperPage = React.memo(WrapperPageComponent); diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts index a83e874437c101..6b3578bacf24c1 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts @@ -26,7 +26,9 @@ import { throwIfNotOk } from '../../../hooks/api/api'; import { DETECTION_ENGINE_RULES_URL, DETECTION_ENGINE_PREPACKAGED_URL, - DETECTION_ENGINE_RULES_STATUS, + DETECTION_ENGINE_RULES_STATUS_URL, + DETECTION_ENGINE_PREPACKAGED_RULES_STATUS_URL, + DETECTION_ENGINE_TAGS_URL, } from '../../../../common/constants'; import * as i18n from '../../../pages/detection_engine/rules/translations'; @@ -53,61 +55,72 @@ export const addRule = async ({ rule, signal }: AddRulesProps): Promise }; /** - * Fetches all rules or single specified rule from the Detection Engine API + * Fetches all rules from the Detection Engine API * * @param filterOptions desired filters (e.g. filter/sortField/sortOrder) * @param pagination desired pagination options (e.g. page/perPage) - * @param id if specified, will return specific rule if exists * @param signal to cancel request + * */ export const fetchRules = async ({ filterOptions = { filter: '', sortField: 'enabled', sortOrder: 'desc', + showCustomRules: false, + showElasticRules: false, + tags: [], }, pagination = { page: 1, perPage: 20, total: 0, }, - id, signal, }: FetchRulesProps): Promise => { + const filters = [ + ...(filterOptions.filter.length !== 0 + ? [`alert.attributes.name:%20${encodeURIComponent(filterOptions.filter)}`] + : []), + ...(filterOptions.showCustomRules + ? ['alert.attributes.tags:%20%22__internal_immutable:false%22'] + : []), + ...(filterOptions.showElasticRules + ? ['alert.attributes.tags:%20%22__internal_immutable:true%22'] + : []), + ...(filterOptions.tags?.map(t => `alert.attributes.tags:${encodeURIComponent(t)}`) ?? []), + ]; + const queryParams = [ `page=${pagination.page}`, `per_page=${pagination.perPage}`, `sort_field=${filterOptions.sortField}`, `sort_order=${filterOptions.sortOrder}`, - ...(filterOptions.filter.length !== 0 - ? [`filter=alert.attributes.name:%20${encodeURIComponent(filterOptions.filter)}`] - : []), + ...(filters.length > 0 ? [`filter=${filters.join('%20AND%20')}`] : []), ]; - const endpoint = - id != null - ? `${chrome.getBasePath()}${DETECTION_ENGINE_RULES_URL}?id="${id}"` - : `${chrome.getBasePath()}${DETECTION_ENGINE_RULES_URL}/_find?${queryParams.join('&')}`; - - const response = await fetch(endpoint, { - method: 'GET', - signal, - }); + const response = await fetch( + `${chrome.getBasePath()}${DETECTION_ENGINE_RULES_URL}/_find?${queryParams.join('&')}`, + { + method: 'GET', + credentials: 'same-origin', + headers: { + 'content-type': 'application/json', + 'kbn-xsrf': 'true', + }, + signal, + } + ); await throwIfNotOk(response); - return id != null - ? { - page: 0, - perPage: 1, - total: 1, - data: response.json(), - } - : response.json(); + return response.json(); }; /** * Fetch a Rule by providing a Rule ID * * @param id Rule ID's (not rule_id) + * @param signal to cancel request + * */ export const fetchRuleById = async ({ id, signal }: FetchRuleProps): Promise => { const response = await fetch(`${chrome.getBasePath()}${DETECTION_ENGINE_RULES_URL}?id=${id}`, { @@ -313,6 +326,7 @@ export const exportRules = async ({ * Get Rule Status provided Rule ID * * @param id string of Rule ID's (not rule_id) + * @param signal AbortSignal for cancelling request * * @throws An error if response is not OK */ @@ -324,7 +338,7 @@ export const getRuleStatusById = async ({ signal: AbortSignal; }): Promise> => { const response = await fetch( - `${chrome.getBasePath()}${DETECTION_ENGINE_RULES_STATUS}?ids=${encodeURIComponent( + `${chrome.getBasePath()}${DETECTION_ENGINE_RULES_STATUS_URL}?ids=${encodeURIComponent( JSON.stringify([id]) )}`, { @@ -341,3 +355,58 @@ export const getRuleStatusById = async ({ await throwIfNotOk(response); return response.json(); }; + +/** + * Fetch all unique Tags used by Rules + * + * @param signal to cancel request + * + */ +export const fetchTags = async ({ signal }: { signal: AbortSignal }): Promise => { + const response = await fetch(`${chrome.getBasePath()}${DETECTION_ENGINE_TAGS_URL}`, { + method: 'GET', + credentials: 'same-origin', + headers: { + 'content-type': 'application/json', + 'kbn-xsrf': 'true', + }, + signal, + }); + + await throwIfNotOk(response); + return response.json(); +}; + +/** + * Get pre packaged rules Status + * + * @param signal AbortSignal for cancelling request + * + * @throws An error if response is not OK + */ +export const getPrePackagedRulesStatus = async ({ + signal, +}: { + signal: AbortSignal; +}): Promise<{ + rules_custom_installed: number; + rules_installed: number; + rules_not_installed: number; + rules_not_updated: number; +}> => { + const response = await fetch( + `${chrome.getBasePath()}${DETECTION_ENGINE_PREPACKAGED_RULES_STATUS_URL}`, + { + method: 'GET', + credentials: 'same-origin', + headers: { + 'content-type': 'application/json', + 'kbn-xsrf': 'true', + }, + signal, + } + ); + + await throwIfNotOk(response); + return response.json(); +}; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx index f7a30766ad7d8c..d376a1d6ad178a 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx @@ -22,11 +22,11 @@ import { useApolloClient } from '../../../utils/apollo_context'; import * as i18n from './translations'; interface FetchIndexPatternReturn { - browserFields: BrowserFields | null; + browserFields: BrowserFields; isLoading: boolean; indices: string[]; indicesExists: boolean; - indexPatterns: IIndexPattern | null; + indexPatterns: IIndexPattern; } type Return = [FetchIndexPatternReturn, Dispatch>]; @@ -35,8 +35,8 @@ export const useFetchIndexPatterns = (defaultIndices: string[] = []): Return => const apolloClient = useApolloClient(); const [indices, setIndices] = useState(defaultIndices); const [indicesExists, setIndicesExists] = useState(false); - const [indexPatterns, setIndexPatterns] = useState(null); - const [browserFields, setBrowserFields] = useState(null); + const [indexPatterns, setIndexPatterns] = useState({ fields: [], title: '' }); + const [browserFields, setBrowserFields] = useState({}); const [isLoading, setIsLoading] = useState(false); const [, dispatchToaster] = useStateToaster(); diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/index.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/index.ts index e9a0f27b346960..c7ecfb33cd9052 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/index.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/index.ts @@ -10,4 +10,5 @@ export * from './persist_rule'; export * from './types'; export * from './use_rule'; export * from './use_rules'; +export * from './use_pre_packaged_rules'; export * from './use_rule_status'; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/translations.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/translations.ts index 39efbde2ad5c24..84e008312fefe6 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/translations.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/translations.ts @@ -16,3 +16,24 @@ export const RULE_ADD_FAILURE = i18n.translate( defaultMessage: 'Failed to add Rule', } ); + +export const RULE_PREPACKAGED_FAILURE = i18n.translate( + 'xpack.siem.containers.detectionEngine.createPrePackagedRuleFailDescription', + { + defaultMessage: 'Failed to installed pre-packaged rules from elastic', + } +); + +export const RULE_PREPACKAGED_SUCCESS = i18n.translate( + 'xpack.siem.containers.detectionEngine.createPrePackagedRuleSuccesDescription', + { + defaultMessage: 'Installed pre-packaged rules from elastic', + } +); + +export const TAG_FETCH_FAILURE = i18n.translate( + 'xpack.siem.containers.detectionEngine.tagFetchFailDescription', + { + defaultMessage: 'Failed to fetch Tags', + } +); diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts index 0dcd0da5be8f61..b30c3b211b1b8d 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts @@ -30,7 +30,7 @@ export const NewRuleSchema = t.intersection([ rule_id: t.string, saved_id: t.string, tags: t.array(t.string), - threats: t.array(t.unknown), + threat: t.array(t.unknown), to: t.string, updated_by: t.string, }), @@ -73,7 +73,7 @@ export const RuleSchema = t.intersection([ tags: t.array(t.string), type: t.string, to: t.string, - threats: t.array(t.unknown), + threat: t.array(t.unknown), updated_at: t.string, updated_by: t.string, }), @@ -114,7 +114,6 @@ export interface PaginationOptions { export interface FetchRulesProps { pagination?: PaginationOptions; filterOptions?: FilterOptions; - id?: string; signal: AbortSignal; } @@ -122,6 +121,9 @@ export interface FilterOptions { filter: string; sortField: string; sortOrder: 'asc' | 'desc'; + showCustomRules?: boolean; + showElasticRules?: boolean; + tags?: string[]; } export interface FetchRulesResponse { diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_create_packaged_rules.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_create_packaged_rules.tsx deleted file mode 100644 index 592419f8790113..00000000000000 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_create_packaged_rules.tsx +++ /dev/null @@ -1,81 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { useEffect, useState } from 'react'; - -import { createPrepackagedRules } from './api'; - -type Return = [boolean, boolean | null]; - -interface UseCreatePackagedRules { - canUserCRUD: boolean | null; - hasIndexManage: boolean | null; - hasManageApiKey: boolean | null; - isAuthenticated: boolean | null; - isSignalIndexExists: boolean | null; -} - -/** - * Hook for creating the packages rules - * - * @param canUserCRUD boolean - * @param hasIndexManage boolean - * @param hasManageApiKey boolean - * @param isAuthenticated boolean - * @param isSignalIndexExists boolean - * - * @returns [loading, hasCreatedPackageRules] - */ -export const useCreatePackagedRules = ({ - canUserCRUD, - hasIndexManage, - hasManageApiKey, - isAuthenticated, - isSignalIndexExists, -}: UseCreatePackagedRules): Return => { - const [hasCreatedPackageRules, setHasCreatedPackageRules] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - let isSubscribed = true; - const abortCtrl = new AbortController(); - setLoading(true); - - async function createRules() { - try { - await createPrepackagedRules({ - signal: abortCtrl.signal, - }); - - if (isSubscribed) { - setHasCreatedPackageRules(true); - } - } catch (error) { - if (isSubscribed) { - setHasCreatedPackageRules(false); - } - } - if (isSubscribed) { - setLoading(false); - } - } - if ( - canUserCRUD && - hasIndexManage && - hasManageApiKey && - isAuthenticated && - isSignalIndexExists - ) { - createRules(); - } - return () => { - isSubscribed = false; - abortCtrl.abort(); - }; - }, [canUserCRUD, hasIndexManage, hasManageApiKey, isAuthenticated, isSignalIndexExists]); - - return [loading, hasCreatedPackageRules]; -}; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.tsx new file mode 100644 index 00000000000000..14d40f9ffbc37a --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_pre_packaged_rules.tsx @@ -0,0 +1,190 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useEffect, useState } from 'react'; + +import { useStateToaster, displaySuccessToast } from '../../../components/toasters'; +import { errorToToaster } from '../../../components/ml/api/error_to_toaster'; +import { getPrePackagedRulesStatus, createPrepackagedRules } from './api'; +import * as i18n from './translations'; + +type Func = () => void; +export type CreatePreBuiltRules = () => Promise; +interface Return { + createPrePackagedRules: null | CreatePreBuiltRules; + loading: boolean; + loadingCreatePrePackagedRules: boolean; + refetchPrePackagedRulesStatus: Func | null; + rulesCustomInstalled: number | null; + rulesInstalled: number | null; + rulesNotInstalled: number | null; + rulesNotUpdated: number | null; +} + +interface UsePrePackagedRuleProps { + canUserCRUD: boolean | null; + hasIndexWrite: boolean | null; + hasManageApiKey: boolean | null; + isAuthenticated: boolean | null; + isSignalIndexExists: boolean | null; +} + +/** + * Hook for using to get status about pre-packaged Rules from the Detection Engine API + * + * @param hasIndexWrite boolean + * @param hasManageApiKey boolean + * @param isAuthenticated boolean + * @param isSignalIndexExists boolean + * + */ +export const usePrePackagedRules = ({ + canUserCRUD, + hasIndexWrite, + hasManageApiKey, + isAuthenticated, + isSignalIndexExists, +}: UsePrePackagedRuleProps): Return => { + const [rulesStatus, setRuleStatus] = useState< + Pick< + Return, + | 'createPrePackagedRules' + | 'refetchPrePackagedRulesStatus' + | 'rulesCustomInstalled' + | 'rulesInstalled' + | 'rulesNotInstalled' + | 'rulesNotUpdated' + > + >({ + createPrePackagedRules: null, + refetchPrePackagedRulesStatus: null, + rulesCustomInstalled: null, + rulesInstalled: null, + rulesNotInstalled: null, + rulesNotUpdated: null, + }); + const [loadingCreatePrePackagedRules, setLoadingCreatePrePackagedRules] = useState(false); + const [loading, setLoading] = useState(true); + const [, dispatchToaster] = useStateToaster(); + + useEffect(() => { + let isSubscribed = true; + const abortCtrl = new AbortController(); + + const fetchPrePackagedRules = async () => { + try { + setLoading(true); + const prePackagedRuleStatusResponse = await getPrePackagedRulesStatus({ + signal: abortCtrl.signal, + }); + + if (isSubscribed) { + setRuleStatus({ + createPrePackagedRules: createElasticRules, + refetchPrePackagedRulesStatus: fetchPrePackagedRules, + rulesCustomInstalled: prePackagedRuleStatusResponse.rules_custom_installed, + rulesInstalled: prePackagedRuleStatusResponse.rules_installed, + rulesNotInstalled: prePackagedRuleStatusResponse.rules_not_installed, + rulesNotUpdated: prePackagedRuleStatusResponse.rules_not_updated, + }); + } + } catch (error) { + if (isSubscribed) { + setRuleStatus({ + createPrePackagedRules: null, + refetchPrePackagedRulesStatus: null, + rulesCustomInstalled: null, + rulesInstalled: null, + rulesNotInstalled: null, + rulesNotUpdated: null, + }); + errorToToaster({ title: i18n.RULE_FETCH_FAILURE, error, dispatchToaster }); + } + } + if (isSubscribed) { + setLoading(false); + } + }; + + const createElasticRules = async (): Promise => { + return new Promise(async resolve => { + try { + if ( + canUserCRUD && + hasIndexWrite && + hasManageApiKey && + isAuthenticated && + isSignalIndexExists + ) { + setLoadingCreatePrePackagedRules(true); + await createPrepackagedRules({ + signal: abortCtrl.signal, + }); + + if (isSubscribed) { + let iterationTryOfFetchingPrePackagedCount = 0; + let timeoutId = -1; + const stopTimeOut = () => { + if (timeoutId !== -1) { + window.clearTimeout(timeoutId); + } + }; + const reFetch = () => + window.setTimeout(async () => { + iterationTryOfFetchingPrePackagedCount = + iterationTryOfFetchingPrePackagedCount + 1; + const prePackagedRuleStatusResponse = await getPrePackagedRulesStatus({ + signal: abortCtrl.signal, + }); + if ( + isSubscribed && + ((prePackagedRuleStatusResponse.rules_not_installed === 0 && + prePackagedRuleStatusResponse.rules_not_updated === 0) || + iterationTryOfFetchingPrePackagedCount > 100) + ) { + setLoadingCreatePrePackagedRules(false); + setRuleStatus({ + createPrePackagedRules: createElasticRules, + refetchPrePackagedRulesStatus: fetchPrePackagedRules, + rulesCustomInstalled: prePackagedRuleStatusResponse.rules_custom_installed, + rulesInstalled: prePackagedRuleStatusResponse.rules_installed, + rulesNotInstalled: prePackagedRuleStatusResponse.rules_not_installed, + rulesNotUpdated: prePackagedRuleStatusResponse.rules_not_updated, + }); + displaySuccessToast(i18n.RULE_PREPACKAGED_SUCCESS, dispatchToaster); + stopTimeOut(); + resolve(true); + } else { + timeoutId = reFetch(); + } + }, 300); + timeoutId = reFetch(); + } + } + } catch (error) { + if (isSubscribed) { + setLoadingCreatePrePackagedRules(false); + errorToToaster({ title: i18n.RULE_PREPACKAGED_FAILURE, error, dispatchToaster }); + resolve(false); + } + } + }); + }; + + fetchPrePackagedRules(); + + return () => { + isSubscribed = false; + abortCtrl.abort(); + }; + }, [canUserCRUD, hasIndexWrite, hasManageApiKey, isAuthenticated, isSignalIndexExists]); + + return { + loading, + loadingCreatePrePackagedRules, + ...rulesStatus, + }; +}; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.tsx index b49dd8d51d4f75..af6e437255acdd 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useEffect, useState } from 'react'; +import { useEffect, useState, useRef } from 'react'; import { FetchRulesResponse, FilterOptions, PaginationOptions } from './types'; import { useStateToaster } from '../../../components/toasters'; @@ -12,36 +12,33 @@ import { fetchRules } from './api'; import { errorToToaster } from '../../../components/ml/api/error_to_toaster'; import * as i18n from './translations'; -type Return = [boolean, FetchRulesResponse]; +type Func = () => void; +type Return = [boolean, FetchRulesResponse, Func | null]; /** * Hook for using the list of Rules from the Detection Engine API * * @param pagination desired pagination options (e.g. page/perPage) * @param filterOptions desired filters (e.g. filter/sortField/sortOrder) - * @param refetchToggle toggle for refetching data */ -export const useRules = ( - pagination: PaginationOptions, - filterOptions: FilterOptions, - refetchToggle: boolean -): Return => { +export const useRules = (pagination: PaginationOptions, filterOptions: FilterOptions): Return => { const [rules, setRules] = useState({ page: 1, perPage: 20, total: 0, data: [], }); + const reFetchRules = useRef(null); const [loading, setLoading] = useState(true); const [, dispatchToaster] = useStateToaster(); useEffect(() => { let isSubscribed = true; const abortCtrl = new AbortController(); - setLoading(true); - async function fetchData() { + async function fetchData(forceReload: boolean = false) { try { + setLoading(true); const fetchRulesResult = await fetchRules({ filterOptions, pagination, @@ -62,18 +59,21 @@ export const useRules = ( } fetchData(); + reFetchRules.current = fetchData.bind(null, true); return () => { isSubscribed = false; abortCtrl.abort(); }; }, [ - refetchToggle, pagination.page, pagination.perPage, filterOptions.filter, filterOptions.sortField, filterOptions.sortOrder, + filterOptions.tags?.sort().join(), + filterOptions.showCustomRules, + filterOptions.showElasticRules, ]); - return [loading, rules]; + return [loading, rules, reFetchRules.current]; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_tags.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_tags.tsx new file mode 100644 index 00000000000000..1c961d530422a5 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_tags.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useEffect, useState } from 'react'; +import { useStateToaster } from '../../../components/toasters'; +import { fetchTags } from './api'; +import { errorToToaster } from '../../../components/ml/api/error_to_toaster'; +import * as i18n from './translations'; + +type Return = [boolean, string[]]; + +/** + * Hook for using the list of Tags from the Detection Engine API + * + */ +export const useTags = (): Return => { + const [tags, setTags] = useState([]); + const [loading, setLoading] = useState(true); + const [, dispatchToaster] = useStateToaster(); + + useEffect(() => { + let isSubscribed = true; + const abortCtrl = new AbortController(); + + async function fetchData() { + setLoading(true); + try { + const fetchTagsResult = await fetchTags({ + signal: abortCtrl.signal, + }); + + if (isSubscribed) { + setTags(fetchTagsResult); + } + } catch (error) { + if (isSubscribed) { + errorToToaster({ title: i18n.TAG_FETCH_FAILURE, error, dispatchToaster }); + } + } + if (isSubscribed) { + setLoading(false); + } + } + + fetchData(); + + return () => { + isSubscribed = false; + abortCtrl.abort(); + }; + }, []); + + return [loading, tags]; +}; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.tsx index 7d0e331200d55e..b93009c8ce2c28 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_privilege_user.tsx @@ -24,10 +24,14 @@ interface Return { */ export const usePrivilegeUser = (): Return => { const [loading, setLoading] = useState(true); - const [isAuthenticated, setAuthenticated] = useState(null); - const [hasIndexManage, setHasIndexManage] = useState(null); - const [hasIndexWrite, setHasIndexWrite] = useState(null); - const [hasManageApiKey, setHasManageApiKey] = useState(null); + const [privilegeUser, setPrivilegeUser] = useState< + Pick + >({ + isAuthenticated: null, + hasIndexManage: null, + hasManageApiKey: null, + hasIndexWrite: null, + }); const [, dispatchToaster] = useStateToaster(); useEffect(() => { @@ -42,23 +46,31 @@ export const usePrivilegeUser = (): Return => { }); if (isSubscribed && privilege != null) { - setAuthenticated(privilege.is_authenticated); if (privilege.index != null && Object.keys(privilege.index).length > 0) { const indexName = Object.keys(privilege.index)[0]; - setHasIndexManage(privilege.index[indexName].manage); - setHasIndexWrite(privilege.index[indexName].write); - setHasManageApiKey( - privilege.cluster.manage_security || + setPrivilegeUser({ + isAuthenticated: privilege.is_authenticated, + hasIndexManage: privilege.index[indexName].manage, + hasIndexWrite: + privilege.index[indexName].create || + privilege.index[indexName].create_doc || + privilege.index[indexName].index || + privilege.index[indexName].write, + hasManageApiKey: + privilege.cluster.manage_security || privilege.cluster.manage_api_key || - privilege.cluster.manage_own_api_key - ); + privilege.cluster.manage_own_api_key, + }); } } } catch (error) { if (isSubscribed) { - setAuthenticated(false); - setHasIndexManage(false); - setHasIndexWrite(false); + setPrivilegeUser({ + isAuthenticated: false, + hasIndexManage: false, + hasManageApiKey: false, + hasIndexWrite: false, + }); errorToToaster({ title: i18n.PRIVILEGE_FETCH_FAILURE, error, dispatchToaster }); } } @@ -74,5 +86,5 @@ export const usePrivilegeUser = (): Return => { }; }, []); - return { loading, isAuthenticated, hasIndexManage, hasManageApiKey, hasIndexWrite }; + return { loading, ...privilegeUser }; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_query.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_query.tsx index fa88a84fb11871..3dc6bac07be341 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_query.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/signals/use_query.tsx @@ -9,11 +9,16 @@ import React, { SetStateAction, useEffect, useState } from 'react'; import { fetchQuerySignals } from './api'; import { SignalSearchResponse } from './types'; -type Return = [ - boolean, - SignalSearchResponse | null, - React.Dispatch> -]; +type Func = () => void; + +interface Return { + loading: boolean; + data: SignalSearchResponse | null; + setQuery: React.Dispatch>; + response: string; + request: string; + refetch: Func | null; +} /** * Hook for using to get a Signals from the Detection Engine API @@ -21,9 +26,20 @@ type Return = [ * @param initialQuery query dsl object * */ -export const useQuerySignals = (initialQuery: object): Return => { +export const useQuerySignals = ( + initialQuery: object, + indexName?: string | null +): Return => { const [query, setQuery] = useState(initialQuery); - const [signals, setSignals] = useState | null>(null); + const [signals, setSignals] = useState< + Pick, 'data' | 'setQuery' | 'response' | 'request' | 'refetch'> + >({ + data: null, + response: '', + request: '', + setQuery, + refetch: null, + }); const [loading, setLoading] = useState(true); useEffect(() => { @@ -39,11 +55,23 @@ export const useQuerySignals = (initialQuery: object): Return(initialQuery: object): Return void; -type Return = [boolean, boolean | null, string | null, Func | null]; +interface Return { + loading: boolean; + signalIndexExists: boolean | null; + signalIndexName: string | null; + createDeSignalIndex: Func | null; +} /** * Hook for managing signal index @@ -23,9 +28,13 @@ type Return = [boolean, boolean | null, string | null, Func | null]; */ export const useSignalIndex = (): Return => { const [loading, setLoading] = useState(true); - const [signalIndexName, setSignalIndexName] = useState(null); - const [signalIndexExists, setSignalIndexExists] = useState(null); - const createDeSignalIndex = useRef(null); + const [signalIndex, setSignalIndex] = useState< + Pick + >({ + signalIndexExists: null, + signalIndexName: null, + createDeSignalIndex: null, + }); const [, dispatchToaster] = useStateToaster(); useEffect(() => { @@ -38,13 +47,19 @@ export const useSignalIndex = (): Return => { const signal = await getSignalIndex({ signal: abortCtrl.signal }); if (isSubscribed && signal != null) { - setSignalIndexName(signal.name); - setSignalIndexExists(true); + setSignalIndex({ + signalIndexExists: true, + signalIndexName: signal.name, + createDeSignalIndex: createIndex, + }); } } catch (error) { if (isSubscribed) { - setSignalIndexName(null); - setSignalIndexExists(false); + setSignalIndex({ + signalIndexExists: false, + signalIndexName: null, + createDeSignalIndex: createIndex, + }); if (error instanceof SignalIndexError && error.statusCode !== 404) { errorToToaster({ title: i18n.SIGNAL_GET_NAME_FAILURE, error, dispatchToaster }); } @@ -70,8 +85,11 @@ export const useSignalIndex = (): Return => { if (error instanceof PostSignalError && error.statusCode === 409) { fetchData(); } else { - setSignalIndexName(null); - setSignalIndexExists(false); + setSignalIndex({ + signalIndexExists: false, + signalIndexName: null, + createDeSignalIndex: createIndex, + }); errorToToaster({ title: i18n.SIGNAL_POST_FAILURE, error, dispatchToaster }); } } @@ -82,12 +100,11 @@ export const useSignalIndex = (): Return => { }; fetchData(); - createDeSignalIndex.current = createIndex; return () => { isSubscribed = false; abortCtrl.abort(); }; }, []); - return [loading, signalIndexExists, signalIndexName, createDeSignalIndex.current]; + return { loading, ...signalIndex }; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.gql_query.ts index 76f061a0a33d0b..6f17bf6915aa45 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.gql_query.ts @@ -31,7 +31,8 @@ export const overviewHostQuery = gql` endgameRegistry endgameSecurity filebeatSystemModule - winlogbeat + winlogbeatSecurity + winlogbeatMWSysmonOperational inspect @include(if: $inspect) { dsl response diff --git a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx index e995d123b1b44c..0336e4a9a977b9 100644 --- a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx @@ -89,7 +89,8 @@ export const WithSource = React.memo(({ children, indexToAdd, s return [...configIndex, ...indexToAdd]; } return configIndex; - }, [configIndex, DEFAULT_INDEX_KEY, indexToAdd]); + }, [configIndex, indexToAdd]); + return ( query={sourceQuery} diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx index 97f007452854ca..f4eb088b6ad94c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx @@ -4,13 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getOr, isEmpty } from 'lodash/fp'; +import { getOr } from 'lodash/fp'; import memoizeOne from 'memoize-one'; import React from 'react'; import { Query } from 'react-apollo'; import { compose } from 'redux'; import { connect } from 'react-redux'; +import { IIndexPattern } from '../../../../../../../src/plugins/data/common/index_patterns'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetTimelineQuery, @@ -23,9 +24,8 @@ import { inputsModel, inputsSelectors, State } from '../../store'; import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { createFilter } from '../helpers'; import { QueryTemplate, QueryTemplateProps } from '../query_template'; - +import { EventType } from '../../store/timeline/model'; import { timelineQuery } from './index.gql_query'; -import { IIndexPattern } from '../../../../../../../src/plugins/data/common/index_patterns'; export interface TimelineArgs { events: TimelineItem[]; @@ -45,6 +45,7 @@ export interface TimelineQueryReduxProps { export interface OwnProps extends QueryTemplateProps { children?: (args: TimelineArgs) => React.ReactNode; + eventType?: EventType; id: string; indexPattern?: IIndexPattern; indexToAdd?: string[]; @@ -70,6 +71,7 @@ class TimelineQueryComponent extends QueryTemplate< public render() { const { children, + eventType = 'raw', id, indexPattern, indexToAdd = [], @@ -82,9 +84,13 @@ class TimelineQueryComponent extends QueryTemplate< sortField, } = this.props; const defaultKibanaIndex = kibana.services.uiSettings.get(DEFAULT_INDEX_KEY); - const defaultIndex = isEmpty(indexPattern) - ? [...defaultKibanaIndex, ...indexToAdd] - : indexPattern?.title.split(',') ?? []; + const defaultIndex = + indexPattern == null || (indexPattern != null && indexPattern.title === '') + ? [ + ...(['all', 'raw'].includes(eventType) ? defaultKibanaIndex : []), + ...(['all', 'signal'].includes(eventType) ? indexToAdd : []), + ] + : indexPattern?.title.split(',') ?? []; const variables: GetTimelineQuery.Variables = { fieldRequested: fields, filterQuery: createFilter(filterQuery), diff --git a/x-pack/legacy/plugins/siem/public/graphql/introspection.json b/x-pack/legacy/plugins/siem/public/graphql/introspection.json index 7b9842fa2c2bce..a9247403bf22c3 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/introspection.json +++ b/x-pack/legacy/plugins/siem/public/graphql/introspection.json @@ -4940,7 +4940,7 @@ "deprecationReason": null }, { - "name": "threats", + "name": "threat", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "ToAny", "ofType": null }, @@ -9291,7 +9291,15 @@ "deprecationReason": null }, { - "name": "winlogbeat", + "name": "winlogbeatSecurity", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "winlogbeatMWSysmonOperational", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, diff --git a/x-pack/legacy/plugins/siem/public/graphql/types.ts b/x-pack/legacy/plugins/siem/public/graphql/types.ts index b13e295a8e1683..6a24ffcc130204 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/public/graphql/types.ts @@ -1015,7 +1015,7 @@ export interface RuleField { tags?: Maybe; - threats?: Maybe; + threat?: Maybe; type?: Maybe; @@ -1847,7 +1847,9 @@ export interface OverviewHostData { filebeatSystemModule?: Maybe; - winlogbeat?: Maybe; + winlogbeatSecurity?: Maybe; + + winlogbeatMWSysmonOperational?: Maybe; inspect?: Maybe; } @@ -4029,7 +4031,9 @@ export namespace GetOverviewHostQuery { filebeatSystemModule: Maybe; - winlogbeat: Maybe; + winlogbeatSecurity: Maybe; + + winlogbeatMWSysmonOperational: Maybe; inspect: Maybe; }; diff --git a/x-pack/legacy/plugins/siem/public/lib/telemetry/index.ts b/x-pack/legacy/plugins/siem/public/lib/telemetry/index.ts new file mode 100644 index 00000000000000..856b7783a53678 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/lib/telemetry/index.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { METRIC_TYPE, UiStatsMetricType } from '@kbn/analytics'; + +import { SetupPlugins } from '../../plugin'; +export { telemetryMiddleware } from './middleware'; + +export { METRIC_TYPE }; + +type TrackFn = (type: UiStatsMetricType, event: string | string[], count?: number) => void; + +let _track: TrackFn; + +export const track: TrackFn = (type, event, count) => { + try { + _track(type, event, count); + } catch (error) { + // ignore failed tracking call + } +}; + +export const initTelemetry = (usageCollection: SetupPlugins['usageCollection'], appId: string) => { + try { + _track = usageCollection.reportUiStats.bind(null, appId); + } catch (error) { + // ignore failed setup here, as we'll just have an inert tracker + } +}; + +export enum TELEMETRY_EVENT { + // Detections + SIEM_RULE_ENABLED = 'siem_rule_enabled', + SIEM_RULE_DISABLED = 'siem_rule_disabled', + CUSTOM_RULE_ENABLED = 'custom_rule_enabled', + CUSTOM_RULE_DISABLED = 'custom_rule_disabled', + + // ML + SIEM_JOB_ENABLED = 'siem_job_enabled', + SIEM_JOB_DISABLED = 'siem_job_disabled', + CUSTOM_JOB_ENABLED = 'custom_job_enabled', + CUSTOM_JOB_DISABLED = 'custom_job_disabled', + JOB_ENABLE_FAILURE = 'job_enable_failure', + JOB_DISABLE_FAILURE = 'job_disable_failure', + + // Timeline + TIMELINE_OPENED = 'open_timeline', + TIMELINE_SAVED = 'timeline_saved', + TIMELINE_NAMED = 'timeline_named', + + // UI Interactions + TAB_CLICKED = 'tab_', +} diff --git a/x-pack/legacy/plugins/siem/public/lib/telemetry/middleware.ts b/x-pack/legacy/plugins/siem/public/lib/telemetry/middleware.ts new file mode 100644 index 00000000000000..59c6cb35669070 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/lib/telemetry/middleware.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Action, Dispatch, MiddlewareAPI } from 'redux'; + +import { track, METRIC_TYPE, TELEMETRY_EVENT } from './'; +import { timelineActions } from '../../store/actions'; + +export const telemetryMiddleware = (api: MiddlewareAPI) => (next: Dispatch) => (action: Action) => { + if (timelineActions.endTimelineSaving.match(action)) { + track(METRIC_TYPE.COUNT, TELEMETRY_EVENT.TIMELINE_SAVED); + } else if (timelineActions.updateTitle.match(action)) { + track(METRIC_TYPE.COUNT, TELEMETRY_EVENT.TIMELINE_NAMED); + } else if (timelineActions.showTimeline.match(action)) { + if (action.payload.show) { + track(METRIC_TYPE.LOADED, TELEMETRY_EVENT.TIMELINE_OPENED); + } + } + + return next(action); +}; diff --git a/x-pack/legacy/plugins/siem/public/lib/track_usage/index.ts b/x-pack/legacy/plugins/siem/public/lib/track_usage/index.ts deleted file mode 100644 index 47277653c816fe..00000000000000 --- a/x-pack/legacy/plugins/siem/public/lib/track_usage/index.ts +++ /dev/null @@ -1,31 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -// @ts-ignore -import { - createUiStatsReporter, - METRIC_TYPE, -} from '../../../../../../../src/legacy/core_plugins/ui_metric/public'; -import { APP_ID } from '../../../common/constants'; - -export const trackUiAction = createUiStatsReporter(APP_ID); -export { METRIC_TYPE }; - -export enum TELEMETRY_EVENT { - // ML - SIEM_JOB_ENABLED = 'siem_job_enabled', - SIEM_JOB_DISABLED = 'siem_job_disabled', - CUSTOM_JOB_ENABLED = 'custom_job_enabled', - CUSTOM_JOB_DISABLED = 'custom_job_disabled', - JOB_ENABLE_FAILURE = 'job_enable_failure', - JOB_DISABLE_FAILURE = 'job_disable_failure', - - // Timeline - TIMELINE_OPENED = 'open_timeline', - - // UI Interactions - TAB_CLICKED = 'tab_', -} diff --git a/x-pack/legacy/plugins/siem/public/mock/news.ts b/x-pack/legacy/plugins/siem/public/mock/news.ts new file mode 100644 index 00000000000000..3e421ce19ae9c5 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/mock/news.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { RawNewsApiResponse } from '../components/news_feed/types'; + +/** A (typed) sample raw API response from a news feed */ +export const rawNewsApiResponse: RawNewsApiResponse = { + items: [ + { + title: { en: 'Got SIEM Questions?' }, + description: { + en: + "There's an awesome community of Elastic SIEM users out there. Join the discussion about configuring, learning, and using the Elastic SIEM app, and detecting threats!", + }, + link_text: null, + link_url: { en: 'https://discuss.elastic.co/c/siem?blade=securitysolutionfeed' }, + languages: null, + badge: { en: '7.6' }, + image_url: { + en: + 'https://aws1.discourse-cdn.com/elastic/original/3X/f/8/f8c3d0b9971cfcd0be349d973aa5799f71d280cc.png?blade=securitysolutionfeed', + }, + publish_on: new Date('2020-01-01T00:00:00'), + expire_on: new Date('2020-12-31T00:00:00'), + hash: '5a35c984a9cdc1c6a25913f3d0b99b1aefc7257bc3b936c39db9fa0435edeed0', + }, + { + title: { en: 'Elastic Security 7.5.0 released' }, + description: { + en: + 'Elastic Security combines the threat hunting and analytics of Elastic SIEM with the prevention and response provided by Elastic Endpoint Security.', + }, + link_text: null, + link_url: { + en: + 'https://www.elastic.co/blog/elastic-security-7-5-0-released?blade=securitysolutionfeed', + }, + languages: null, + badge: { en: '7.5' }, + image_url: { + en: + 'https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1caa35177420c61b/5d0d0394d8ff351753cbf2c5/illustrated-screenshot-hero-siem.png?blade=securitysolutionfeed', + }, + publish_on: new Date('2019-12-02T00:00:00'), + expire_on: new Date('2020-12-31T00:00:00'), + hash: 'edcb2d396ffdd80bfd5a97fbc0dc9f4b73477f9be556863fe0a1caf086679420', + }, + { + title: { en: 'Elastic Endpoint Security Overview Webinar' }, + description: { + en: + 'At Elastic, we’re bringing endpoint protection and SIEM together into the same experience to streamline how you secure your organization.', + }, + link_text: null, + link_url: { + en: + 'https://www.elastic.co/webinars/elastic-endpoint-security-overview-security-starts-at-the-endpoint?blade=securitysolutionfeed', + }, + languages: null, + badge: { en: '7.5' }, + image_url: { + en: + 'https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd0eb8689eafe398a/5d970ecc1970e80e85277925/illustration-endpoint-hero.png?blade=securitysolutionfeed', + }, + publish_on: new Date('2019-11-17T00:00:00'), + expire_on: new Date('2020-12-31T00:00:00'), + hash: 'ec970adc85e9eede83f77e4cc6a6fea00cd7822cbe48a71dc2c5f1df10939196', + }, + { + title: { en: 'Trying Elastic SIEM at Home?' }, + description: { + en: + 'For small businesses and homes, having access to effective security analytics can come at a high cost of either time or money. Well, until now!', + }, + link_text: null, + link_url: { + en: + 'https://www.elastic.co/blog/elastic-siem-for-small-business-and-home-1-getting-started?blade=securitysolutionfeed', + }, + languages: null, + badge: { en: '7.5' }, + image_url: { + en: + 'https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt024c26b7636cb24f/5daf4e293a326d6df6c0e025/home-siem-blog-1-map.jpg?blade=securitysolutionfeed', + }, + publish_on: new Date('2019-10-24T00:00:00'), + expire_on: new Date('2020-12-31T00:00:00'), + hash: 'aa243fd5845356a5ccd54a7a11b208ed307e0d88158873b1fcf7d1164b739bac', + }, + { + title: { en: 'Introducing Elastic Endpoint Security' }, + description: { + en: + 'Elastic is excited to announce the introduction of Elastic Endpoint Security, based on Elastic’s acquisition of Endgame, a pioneer and industry-recognized leader in endpoint threat prevention, detection, and response.', + }, + link_text: null, + link_url: { + en: + 'https://www.elastic.co/blog/introducing-elastic-endpoint-security?blade=securitysolutionfeed', + }, + languages: null, + badge: { en: '7.5' }, + image_url: { + en: + 'https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt1f87637fb7870298/5d9fe27bf8ca980f8717f6f8/screenshot-resolver-trickbot-enrichments-showing-defender-shutdown-endgame-2-optimized.png?blade=securitysolutionfeed', + }, + publish_on: new Date('2019-10-15T00:00:00'), + expire_on: new Date('2020-03-01T00:00:00'), + hash: '3c64576c9749d33ff98726d641cdf2fb2bfde3dd9a6f99ff2573ac8d8c5b2c02', + }, + { + title: { en: 'What is Elastic Common Schema (ECS)?' }, + description: { + en: + 'Elastic SIEM is powered by Elastic Common Schema. With ECS, analytics content such as dashboards, rules, and machine learning jobs can be applied more broadly, searches can be crafted more narrowly, and field names are easier to remember.', + }, + link_text: null, + link_url: { + en: + 'https://www.elastic.co/blog/introducing-the-elastic-common-schema?blade=securitysolutionfeed', + }, + languages: null, + badge: { en: '7.0' }, + image_url: { + en: + 'https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt71256f06dc672546/5c98d595975fd58f4d12646d/ecs-intro-dashboard-1360.jpg?blade=securitysolutionfeed', + }, + publish_on: new Date('2019-02-13T00:00:00'), + expire_on: new Date('2020-12-31T00:00:00'), + hash: 'b8a0d3d21e9638bde891ab5eb32594b3d7a3daacc7f0900c6dd506d5d7b42410', + }, + ], +}; diff --git a/x-pack/legacy/plugins/siem/public/mock/raw_news.ts b/x-pack/legacy/plugins/siem/public/mock/raw_news.ts new file mode 100644 index 00000000000000..85bef15a41b230 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/mock/raw_news.ts @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** A raw JSON response from a news feed */ +export const rawNewsJSON = ` +{ + "items":[ + { + "title":{ + "en":"Got SIEM Questions?" + }, + "description":{ + "en":"There's an awesome community of Elastic SIEM users out there. Join the discussion about configuring, learning, and using the Elastic SIEM app, and detecting threats!" + }, + "link_text":null, + "link_url":{ + "en":"https://discuss.elastic.co/c/siem?blade=securitysolutionfeed" + }, + "languages":null, + "badge":{ + "en":"7.6" + }, + "image_url":{ + "en":"https://aws1.discourse-cdn.com/elastic/original/3X/f/8/f8c3d0b9971cfcd0be349d973aa5799f71d280cc.png?blade=securitysolutionfeed" + }, + "publish_on":"2020-01-01T00:00:00", + "expire_on":"2020-12-31T00:00:00", + "hash":"5a35c984a9cdc1c6a25913f3d0b99b1aefc7257bc3b936c39db9fa0435edeed0" + }, + { + "title":{ + "en":"Elastic Security 7.5.0 released" + }, + "description":{ + "en":"Elastic Security combines the threat hunting and analytics of Elastic SIEM with the prevention and response provided by Elastic Endpoint Security." + }, + "link_text":null, + "link_url":{ + "en":"https://www.elastic.co/blog/elastic-security-7-5-0-released?blade=securitysolutionfeed" + }, + "languages":null, + "badge":{ + "en":"7.5" + }, + "image_url":{ + "en":"https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1caa35177420c61b/5d0d0394d8ff351753cbf2c5/illustrated-screenshot-hero-siem.png?blade=securitysolutionfeed" + }, + "publish_on":"2019-12-02T00:00:00", + "expire_on":"2020-12-31T00:00:00", + "hash":"edcb2d396ffdd80bfd5a97fbc0dc9f4b73477f9be556863fe0a1caf086679420" + }, + { + "title":{ + "en":"Elastic Endpoint Security Overview Webinar" + }, + "description":{ + "en":"At Elastic, we’re bringing endpoint protection and SIEM together into the same experience to streamline how you secure your organization." + }, + "link_text":null, + "link_url":{ + "en":"https://www.elastic.co/webinars/elastic-endpoint-security-overview-security-starts-at-the-endpoint?blade=securitysolutionfeed" + }, + "languages":null, + "badge":{ + "en":"7.5" + }, + "image_url":{ + "en":"https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd0eb8689eafe398a/5d970ecc1970e80e85277925/illustration-endpoint-hero.png?blade=securitysolutionfeed" + }, + "publish_on":"2019-11-17T00:00:00", + "expire_on":"2020-12-31T00:00:00", + "hash":"ec970adc85e9eede83f77e4cc6a6fea00cd7822cbe48a71dc2c5f1df10939196" + }, + { + "title":{ + "en":"Trying Elastic SIEM at Home?" + }, + "description":{ + "en":"For small businesses and homes, having access to effective security analytics can come at a high cost of either time or money. Well, until now!" + }, + "link_text":null, + "link_url":{ + "en":"https://www.elastic.co/blog/elastic-siem-for-small-business-and-home-1-getting-started?blade=securitysolutionfeed" + }, + "languages":null, + "badge":{ + "en":"7.5" + }, + "image_url":{ + "en":"https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt024c26b7636cb24f/5daf4e293a326d6df6c0e025/home-siem-blog-1-map.jpg?blade=securitysolutionfeed" + }, + "publish_on":"2019-10-24T00:00:00", + "expire_on":"2020-12-31T00:00:00", + "hash":"aa243fd5845356a5ccd54a7a11b208ed307e0d88158873b1fcf7d1164b739bac" + }, + { + "title":{ + "en":"Introducing Elastic Endpoint Security" + }, + "description":{ + "en":"Elastic is excited to announce the introduction of Elastic Endpoint Security, based on Elastic’s acquisition of Endgame, a pioneer and industry-recognized leader in endpoint threat prevention, detection, and response." + }, + "link_text":null, + "link_url":{ + "en":"https://www.elastic.co/blog/introducing-elastic-endpoint-security?blade=securitysolutionfeed" + }, + "languages":null, + "badge":{ + "en":"7.5" + }, + "image_url":{ + "en":"https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt1f87637fb7870298/5d9fe27bf8ca980f8717f6f8/screenshot-resolver-trickbot-enrichments-showing-defender-shutdown-endgame-2-optimized.png?blade=securitysolutionfeed" + }, + "publish_on":"2019-10-15T00:00:00", + "expire_on":"2020-03-01T00:00:00", + "hash":"3c64576c9749d33ff98726d641cdf2fb2bfde3dd9a6f99ff2573ac8d8c5b2c02" + }, + { + "title":{ + "en":"What is Elastic Common Schema (ECS)?" + }, + "description":{ + "en":"Elastic SIEM is powered by Elastic Common Schema. With ECS, analytics content such as dashboards, rules, and machine learning jobs can be applied more broadly, searches can be crafted more narrowly, and field names are easier to remember." + }, + "link_text":null, + "link_url":{ + "en":"https://www.elastic.co/blog/introducing-the-elastic-common-schema?blade=securitysolutionfeed" + }, + "languages":null, + "badge":{ + "en":"7.0" + }, + "image_url":{ + "en":"https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt71256f06dc672546/5c98d595975fd58f4d12646d/ecs-intro-dashboard-1360.jpg?blade=securitysolutionfeed" + }, + "publish_on":"2019-02-13T00:00:00", + "expire_on":"2020-12-31T00:00:00", + "hash":"b8a0d3d21e9638bde891ab5eb32594b3d7a3daacc7f0900c6dd506d5d7b42410" + } + ] +} +`; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/detection_engine_header_page/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/detection_engine_header_page/index.tsx new file mode 100644 index 00000000000000..c9450739190139 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/detection_engine_header_page/index.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; + +import { HeaderPage, HeaderPageProps } from '../../../../components/header_page'; +import * as i18n from './translations'; + +const DetectionEngineHeaderPageComponent: React.FC = props => ( + +); + +DetectionEngineHeaderPageComponent.defaultProps = { + badgeOptions: { + beta: true, + text: i18n.PAGE_BADGE_LABEL, + tooltip: i18n.PAGE_BADGE_TOOLTIP, + }, +}; + +export const DetectionEngineHeaderPage = React.memo(DetectionEngineHeaderPageComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/detection_engine_header_page/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/detection_engine_header_page/translations.ts new file mode 100644 index 00000000000000..303431a559e8f3 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/detection_engine_header_page/translations.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const PAGE_BADGE_LABEL = i18n.translate( + 'xpack.siem.detectionEngine.headerPage.pageBadgeLabel', + { + defaultMessage: 'Beta', + } +); + +export const PAGE_BADGE_TOOLTIP = i18n.translate( + 'xpack.siem.detectionEngine.headerPage.pageBadgeTooltip', + { + defaultMessage: + 'Detections is still in beta. Please help us improve by reporting issues or bugs in the Kibana repo.', + } +); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.tsx index 4701ed93dc4f0a..a33efeda2196b5 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.tsx @@ -151,11 +151,25 @@ export const sendSignalToTimelineAction = async ({ updateTimelineIsLoading({ id: 'timeline-1', isLoading: false }); } } else { - const query = `_id: ${ecsData._id}`; createTimeline({ from, timeline: { ...timelineDefaults, + dataProviders: [ + { + and: [], + id: `send-signal-to-timeline-action-default-draggable-event-details-value-formatted-field-value-timeline-1-signal-id-${ecsData._id}`, + name: ecsData._id, + enabled: true, + excluded: false, + kqlQuery: '', + queryMatch: { + field: '_id', + value: ecsData._id, + operator: ':', + }, + }, + ], id: 'timeline-1', dateRange: { start: from, @@ -166,13 +180,13 @@ export const sendSignalToTimelineAction = async ({ filterQuery: { kuery: { kind: 'kuery', - expression: query, + expression: '', }, - serializedQuery: convertKueryToElasticSearchQuery(query), + serializedQuery: '', }, filterQueryDraft: { kind: 'kuery', - expression: query, + expression: '', }, }, }, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx index e00dfa5b844739..f5d138a3afcb8c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx @@ -90,19 +90,26 @@ export const signalsHeaders: ColumnHeader[] = [ columnHeaderType: defaultColumnHeaderType, id: 'signal.rule.name', label: i18n.SIGNALS_HEADERS_RULE, + linkField: 'signal.rule.id', width: DEFAULT_COLUMN_MIN_WIDTH, }, + { + columnHeaderType: defaultColumnHeaderType, + id: 'signal.rule.version', + label: i18n.SIGNALS_HEADERS_VERSION, + width: 100, + }, { columnHeaderType: defaultColumnHeaderType, id: 'signal.rule.type', label: i18n.SIGNALS_HEADERS_METHOD, - width: 80, + width: 100, }, { columnHeaderType: defaultColumnHeaderType, id: 'signal.rule.severity', label: i18n.SIGNALS_HEADERS_SEVERITY, - width: 80, + width: 100, }, { columnHeaderType: defaultColumnHeaderType, @@ -141,7 +148,7 @@ export const signalsHeaders: ColumnHeader[] = [ { columnHeaderType: defaultColumnHeaderType, id: 'destination.ip', - width: 120, + width: 140, }, { columnHeaderType: defaultColumnHeaderType, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx index 6fd37215b9259b..e65adcf3a6920a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx @@ -20,8 +20,7 @@ import { DispatchUpdateTimeline } from '../../../../components/open_timeline/typ import { combineQueries } from '../../../../components/timeline/helpers'; import { TimelineNonEcsData } from '../../../../graphql/types'; import { useKibana } from '../../../../lib/kibana'; -import { inputsSelectors, State } from '../../../../store'; -import { InputsRange } from '../../../../store/inputs/model'; +import { inputsSelectors, State, inputsModel } from '../../../../store'; import { timelineActions, timelineSelectors } from '../../../../store/timeline'; import { timelineDefaults, TimelineModel } from '../../../../store/timeline/model'; import { useApolloClient } from '../../../../utils/apollo_context'; @@ -46,7 +45,7 @@ import { CreateTimelineProps, SetEventsDeletedProps, SetEventsLoadingProps, - UpdateSignalsStatus, + UpdateSignalsStatusCallback, UpdateSignalsStatusProps, } from './types'; import { dispatchUpdateTimeline } from '../../../../components/open_timeline/helpers'; @@ -92,247 +91,252 @@ interface OwnProps { type SignalsTableComponentProps = OwnProps & ReduxProps & DispatchProps; -export const SignalsTableComponent = React.memo( - ({ - canUserCRUD, - clearEventsDeleted, - clearEventsLoading, - clearSelected, - defaultFilters = [], - from, - globalFilters, - globalQuery, - hasIndexWrite, - isSelectAllChecked, - loading, - loadingEventIds, - selectedEventIds, - setEventsDeleted, - setEventsLoading, - signalsIndex, - to, - updateTimeline, - updateTimelineIsLoading, - }) => { - const [selectAll, setSelectAll] = useState(false); - const apolloClient = useApolloClient(); +const SignalsTableComponent: React.FC = ({ + canUserCRUD, + clearEventsDeleted, + clearEventsLoading, + clearSelected, + defaultFilters, + from, + globalFilters, + globalQuery, + hasIndexWrite, + isSelectAllChecked, + loading, + loadingEventIds, + selectedEventIds, + setEventsDeleted, + setEventsLoading, + signalsIndex, + to, + updateTimeline, + updateTimelineIsLoading, +}) => { + const [selectAll, setSelectAll] = useState(false); + const apolloClient = useApolloClient(); - const [showClearSelectionAction, setShowClearSelectionAction] = useState(false); - const [filterGroup, setFilterGroup] = useState(FILTER_OPEN); - const [{ browserFields, indexPatterns }] = useFetchIndexPatterns([signalsIndex]); - const kibana = useKibana(); + const [showClearSelectionAction, setShowClearSelectionAction] = useState(false); + const [filterGroup, setFilterGroup] = useState(FILTER_OPEN); + const [{ browserFields, indexPatterns }] = useFetchIndexPatterns( + signalsIndex !== '' ? [signalsIndex] : [] + ); + const kibana = useKibana(); - const getGlobalQuery = useCallback(() => { - if (browserFields != null && indexPatterns != null) { - return combineQueries({ - config: esQuery.getEsQueryConfig(kibana.services.uiSettings), - dataProviders: [], - indexPattern: indexPatterns, - browserFields, - filters: globalFilters, - kqlQuery: globalQuery, - kqlMode: globalQuery.language, - start: from, - end: to, - isEventViewer: true, - }); - } - return null; - }, [browserFields, globalFilters, globalQuery, indexPatterns, kibana, to, from]); - - // Callback for creating a new timeline -- utilized by row/batch actions - const createTimelineCallback = useCallback( - ({ from: fromTimeline, timeline, to: toTimeline }: CreateTimelineProps) => { - updateTimelineIsLoading({ id: 'timeline-1', isLoading: false }); - updateTimeline({ - duplicate: true, - from: fromTimeline, - id: 'timeline-1', - notes: [], - timeline: { - ...timeline, - show: true, - }, - to: toTimeline, - })(); - }, - [updateTimeline, updateTimelineIsLoading] - ); + const getGlobalQuery = useCallback(() => { + if (browserFields != null && indexPatterns != null) { + return combineQueries({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + dataProviders: [], + indexPattern: indexPatterns, + browserFields, + filters: globalFilters, + kqlQuery: globalQuery, + kqlMode: globalQuery.language, + start: from, + end: to, + isEventViewer: true, + }); + } + return null; + }, [browserFields, globalFilters, globalQuery, indexPatterns, kibana, to, from]); - const setEventsLoadingCallback = useCallback( - ({ eventIds, isLoading }: SetEventsLoadingProps) => { - setEventsLoading!({ id: SIGNALS_PAGE_TIMELINE_ID, eventIds, isLoading }); - }, - [setEventsLoading, SIGNALS_PAGE_TIMELINE_ID] - ); + // Callback for creating a new timeline -- utilized by row/batch actions + const createTimelineCallback = useCallback( + ({ from: fromTimeline, timeline, to: toTimeline }: CreateTimelineProps) => { + updateTimelineIsLoading({ id: 'timeline-1', isLoading: false }); + updateTimeline({ + duplicate: true, + from: fromTimeline, + id: 'timeline-1', + notes: [], + timeline: { + ...timeline, + show: true, + }, + to: toTimeline, + })(); + }, + [updateTimeline, updateTimelineIsLoading] + ); - const setEventsDeletedCallback = useCallback( - ({ eventIds, isDeleted }: SetEventsDeletedProps) => { - setEventsDeleted!({ id: SIGNALS_PAGE_TIMELINE_ID, eventIds, isDeleted }); - }, - [setEventsDeleted, SIGNALS_PAGE_TIMELINE_ID] - ); + const setEventsLoadingCallback = useCallback( + ({ eventIds, isLoading }: SetEventsLoadingProps) => { + setEventsLoading!({ id: SIGNALS_PAGE_TIMELINE_ID, eventIds, isLoading }); + }, + [setEventsLoading, SIGNALS_PAGE_TIMELINE_ID] + ); - // Catches state change isSelectAllChecked->false upon user selection change to reset utility bar - useEffect(() => { - if (!isSelectAllChecked) { - setShowClearSelectionAction(false); - } else { - setSelectAll(false); - } - }, [isSelectAllChecked]); + const setEventsDeletedCallback = useCallback( + ({ eventIds, isDeleted }: SetEventsDeletedProps) => { + setEventsDeleted!({ id: SIGNALS_PAGE_TIMELINE_ID, eventIds, isDeleted }); + }, + [setEventsDeleted, SIGNALS_PAGE_TIMELINE_ID] + ); - // Callback for when open/closed filter changes - const onFilterGroupChangedCallback = useCallback( - (newFilterGroup: SignalFilterOption) => { - clearEventsLoading!({ id: SIGNALS_PAGE_TIMELINE_ID }); - clearEventsDeleted!({ id: SIGNALS_PAGE_TIMELINE_ID }); - clearSelected!({ id: SIGNALS_PAGE_TIMELINE_ID }); - setFilterGroup(newFilterGroup); - }, - [clearEventsLoading, clearEventsDeleted, clearSelected, setFilterGroup] - ); + // Catches state change isSelectAllChecked->false upon user selection change to reset utility bar + useEffect(() => { + if (!isSelectAllChecked) { + setShowClearSelectionAction(false); + } else { + setSelectAll(false); + } + }, [isSelectAllChecked]); - // Callback for clearing entire selection from utility bar - const clearSelectionCallback = useCallback(() => { + // Callback for when open/closed filter changes + const onFilterGroupChangedCallback = useCallback( + (newFilterGroup: SignalFilterOption) => { + clearEventsLoading!({ id: SIGNALS_PAGE_TIMELINE_ID }); + clearEventsDeleted!({ id: SIGNALS_PAGE_TIMELINE_ID }); clearSelected!({ id: SIGNALS_PAGE_TIMELINE_ID }); - setSelectAll(false); - setShowClearSelectionAction(false); - }, [clearSelected, setSelectAll, setShowClearSelectionAction]); + setFilterGroup(newFilterGroup); + }, + [clearEventsLoading, clearEventsDeleted, clearSelected, setFilterGroup] + ); - // Callback for selecting all events on all pages from utility bar - // Dispatches to stateful_body's selectAll via TimelineTypeContext props - // as scope of response data required to actually set selectedEvents - const selectAllCallback = useCallback(() => { - setSelectAll(true); - setShowClearSelectionAction(true); - }, [setSelectAll, setShowClearSelectionAction]); + // Callback for clearing entire selection from utility bar + const clearSelectionCallback = useCallback(() => { + clearSelected!({ id: SIGNALS_PAGE_TIMELINE_ID }); + setSelectAll(false); + setShowClearSelectionAction(false); + }, [clearSelected, setSelectAll, setShowClearSelectionAction]); - const updateSignalsStatusCallback: UpdateSignalsStatus = useCallback( - async ({ signalIds, status }: UpdateSignalsStatusProps) => { - await updateSignalStatusAction({ - query: showClearSelectionAction ? getGlobalQuery()?.filterQuery : undefined, - signalIds: Object.keys(selectedEventIds), - status, - setEventsDeleted: setEventsDeletedCallback, - setEventsLoading: setEventsLoadingCallback, - }); - }, - [ - getGlobalQuery, - selectedEventIds, - setEventsDeletedCallback, - setEventsLoadingCallback, - showClearSelectionAction, - ] - ); + // Callback for selecting all events on all pages from utility bar + // Dispatches to stateful_body's selectAll via TimelineTypeContext props + // as scope of response data required to actually set selectedEvents + const selectAllCallback = useCallback(() => { + setSelectAll(true); + setShowClearSelectionAction(true); + }, [setSelectAll, setShowClearSelectionAction]); - // Callback for creating the SignalUtilityBar which receives totalCount from EventsViewer component - const utilityBarCallback = useCallback( - (totalCount: number) => { - return ( - 0} - clearSelection={clearSelectionCallback} - hasIndexWrite={hasIndexWrite} - isFilteredToOpen={filterGroup === FILTER_OPEN} - selectAll={selectAllCallback} - selectedEventIds={selectedEventIds} - showClearSelection={showClearSelectionAction} - totalCount={totalCount} - updateSignalsStatus={updateSignalsStatusCallback} - /> - ); - }, - [ - canUserCRUD, - hasIndexWrite, - clearSelectionCallback, - filterGroup, - loadingEventIds.length, - selectAllCallback, - selectedEventIds, - showClearSelectionAction, - updateSignalsStatusCallback, - ] - ); + const updateSignalsStatusCallback: UpdateSignalsStatusCallback = useCallback( + async (refetchQuery: inputsModel.Refetch, { signalIds, status }: UpdateSignalsStatusProps) => { + await updateSignalStatusAction({ + query: showClearSelectionAction ? getGlobalQuery()?.filterQuery : undefined, + signalIds: Object.keys(selectedEventIds), + status, + setEventsDeleted: setEventsDeletedCallback, + setEventsLoading: setEventsLoadingCallback, + }); + refetchQuery(); + }, + [ + getGlobalQuery, + selectedEventIds, + setEventsDeletedCallback, + setEventsLoadingCallback, + showClearSelectionAction, + ] + ); - // Send to Timeline / Update Signal Status Actions for each table row - const additionalActions = useMemo( - () => - getSignalsActions({ - apolloClient, - canUserCRUD, - hasIndexWrite, - createTimeline: createTimelineCallback, - setEventsLoading: setEventsLoadingCallback, - setEventsDeleted: setEventsDeletedCallback, - status: filterGroup === FILTER_OPEN ? FILTER_CLOSED : FILTER_OPEN, - updateTimelineIsLoading, - }), - [ + // Callback for creating the SignalUtilityBar which receives totalCount from EventsViewer component + const utilityBarCallback = useCallback( + (refetchQuery: inputsModel.Refetch, totalCount: number) => { + return ( + 0} + clearSelection={clearSelectionCallback} + hasIndexWrite={hasIndexWrite} + isFilteredToOpen={filterGroup === FILTER_OPEN} + selectAll={selectAllCallback} + selectedEventIds={selectedEventIds} + showClearSelection={showClearSelectionAction} + totalCount={totalCount} + updateSignalsStatus={updateSignalsStatusCallback.bind(null, refetchQuery)} + /> + ); + }, + [ + canUserCRUD, + hasIndexWrite, + clearSelectionCallback, + filterGroup, + loadingEventIds.length, + selectAllCallback, + selectedEventIds, + showClearSelectionAction, + updateSignalsStatusCallback, + ] + ); + + // Send to Timeline / Update Signal Status Actions for each table row + const additionalActions = useMemo( + () => + getSignalsActions({ apolloClient, canUserCRUD, - createTimelineCallback, hasIndexWrite, - filterGroup, - setEventsLoadingCallback, - setEventsDeletedCallback, + createTimeline: createTimelineCallback, + setEventsLoading: setEventsLoadingCallback, + setEventsDeleted: setEventsDeletedCallback, + status: filterGroup === FILTER_OPEN ? FILTER_CLOSED : FILTER_OPEN, updateTimelineIsLoading, - ] - ); + }), + [ + apolloClient, + canUserCRUD, + createTimelineCallback, + hasIndexWrite, + filterGroup, + setEventsLoadingCallback, + setEventsDeletedCallback, + updateTimelineIsLoading, + ] + ); - const defaultIndices = useMemo(() => [signalsIndex], [signalsIndex]); - const defaultFiltersMemo = useMemo( - () => [ + const defaultIndices = useMemo(() => [signalsIndex], [signalsIndex]); + const defaultFiltersMemo = useMemo(() => { + if (isEmpty(defaultFilters)) { + return filterGroup === FILTER_OPEN ? signalsOpenFilters : signalsClosedFilters; + } else if (defaultFilters != null && !isEmpty(defaultFilters)) { + return [ ...defaultFilters, ...(filterGroup === FILTER_OPEN ? signalsOpenFilters : signalsClosedFilters), - ], - [defaultFilters, filterGroup] - ); + ]; + } + }, [defaultFilters, filterGroup]); - const timelineTypeContext = useMemo( - () => ({ - documentType: i18n.SIGNALS_DOCUMENT_TYPE, - footerText: i18n.TOTAL_COUNT_OF_SIGNALS, - loadingText: i18n.LOADING_SIGNALS, - queryFields: requiredFieldsForActions, - timelineActions: additionalActions, - title: i18n.SIGNALS_TABLE_TITLE, - selectAll: canUserCRUD ? selectAll : false, - }), - [additionalActions, canUserCRUD, selectAll] - ); + const timelineTypeContext = useMemo( + () => ({ + documentType: i18n.SIGNALS_DOCUMENT_TYPE, + footerText: i18n.TOTAL_COUNT_OF_SIGNALS, + loadingText: i18n.LOADING_SIGNALS, + queryFields: requiredFieldsForActions, + timelineActions: additionalActions, + title: i18n.SIGNALS_TABLE_TITLE, + selectAll: canUserCRUD ? selectAll : false, + }), + [additionalActions, canUserCRUD, selectAll] + ); - if (loading || isEmpty(signalsIndex)) { - return ( - - - - - ); - } + const headerFilterGroup = useMemo( + () => , + [onFilterGroupChangedCallback] + ); + if (loading || isEmpty(signalsIndex)) { return ( - - } - id={SIGNALS_PAGE_TIMELINE_ID} - start={from} - timelineTypeContext={timelineTypeContext} - utilityBar={utilityBarCallback} - /> + + + + ); } -); -SignalsTableComponent.displayName = 'SignalsTableComponent'; + return ( + + ); +}; const makeMapStateToProps = () => { const getTimeline = timelineSelectors.getTimelineByIdSelector(); @@ -342,9 +346,8 @@ const makeMapStateToProps = () => { getTimeline(state, SIGNALS_PAGE_TIMELINE_ID) ?? timelineDefaults; const { deletedEventIds, isSelectAllChecked, loadingEventIds, selectedEventIds } = timeline; - const globalInputs: InputsRange = getGlobalInputs(state); + const globalInputs: inputsModel.InputsRange = getGlobalInputs(state); const { query, filters } = globalInputs; - return { globalQuery: query, globalFilters: filters, @@ -386,4 +389,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateTimeline: dispatchUpdateTimeline(dispatch), }); -export const SignalsTable = connect(makeMapStateToProps, mapDispatchToProps)(SignalsTableComponent); +export const SignalsTable = connect( + makeMapStateToProps, + mapDispatchToProps +)(React.memo(SignalsTableComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts index c262f907c98763..c2807db1797808 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts @@ -53,6 +53,13 @@ export const SIGNALS_HEADERS_RULE = i18n.translate( } ); +export const SIGNALS_HEADERS_VERSION = i18n.translate( + 'xpack.siem.eventsViewer.signals.defaultHeaders.versionTitle', + { + defaultMessage: 'Version', + } +); + export const SIGNALS_HEADERS_METHOD = i18n.translate( 'xpack.siem.eventsViewer.signals.defaultHeaders.methodTitle', { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts index 2366a103492ec5..b3e7ed75cfb995 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts @@ -8,6 +8,7 @@ import ApolloClient from 'apollo-client'; import { Ecs } from '../../../../graphql/types'; import { TimelineModel } from '../../../../store/timeline/model'; +import { inputsModel } from '../../../../store'; export interface SetEventsLoadingProps { eventIds: string[]; @@ -24,6 +25,10 @@ export interface UpdateSignalsStatusProps { status: 'open' | 'closed'; } +export type UpdateSignalsStatusCallback = ( + refetchQuery: inputsModel.Refetch, + { signalIds, status }: UpdateSignalsStatusProps +) => void; export type UpdateSignalsStatus = ({ signalIds, status }: UpdateSignalsStatusProps) => void; export interface UpdateSignalStatusActionProps { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/config.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/config.ts index d475fd155ea25d..2c5a1ddd9a010b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/config.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/config.ts @@ -9,6 +9,7 @@ import { SignalsHistogramOption } from './types'; export const signalsHistogramOptions: SignalsHistogramOption[] = [ { text: 'signal.rule.risk_score', value: 'signal.rule.risk_score' }, { text: 'signal.rule.severity', value: 'signal.rule.severity' }, + { text: 'signal.rule.threat.tactic.name', value: 'signal.rule.threat.tactic.name' }, { text: 'destination.ip', value: 'destination.ip' }, { text: 'event.action', value: 'event.action' }, { text: 'event.category', value: 'event.category' }, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/helpers.tsx similarity index 81% rename from x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/helpers.tsx rename to x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/helpers.tsx index ed503e9872f0af..551850fa610dbd 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/helpers.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HistogramData, SignalsAggregation, SignalsBucket, SignalsGroupBucket } from '../types'; -import { SignalSearchResponse } from '../../../../../containers/detection_engine/signals/types'; -import * as i18n from '../translations'; +import { HistogramData, SignalsAggregation, SignalsBucket, SignalsGroupBucket } from './types'; +import { SignalSearchResponse } from '../../../../containers/detection_engine/signals/types'; +import * as i18n from './translations'; export const formatSignalsData = ( signalsData: SignalSearchResponse<{}, SignalsAggregation> | null @@ -47,9 +47,14 @@ export const getSignalsHistogramQuery = ( }, aggs: { signals: { - auto_date_histogram: { + date_histogram: { field: '@timestamp', - buckets: 36, + fixed_interval: `${Math.floor((to - from) / 32)}ms`, + min_doc_count: 0, + extended_bounds: { + min: from, + max: to, + }, }, }, }, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx index 64bc7ba24c6895..2cdafe38a74347 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx @@ -4,34 +4,50 @@ * you may not use this file except in compliance with the Elastic License. */ import { Position } from '@elastic/charts'; -import { EuiButton, EuiPanel, EuiSelect } from '@elastic/eui'; +import { EuiButton, EuiSelect, EuiPanel } from '@elastic/eui'; import numeral from '@elastic/numeral'; -import React, { memo, useCallback, useMemo, useState } from 'react'; +import React, { memo, useCallback, useMemo, useState, useEffect } from 'react'; +import styled from 'styled-components'; +import { isEmpty } from 'lodash/fp'; import { HeaderSection } from '../../../../components/header_section'; import { SignalsHistogram } from './signals_histogram'; import * as i18n from './translations'; import { Query } from '../../../../../../../../../src/plugins/data/common/query'; -import { esFilters } from '../../../../../../../../../src/plugins/data/common/es_query'; -import { SignalsHistogramOption, SignalsTotal } from './types'; +import { esFilters, esQuery } from '../../../../../../../../../src/plugins/data/common/es_query'; +import { RegisterQuery, SignalsHistogramOption, SignalsAggregation, SignalsTotal } from './types'; import { signalsHistogramOptions } from './config'; import { getDetectionEngineUrl } from '../../../../components/link_to'; import { DEFAULT_NUMBER_FORMAT } from '../../../../../common/constants'; -import { useUiSetting$ } from '../../../../lib/kibana'; +import { useKibana, useUiSetting$ } from '../../../../lib/kibana'; +import { InspectButtonContainer } from '../../../../components/inspect'; +import { useQuerySignals } from '../../../../containers/detection_engine/signals/use_query'; +import { MatrixLoader } from '../../../../components/matrix_histogram/matrix_loader'; + +import { formatSignalsData, getSignalsHistogramQuery } from './helpers'; + +const StyledEuiPanel = styled(EuiPanel)` + position: relative; +`; const defaultTotalSignalsObj: SignalsTotal = { value: 0, relation: 'eq', }; +export const DETECTIONS_HISTOGRAM_ID = 'detections-histogram'; + interface SignalsHistogramPanelProps { defaultStackByOption?: SignalsHistogramOption; + deleteQuery?: ({ id }: { id: string }) => void; filters?: esFilters.Filter[]; from: number; query?: Query; legendPosition?: Position; loadingInitial?: boolean; + signalIndexName: string | null; + setQuery: (params: RegisterQuery) => void; showLinkToSignals?: boolean; showTotalSignalsCount?: boolean; stackByOptions?: SignalsHistogramOption[]; @@ -43,11 +59,14 @@ interface SignalsHistogramPanelProps { export const SignalsHistogramPanel = memo( ({ defaultStackByOption = signalsHistogramOptions[0], + deleteQuery, filters, query, from, legendPosition = 'right', loadingInitial = false, + setQuery, + signalIndexName, showLinkToSignals = false, showTotalSignalsCount = false, stackByOptions, @@ -55,11 +74,24 @@ export const SignalsHistogramPanel = memo( title = i18n.HISTOGRAM_HEADER, updateDateRange, }) => { + const [isInitialLoading, setIsInitialLoading] = useState(loadingInitial || true); const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); const [totalSignalsObj, setTotalSignalsObj] = useState(defaultTotalSignalsObj); const [selectedStackByOption, setSelectedStackByOption] = useState( defaultStackByOption ); + const { + loading: isLoadingSignals, + data: signalsData, + setQuery: setSignalsQuery, + response, + request, + refetch, + } = useQuerySignals<{}, SignalsAggregation>( + getSignalsHistogramQuery(selectedStackByOption.value, from, to, []), + signalIndexName + ); + const kibana = useKibana(); const totalSignals = useMemo( () => @@ -77,34 +109,106 @@ export const SignalsHistogramPanel = memo( ); }, []); + const formattedSignalsData = useMemo(() => formatSignalsData(signalsData), [signalsData]); + + useEffect(() => { + if (!loadingInitial && isInitialLoading && !isLoadingSignals && signalsData) { + setIsInitialLoading(false); + } + }, [loadingInitial, isLoadingSignals, signalsData]); + + useEffect(() => { + return () => { + if (deleteQuery) { + deleteQuery({ id: DETECTIONS_HISTOGRAM_ID }); + } + }; + }, []); + + useEffect(() => { + if (refetch != null && setQuery != null) { + setQuery({ + id: DETECTIONS_HISTOGRAM_ID, + inspect: { + dsl: [request], + response: [response], + }, + loading: isLoadingSignals, + refetch, + }); + } + }, [setQuery, isLoadingSignals, signalsData, response, request, refetch]); + + useEffect(() => { + setTotalSignalsObj( + signalsData?.hits.total ?? { + value: 0, + relation: 'eq', + } + ); + }, [signalsData]); + + useEffect(() => { + const converted = esQuery.buildEsQuery( + undefined, + query != null ? [query] : [], + filters?.filter(f => f.meta.disabled === false) ?? [], + { + ...esQuery.getEsQueryConfig(kibana.services.uiSettings), + dateFormatTZ: undefined, + } + ); + + setSignalsQuery( + getSignalsHistogramQuery( + selectedStackByOption.value, + from, + to, + !isEmpty(converted) ? [converted] : [] + ) + ); + }, [selectedStackByOption.value, from, to, query, filters]); + return ( - - - {stackByOptions && ( - - )} - {showLinkToSignals && ( - {i18n.VIEW_SIGNALS} + + + {isInitialLoading ? ( + <> + + + + ) : ( + <> + + {stackByOptions && ( + + )} + {showLinkToSignals && ( + {i18n.VIEW_SIGNALS} + )} + + + + )} - - - - + + ); } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx new file mode 100644 index 00000000000000..9d2af1e78f2856 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + Axis, + Chart, + getAxisId, + getSpecId, + HistogramBarSeries, + Position, + Settings, +} from '@elastic/charts'; +import React from 'react'; +import { EuiProgress } from '@elastic/eui'; +import { useTheme } from '../../../../components/charts/common'; +import { histogramDateTimeFormatter } from '../../../../components/utils'; +import { HistogramData } from './types'; + +interface HistogramSignalsProps { + from: number; + legendPosition?: Position; + loading: boolean; + to: number; + data: HistogramData[]; + updateDateRange: (min: number, max: number) => void; +} + +export const SignalsHistogram = React.memo( + ({ to, from, legendPosition = 'right', data, updateDateRange, loading }) => { + const theme = useTheme(); + + return ( + <> + {loading && ( + + )} + + + + + + + + + + + + ); + } +); +SignalsHistogram.displayName = 'SignalsHistogram'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/index.tsx deleted file mode 100644 index d4db8cc7c37e87..00000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/index.tsx +++ /dev/null @@ -1,122 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - Axis, - Chart, - getAxisId, - getSpecId, - HistogramBarSeries, - niceTimeFormatByDay, - Position, - Settings, - timeFormatter, -} from '@elastic/charts'; -import React, { useEffect, useMemo } from 'react'; -import { EuiLoadingContent } from '@elastic/eui'; -import { isEmpty } from 'lodash/fp'; -import { useQuerySignals } from '../../../../../containers/detection_engine/signals/use_query'; -import { Query } from '../../../../../../../../../../src/plugins/data/common/query'; -import { esFilters, esQuery } from '../../../../../../../../../../src/plugins/data/common/es_query'; -import { SignalsAggregation, SignalsTotal } from '../types'; -import { formatSignalsData, getSignalsHistogramQuery } from './helpers'; -import { useTheme } from '../../../../../components/charts/common'; -import { useKibana } from '../../../../../lib/kibana'; - -interface HistogramSignalsProps { - filters?: esFilters.Filter[]; - from: number; - legendPosition?: Position; - loadingInitial: boolean; - query?: Query; - setTotalSignalsCount: React.Dispatch; - stackByField: string; - to: number; - updateDateRange: (min: number, max: number) => void; -} - -export const SignalsHistogram = React.memo( - ({ - to, - from, - query, - filters, - legendPosition = 'right', - loadingInitial, - setTotalSignalsCount, - stackByField, - updateDateRange, - }) => { - const [isLoadingSignals, signalsData, setQuery] = useQuerySignals<{}, SignalsAggregation>( - getSignalsHistogramQuery(stackByField, from, to, []) - ); - const theme = useTheme(); - const kibana = useKibana(); - - const formattedSignalsData = useMemo(() => formatSignalsData(signalsData), [signalsData]); - - useEffect(() => { - setTotalSignalsCount( - signalsData?.hits.total ?? { - value: 0, - relation: 'eq', - } - ); - }, [signalsData]); - - useEffect(() => { - const converted = esQuery.buildEsQuery( - undefined, - query != null ? [query] : [], - filters?.filter(f => f.meta.disabled === false) ?? [], - { - ...esQuery.getEsQueryConfig(kibana.services.uiSettings), - dateFormatTZ: undefined, - } - ); - - setQuery( - getSignalsHistogramQuery(stackByField, from, to, !isEmpty(converted) ? [converted] : []) - ); - }, [stackByField, from, to, query, filters]); - - return ( - <> - {loadingInitial || isLoadingSignals ? ( - - ) : ( - - - - - - - - - - )} - - ); - } -); -SignalsHistogram.displayName = 'SignalsHistogram'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts index 8c88fa4a5dae60..4cecf7376ca41f 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts @@ -86,7 +86,7 @@ export const STACK_BY_USERS = i18n.translate( export const HISTOGRAM_HEADER = i18n.translate( 'xpack.siem.detectionEngine.signals.histogram.headerTitle', { - defaultMessage: 'Signal count', + defaultMessage: 'Signals count', } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/types.ts index 4eb10852450ade..6ef4cecc4ec8b4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/types.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { inputsModel } from '../../../../store'; + export interface SignalsHistogramOption { text: string; value: string; @@ -38,3 +40,10 @@ export interface SignalsTotal { value: number; relation: string; } + +export interface RegisterQuery { + id: string; + inspect: inputsModel.InspectQuery | null; + loading: boolean; + refetch: inputsModel.Refetch; +} diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_info/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_info/index.tsx index fc1110e3828473..e7cdc3345c031a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_info/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_info/index.tsx @@ -26,7 +26,7 @@ export const useSignalInfo = ({ ruleId = null }: SignalInfo): Return => { ); - const [loading, signals] = useQuerySignals(buildLastSignalsQuery(ruleId)); + const { loading, data: signals } = useQuerySignals(buildLastSignalsQuery(ruleId)); useEffect(() => { if (signals != null) { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/user_info/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/user_info/index.tsx index 24e14473d40e98..0f6a51e52cd2e8 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/user_info/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/user_info/index.tsx @@ -10,7 +10,6 @@ import React, { useEffect, useReducer, Dispatch, createContext, useContext } fro import { usePrivilegeUser } from '../../../../containers/detection_engine/signals/use_privilege_user'; import { useSignalIndex } from '../../../../containers/detection_engine/signals/use_signal_index'; import { useKibana } from '../../../../lib/kibana'; -import { useCreatePackagedRules } from '../../../../containers/detection_engine/rules/use_create_packaged_rules'; export interface State { canUserCRUD: boolean | null; @@ -155,20 +154,12 @@ export const useUserInfo = (): State => { hasIndexWrite: hasApiIndexWrite, hasManageApiKey: hasApiManageApiKey, } = usePrivilegeUser(); - const [ - indexNameLoading, - isApiSignalIndexExists, - apiSignalIndexName, - createSignalIndex, - ] = useSignalIndex(); - - useCreatePackagedRules({ - canUserCRUD, - hasIndexManage, - hasManageApiKey, - isAuthenticated, - isSignalIndexExists, - }); + const { + loading: indexNameLoading, + signalIndexExists: isApiSignalIndexExists, + signalIndexName: apiSignalIndexName, + createDeSignalIndex: createSignalIndex, + } = useSignalIndex(); const uiCapabilities = useKibana().services.application.capabilities; const capabilitiesCanUserCRUD: boolean = @@ -181,46 +172,50 @@ export const useUserInfo = (): State => { }, [loading, privilegeLoading, indexNameLoading]); useEffect(() => { - if (hasIndexManage !== hasApiIndexManage && hasApiIndexManage != null) { + if (!loading && hasIndexManage !== hasApiIndexManage && hasApiIndexManage != null) { dispatch({ type: 'updateHasIndexManage', hasIndexManage: hasApiIndexManage }); } - }, [hasIndexManage, hasApiIndexManage]); + }, [loading, hasIndexManage, hasApiIndexManage]); useEffect(() => { - if (hasIndexWrite !== hasApiIndexWrite && hasApiIndexWrite != null) { + if (!loading && hasIndexWrite !== hasApiIndexWrite && hasApiIndexWrite != null) { dispatch({ type: 'updateHasIndexWrite', hasIndexWrite: hasApiIndexWrite }); } - }, [hasIndexWrite, hasApiIndexWrite]); + }, [loading, hasIndexWrite, hasApiIndexWrite]); useEffect(() => { - if (hasManageApiKey !== hasApiManageApiKey && hasApiManageApiKey != null) { + if (!loading && hasManageApiKey !== hasApiManageApiKey && hasApiManageApiKey != null) { dispatch({ type: 'updateHasManageApiKey', hasManageApiKey: hasApiManageApiKey }); } - }, [hasManageApiKey, hasApiManageApiKey]); + }, [loading, hasManageApiKey, hasApiManageApiKey]); useEffect(() => { - if (isSignalIndexExists !== isApiSignalIndexExists && isApiSignalIndexExists != null) { + if ( + !loading && + isSignalIndexExists !== isApiSignalIndexExists && + isApiSignalIndexExists != null + ) { dispatch({ type: 'updateIsSignalIndexExists', isSignalIndexExists: isApiSignalIndexExists }); } - }, [isSignalIndexExists, isApiSignalIndexExists]); + }, [loading, isSignalIndexExists, isApiSignalIndexExists]); useEffect(() => { - if (isAuthenticated !== isApiAuthenticated && isApiAuthenticated != null) { + if (!loading && isAuthenticated !== isApiAuthenticated && isApiAuthenticated != null) { dispatch({ type: 'updateIsAuthenticated', isAuthenticated: isApiAuthenticated }); } - }, [isAuthenticated, isApiAuthenticated]); + }, [loading, isAuthenticated, isApiAuthenticated]); useEffect(() => { - if (canUserCRUD !== capabilitiesCanUserCRUD && capabilitiesCanUserCRUD != null) { + if (!loading && canUserCRUD !== capabilitiesCanUserCRUD && capabilitiesCanUserCRUD != null) { dispatch({ type: 'updateCanUserCRUD', canUserCRUD: capabilitiesCanUserCRUD }); } - }, [canUserCRUD, capabilitiesCanUserCRUD]); + }, [loading, canUserCRUD, capabilitiesCanUserCRUD]); useEffect(() => { - if (signalIndexName !== apiSignalIndexName && apiSignalIndexName != null) { + if (!loading && signalIndexName !== apiSignalIndexName && apiSignalIndexName != null) { dispatch({ type: 'updateSignalIndexName', signalIndexName: apiSignalIndexName }); } - }, [signalIndexName, apiSignalIndexName]); + }, [loading, signalIndexName, apiSignalIndexName]); useEffect(() => { if ( diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx index d9e0377b34060e..e49cd2b36c7b89 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx @@ -18,7 +18,6 @@ import { GlobalTime } from '../../containers/global_time'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; import { AlertsTable } from '../../components/alerts_viewer/alerts_table'; import { FiltersGlobal } from '../../components/filters_global'; -import { HeaderPage } from '../../components/header_page'; import { DETECTION_ENGINE_PAGE_NAME } from '../../components/link_to/redirect_to_detection_engine'; import { SiemSearchBar } from '../../components/search_bar'; import { WrapperPage } from '../../components/wrapper_page'; @@ -37,6 +36,7 @@ import { signalsHistogramOptions } from './components/signals_histogram_panel/co import { useUserInfo } from './components/user_info'; import { DetectionEngineEmptyPage } from './detection_engine_empty_page'; import { DetectionEngineNoIndex } from './detection_engine_no_signal_index'; +import { DetectionEngineHeaderPage } from './components/detection_engine_header_page'; import { DetectionEngineUserUnauthenticated } from './detection_engine_user_unauthenticated'; import * as i18n from './translations'; import { DetectionEngineTab } from './types'; @@ -54,7 +54,7 @@ export interface DispatchProps { }>; } -type DetectionEngineComponentProps = ReduxProps & DispatchProps; +type DetectionEnginePageComponentProps = ReduxProps & DispatchProps; const detectionsTabs = [ { @@ -69,153 +69,161 @@ const detectionsTabs = [ }, ]; -const DetectionEngineComponent = React.memo( - ({ filters, query, setAbsoluteRangeDatePicker }) => { - const { tabName = DetectionEngineTab.signals } = useParams(); - const { - loading, - isSignalIndexExists, - isAuthenticated: isUserAuthenticated, - canUserCRUD, - signalIndexName, - hasIndexWrite, - } = useUserInfo(); - - const [lastSignals] = useSignalInfo({}); - - const updateDateRangeCallback = useCallback( - (min: number, max: number) => { - setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); - }, - [setAbsoluteRangeDatePicker] +const DetectionEnginePageComponent: React.FC = ({ + filters, + query, + setAbsoluteRangeDatePicker, +}) => { + const { tabName = DetectionEngineTab.signals } = useParams(); + const { + loading, + isSignalIndexExists, + isAuthenticated: isUserAuthenticated, + canUserCRUD, + signalIndexName, + hasIndexWrite, + } = useUserInfo(); + + const [lastSignals] = useSignalInfo({}); + + const updateDateRangeCallback = useCallback( + (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + [setAbsoluteRangeDatePicker] + ); + + const tabs = useMemo( + () => ( + + {detectionsTabs.map(tab => ( + + {tab.name} + + ))} + + ), + [detectionsTabs, tabName] + ); + + const indexToAdd = useMemo(() => (signalIndexName == null ? [] : [signalIndexName]), [ + signalIndexName, + ]); + + if (isUserAuthenticated != null && !isUserAuthenticated && !loading) { + return ( + + + + ); - - if (isUserAuthenticated != null && !isUserAuthenticated && !loading) { - return ( - - - - - ); - } - if (isSignalIndexExists != null && !isSignalIndexExists && !loading) { - return ( - - - - - ); - } - - const tabs = useMemo( - () => ( - - {detectionsTabs.map(tab => ( - - {tab.name} - - ))} - - ), - [detectionsTabs, tabName] + } + if (isSignalIndexExists != null && !isSignalIndexExists && !loading) { + return ( + + + + ); + } - return ( - <> - {hasIndexWrite != null && !hasIndexWrite && } - - {({ indicesExist, indexPattern }) => { - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - - {i18n.LAST_SIGNAL} - {': '} - {lastSignals} - - ) - } - title={i18n.PAGE_TITLE} - > - - {i18n.BUTTON_MANAGE_RULES} - - - - - {({ to, from, deleteQuery, setQuery }) => ( + return ( + <> + {hasIndexWrite != null && !hasIndexWrite && } + + {({ indicesExist, indexPattern }) => { + return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( + + + + + + - {tabs} - - {tabName === DetectionEngineTab.signals && ( - <> - - - - - )} - {tabName === DetectionEngineTab.alerts && ( - <> - - - - - )} + {i18n.LAST_SIGNAL} + {': '} + {lastSignals} - )} - - - - ) : ( - - - + ) + } + title={i18n.PAGE_TITLE} + > + + {i18n.BUTTON_MANAGE_RULES} + + + + + {({ to, from, deleteQuery, setQuery }) => ( + <> + {tabs} + + {tabName === DetectionEngineTab.signals && ( + <> + + + + + )} + {tabName === DetectionEngineTab.alerts && ( + <> + + + + + )} + + )} + - ); - }} - - - - ); - } -); -DetectionEngineComponent.displayName = 'DetectionEngineComponent'; + + ) : ( + + + + + ); + }} + + + + ); +}; const makeMapStateToProps = () => { const getGlobalInputs = inputsSelectors.globalSelector(); @@ -230,8 +238,11 @@ const makeMapStateToProps = () => { }; }; -export const DetectionEngine = connect(makeMapStateToProps, { +const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, -})(DetectionEngineComponent); +}; -DetectionEngine.displayName = 'DetectionEngine'; +export const DetectionEnginePage = connect( + makeMapStateToProps, + mapDispatchToProps +)(React.memo(DetectionEnginePageComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine_no_signal_index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine_no_signal_index.tsx index 1be6317a91607c..f1478ab5858c9a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine_no_signal_index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine_no_signal_index.tsx @@ -5,23 +5,24 @@ */ import React from 'react'; -import chrome from 'ui/chrome'; import { EmptyPage } from '../../components/empty_page'; import * as i18n from './translations'; +import { useKibana } from '../../lib/kibana'; -const basePath = chrome.getBasePath(); - -export const DetectionEngineNoIndex = React.memo(() => ( - -)); +export const DetectionEngineNoIndex = React.memo(() => { + const docLinks = useKibana().services.docLinks; + return ( + + ); +}); DetectionEngineNoIndex.displayName = 'DetectionEngineNoIndex'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine_user_unauthenticated.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine_user_unauthenticated.tsx index 33b63aa3bf0fe4..b5c805f92135ad 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine_user_unauthenticated.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine_user_unauthenticated.tsx @@ -5,23 +5,25 @@ */ import React from 'react'; -import chrome from 'ui/chrome'; import { EmptyPage } from '../../components/empty_page'; import * as i18n from './translations'; +import { useKibana } from '../../lib/kibana'; -const basePath = chrome.getBasePath(); +export const DetectionEngineUserUnauthenticated = React.memo(() => { + const docLinks = useKibana().services.docLinks; -export const DetectionEngineUserUnauthenticated = React.memo(() => ( - -)); + return ( + + ); +}); DetectionEngineUserUnauthenticated.displayName = 'DetectionEngineUserUnauthenticated'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/index.tsx index 33186d2787d8ae..15093488195106 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/index.tsx @@ -8,18 +8,18 @@ import React from 'react'; import { Redirect, Route, Switch, RouteComponentProps } from 'react-router-dom'; import { ManageUserInfo } from './components/user_info'; -import { CreateRuleComponent } from './rules/create'; -import { DetectionEngine } from './detection_engine'; -import { EditRuleComponent } from './rules/edit'; -import { RuleDetails } from './rules/details'; -import { RulesComponent } from './rules'; +import { CreateRulePage } from './rules/create'; +import { DetectionEnginePage } from './detection_engine'; +import { EditRulePage } from './rules/edit'; +import { RuleDetailsPage } from './rules/details'; +import { RulesPage } from './rules'; import { DetectionEngineTab } from './types'; const detectionEnginePath = `/:pageName(detections)`; type Props = Partial> & { url: string }; -export const DetectionEngineContainer = React.memo(() => ( +const DetectionEngineContainerComponent: React.FC = () => ( (() => ( path={`${detectionEnginePath}/:tabName(${DetectionEngineTab.signals}|${DetectionEngineTab.alerts})`} strict > - + - + - + - - + + - - + + (() => ( /> -)); -DetectionEngineContainer.displayName = 'DetectionEngineContainer'; +); + +export const DetectionEngineContainer = React.memo(DetectionEngineContainerComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/mitre/mitre_tactics_techniques.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/mitre/mitre_tactics_techniques.ts index 160e006c4d267f..16ab73365222bc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/mitre/mitre_tactics_techniques.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/mitre/mitre_tactics_techniques.ts @@ -187,7 +187,7 @@ export const tacticsOptions: MitreTacticsOptions[] = [ }, ]; -export const techniques = [ +export const technique = [ { name: '.bash_profile and .bashrc', id: 'T1156', diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts index b79b3ed091f169..980575f1470a5a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts @@ -37,7 +37,7 @@ export const mockRule = (id: string): Rule => ({ tags: [], to: 'now', type: 'saved_query', - threats: [], + threat: [], version: 1, }); @@ -56,13 +56,10 @@ export const mockTableData: TableData[] = [ id: 'abe6c564-050d-45a5-aaf0-386c37dd1f61', immutable: false, isLoading: false, - lastCompletedRun: undefined, - lastResponse: { type: '—' }, - method: 'saved_query', + risk_score: 21, rule: { href: '#/detections/rules/id/abe6c564-050d-45a5-aaf0-386c37dd1f61', name: 'Home Grown!', - status: 'Status Placeholder', }, rule_id: 'b5ba41ab-aaf3-4f43-971b-bdf9434ce0ea', severity: 'low', @@ -90,7 +87,7 @@ export const mockTableData: TableData[] = [ saved_id: "Garrett's IP", severity: 'low', tags: [], - threats: [], + threat: [], timeline_id: '86aa74d0-2136-11ea-9864-ebc8cc1cb8c2', timeline_title: 'Untitled timeline', to: 'now', @@ -108,13 +105,10 @@ export const mockTableData: TableData[] = [ id: '63f06f34-c181-4b2d-af35-f2ace572a1ee', immutable: false, isLoading: false, - lastCompletedRun: undefined, - lastResponse: { type: '—' }, - method: 'saved_query', + risk_score: 21, rule: { href: '#/detections/rules/id/63f06f34-c181-4b2d-af35-f2ace572a1ee', name: 'Home Grown!', - status: 'Status Placeholder', }, rule_id: 'b5ba41ab-aaf3-4f43-971b-bdf9434ce0ea', severity: 'low', @@ -142,7 +136,7 @@ export const mockTableData: TableData[] = [ saved_id: "Garrett's IP", severity: 'low', tags: [], - threats: [], + threat: [], timeline_id: '86aa74d0-2136-11ea-9864-ebc8cc1cb8c2', timeline_title: 'Untitled timeline', to: 'now', diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/actions.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/actions.tsx index 435edcab433b6c..6212c2067384d9 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/actions.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/actions.tsx @@ -21,6 +21,7 @@ import { displayErrorToast, displaySuccessToast, } from '../../../../components/toasters'; +import { track, METRIC_TYPE, TELEMETRY_EVENT } from '../../../../lib/telemetry'; import * as i18n from '../translations'; import { bucketRulesResponse } from './helpers'; @@ -38,12 +39,7 @@ export const duplicateRulesAction = async ( const ruleIds = rules.map(r => r.id); dispatch({ type: 'updateLoading', ids: ruleIds, isLoading: true }); const duplicatedRules = await duplicateRules({ rules }); - dispatch({ type: 'updateLoading', ids: ruleIds, isLoading: false }); - dispatch({ - type: 'updateRules', - rules: duplicatedRules, - appendRuleId: rules[rules.length - 1].id, - }); + dispatch({ type: 'refresh' }); displaySuccessToast( i18n.SUCCESSFULLY_DUPLICATED_RULES(duplicatedRules.length), dispatchToaster @@ -64,13 +60,12 @@ export const deleteRulesAction = async ( onRuleDeleted?: () => void ) => { try { - dispatch({ type: 'updateLoading', ids, isLoading: true }); + dispatch({ type: 'loading', isLoading: true }); const response = await deleteRules({ ids }); - const { rules, errors } = bucketRulesResponse(response); - - dispatch({ type: 'deleteRules', rules }); + const { errors } = bucketRulesResponse(response); + dispatch({ type: 'refresh' }); if (errors.length > 0) { displayErrorToast( i18n.BATCH_ACTION_DELETE_SELECTED_ERROR(ids.length), @@ -115,6 +110,19 @@ export const enableRulesAction = async ( dispatchToaster ); } + + if (rules.some(rule => rule.immutable)) { + track( + METRIC_TYPE.COUNT, + enabled ? TELEMETRY_EVENT.SIEM_RULE_ENABLED : TELEMETRY_EVENT.SIEM_RULE_DISABLED + ); + } + if (rules.some(rule => !rule.immutable)) { + track( + METRIC_TYPE.COUNT, + enabled ? TELEMETRY_EVENT.CUSTOM_RULE_ENABLED : TELEMETRY_EVENT.CUSTOM_RULE_DISABLED + ); + } } catch (e) { displayErrorToast(errorTitle, [e.message], dispatchToaster); dispatch({ type: 'updateLoading', ids, isLoading: false }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx index d546c4edb55d35..d648854368c28b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx @@ -31,6 +31,7 @@ import { RuleSwitch } from '../components/rule_switch'; import { SeverityBadge } from '../components/severity_badge'; import { ActionToaster } from '../../../../components/toasters'; import { getStatusColor } from '../components/rule_status/helpers'; +import { TruncatableText } from '../../../../components/truncatable_text'; const getActions = ( dispatch: React.Dispatch, @@ -84,8 +85,8 @@ export const getColumns = ( width: '24%', }, { - field: 'method', - name: i18n.COLUMN_METHOD, + field: 'risk_score', + name: i18n.COLUMN_RISK_SCORE, truncateText: true, width: '14%', }, @@ -129,13 +130,13 @@ export const getColumns = ( field: 'tags', name: i18n.COLUMN_TAGS, render: (value: TableData['tags']) => ( - <> + {value.map((tag, i) => ( {tag} ))} - + ), truncateText: true, width: '20%', diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/helpers.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/helpers.ts index 07a2f2f2789874..9a523536694d93 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/helpers.ts @@ -10,7 +10,6 @@ import { RuleResponseBuckets, } from '../../../../containers/detection_engine/rules'; import { TableData } from '../types'; -import { getEmptyValue } from '../../../../components/empty_value'; /** * Formats rules into the correct format for the AllRulesTable @@ -26,14 +25,9 @@ export const formatRules = (rules: Rule[], selectedIds?: string[]): TableData[] rule: { href: `#/detections/rules/id/${encodeURIComponent(rule.id)}`, name: rule.name, - status: 'Status Placeholder', }, - method: rule.type, // TODO: Map to i18n? + risk_score: rule.risk_score, severity: rule.severity, - lastCompletedRun: undefined, // TODO: Not available yet - lastResponse: { - type: getEmptyValue(), // TODO: Not available yet - }, tags: rule.tags ?? [], activate: rule.enabled, status: rule.status ?? null, @@ -56,3 +50,16 @@ export const bucketRulesResponse = (response: Array) => }, { rules: [], errors: [] } ); + +export const showRulesTable = ({ + isInitialLoad, + rulesCustomInstalled, + rulesInstalled, +}: { + isInitialLoad: boolean; + rulesCustomInstalled: number | null; + rulesInstalled: number | null; +}) => + !isInitialLoad && + ((rulesCustomInstalled != null && rulesCustomInstalled > 0) || + (rulesInstalled != null && rulesInstalled > 0)); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx index 4aa6b778582f97..b304d77f2e2767 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx @@ -7,14 +7,20 @@ import { EuiBasicTable, EuiContextMenuPanel, - EuiFieldSearch, + EuiEmptyPrompt, EuiLoadingContent, EuiSpacer, } from '@elastic/eui'; +import { isEmpty } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useReducer, useState } from 'react'; import { useHistory } from 'react-router-dom'; - import uuid from 'uuid'; + +import { + useRules, + CreatePreBuiltRules, + FilterOptions, +} from '../../../../containers/detection_engine/rules'; import { HeaderSection } from '../../../../components/header_section'; import { UtilityBar, @@ -23,16 +29,19 @@ import { UtilityBarSection, UtilityBarText, } from '../../../../components/detection_engine/utility_bar'; -import { getColumns } from './columns'; -import { useRules } from '../../../../containers/detection_engine/rules'; +import { useStateToaster } from '../../../../components/toasters'; import { Loader } from '../../../../components/loader'; import { Panel } from '../../../../components/panel'; -import { getBatchItems } from './batch_actions'; +import { PrePackagedRulesPrompt } from '../components/pre_packaged_rules/load_empty_prompt'; +import { RuleDownloader } from '../components/rule_downloader'; +import { getPrePackagedRuleStatus } from '../helpers'; +import * as i18n from '../translations'; import { EuiBasicTableOnChange, TableData } from '../types'; +import { getBatchItems } from './batch_actions'; +import { getColumns } from './columns'; +import { showRulesTable } from './helpers'; import { allRulesReducer, State } from './reducer'; -import * as i18n from '../translations'; -import { RuleDownloader } from '../components/rule_downloader'; -import { useStateToaster } from '../../../../components/toasters'; +import { RulesTableFilters } from './rules_table_filters/rules_table_filters'; const initialState: State = { isLoading: true, @@ -52,6 +61,20 @@ const initialState: State = { }, }; +interface AllRulesProps { + createPrePackagedRules: CreatePreBuiltRules | null; + hasNoPermissions: boolean; + importCompleteToggle: boolean; + loading: boolean; + loadingCreatePrePackagedRules: boolean; + refetchPrePackagedRulesStatus: () => void; + rulesCustomInstalled: number | null; + rulesInstalled: number | null; + rulesNotInstalled: number | null; + rulesNotUpdated: number | null; + setRefreshRulesData: (refreshRule: () => void) => void; +} + /** * Table Component for displaying all Rules for a given cluster. Provides the ability to filter * by name, sort by enabled, and perform the following actions: @@ -60,191 +83,259 @@ const initialState: State = { * * Delete * * Import/Export */ -export const AllRules = React.memo<{ - hasNoPermissions: boolean; - importCompleteToggle: boolean; - loading: boolean; -}>(({ hasNoPermissions, importCompleteToggle, loading }) => { - const [ - { - exportPayload, - filterOptions, - isLoading, +export const AllRules = React.memo( + ({ + createPrePackagedRules, + hasNoPermissions, + importCompleteToggle, + loading, + loadingCreatePrePackagedRules, + refetchPrePackagedRulesStatus, + rulesCustomInstalled, + rulesInstalled, + rulesNotInstalled, + rulesNotUpdated, + setRefreshRulesData, + }) => { + const [ + { + exportPayload, + filterOptions, + isLoading, + refreshToggle, + selectedItems, + tableData, + pagination, + }, + dispatch, + ] = useReducer(allRulesReducer, initialState); + const history = useHistory(); + const [oldRefreshToggle, setOldRefreshToggle] = useState(refreshToggle); + const [isInitialLoad, setIsInitialLoad] = useState(true); + const [isGlobalLoading, setIsGlobalLoad] = useState(false); + const [, dispatchToaster] = useStateToaster(); + const [isLoadingRules, rulesData, reFetchRulesData] = useRules(pagination, filterOptions); + + const prePackagedRuleStatus = getPrePackagedRuleStatus( + rulesInstalled, + rulesNotInstalled, + rulesNotUpdated + ); + + const getBatchItemsPopoverContent = useCallback( + (closePopover: () => void) => ( + + ), + [selectedItems, dispatch, dispatchToaster, history] + ); + + const tableOnChangeCallback = useCallback( + ({ page, sort }: EuiBasicTableOnChange) => { + dispatch({ + type: 'updateFilterOptions', + filterOptions: { + sortField: 'enabled', // Only enabled is supported for sorting currently + sortOrder: sort?.direction ?? 'desc', + }, + pagination: { page: page.index + 1, perPage: page.size }, + }); + }, + [dispatch] + ); + + const columns = useMemo(() => { + return getColumns(dispatch, dispatchToaster, history, hasNoPermissions); + }, [dispatch, dispatchToaster, history]); + + useEffect(() => { + dispatch({ type: 'loading', isLoading: isLoadingRules }); + }, [isLoadingRules]); + + useEffect(() => { + if (!isLoadingRules && !loading && isInitialLoad) { + setIsInitialLoad(false); + } + }, [isInitialLoad, isLoadingRules, loading]); + + useEffect(() => { + if (!isGlobalLoading && (isLoadingRules || isLoading)) { + setIsGlobalLoad(true); + } else if (isGlobalLoading && !isLoadingRules && !isLoading) { + setIsGlobalLoad(false); + } + }, [setIsGlobalLoad, isGlobalLoading, isLoadingRules, isLoading]); + + useEffect(() => { + if (!isInitialLoad) { + dispatch({ type: 'refresh' }); + } + }, [importCompleteToggle]); + + useEffect(() => { + if (!isInitialLoad && reFetchRulesData != null && oldRefreshToggle !== refreshToggle) { + setOldRefreshToggle(refreshToggle); + reFetchRulesData(); + refetchPrePackagedRulesStatus(); + } + }, [ + isInitialLoad, refreshToggle, - selectedItems, - tableData, - pagination, - }, - dispatch, - ] = useReducer(allRulesReducer, initialState); - const history = useHistory(); - const [isInitialLoad, setIsInitialLoad] = useState(true); - const [isLoadingRules, rulesData] = useRules(pagination, filterOptions, refreshToggle); - const [, dispatchToaster] = useStateToaster(); - - const getBatchItemsPopoverContent = useCallback( - (closePopover: () => void) => ( - - ), - [selectedItems, dispatch, dispatchToaster, history] - ); - - const tableOnChangeCallback = useCallback( - ({ page, sort }: EuiBasicTableOnChange) => { + oldRefreshToggle, + reFetchRulesData, + refetchPrePackagedRulesStatus, + ]); + + useEffect(() => { + if (reFetchRulesData != null) { + setRefreshRulesData(reFetchRulesData); + } + }, [reFetchRulesData, setRefreshRulesData]); + + useEffect(() => { dispatch({ - type: 'updatePagination', - pagination: { ...pagination, page: page.index + 1, perPage: page.size }, + type: 'updateRules', + rules: rulesData.data, + pagination: { + page: rulesData.page, + perPage: rulesData.perPage, + total: rulesData.total, + }, }); + }, [rulesData]); + + const handleCreatePrePackagedRules = useCallback(async () => { + if (createPrePackagedRules != null) { + await createPrePackagedRules(); + dispatch({ type: 'refresh' }); + } + }, [createPrePackagedRules]); + + const euiBasicTableSelectionProps = useMemo( + () => ({ + selectable: (item: TableData) => !item.isLoading, + onSelectionChange: (selected: TableData[]) => + dispatch({ type: 'setSelected', selectedItems: selected }), + }), + [] + ); + + const onFilterChangedCallback = useCallback((newFilterOptions: Partial) => { dispatch({ type: 'updateFilterOptions', filterOptions: { - ...filterOptions, - sortField: 'enabled', // Only enabled is supported for sorting currently - sortOrder: sort?.direction ?? 'desc', + ...newFilterOptions, }, + pagination: { page: 1 }, }); - }, - [dispatch, filterOptions, pagination] - ); - - const columns = useMemo(() => { - return getColumns(dispatch, dispatchToaster, history, hasNoPermissions); - }, [dispatch, dispatchToaster, history]); - - useEffect(() => { - dispatch({ type: 'loading', isLoading: isLoadingRules }); - - if (!isLoadingRules) { - setIsInitialLoad(false); - } - }, [isLoadingRules]); - - useEffect(() => { - if (!isInitialLoad) { - dispatch({ type: 'refresh' }); - } - }, [importCompleteToggle]); - - useEffect(() => { - dispatch({ - type: 'updateRules', - rules: rulesData.data, - pagination: { - page: rulesData.page, - perPage: rulesData.perPage, - total: rulesData.total, - }, - }); - }, [rulesData]); - - const euiBasicTableSelectionProps = useMemo( - () => ({ - selectable: (item: TableData) => !item.isLoading, - onSelectionChange: (selected: TableData[]) => - dispatch({ type: 'setSelected', selectedItems: selected }), - }), - [] - ); - - return ( - <> - { - dispatchToaster({ - type: 'addToaster', - toast: { - id: uuid.v4(), - title: i18n.SUCCESSFULLY_EXPORTED_RULES(exportCount), - color: 'success', - iconType: 'check', - }, - }); - }} - /> - - - - {isInitialLoad ? ( - - ) : ( + }, []); + + const emptyPrompt = useMemo(() => { + return ( + {i18n.NO_RULES}} titleSize="xs" body={i18n.NO_RULES_BODY} /> + ); + }, []); + + return ( + <> + { + dispatchToaster({ + type: 'addToaster', + toast: { + id: uuid.v4(), + title: i18n.SUCCESSFULLY_EXPORTED_RULES(exportCount), + color: 'success', + iconType: 'check', + }, + }); + }} + /> + + + <> - - { - dispatch({ - type: 'updateFilterOptions', - filterOptions: { - ...filterOptions, - filter: filterString, - }, - }); - dispatch({ - type: 'updatePagination', - pagination: { ...pagination, page: 1 }, - }); - }} - /> - - - - - - {i18n.SHOWING_RULES(pagination.total ?? 0)} - - - - {i18n.SELECTED_RULES(selectedItems.length)} - {!hasNoPermissions && ( - - {i18n.BATCH_ACTIONS} - - )} - dispatch({ type: 'refresh' })} - > - {i18n.REFRESH} - - - - - - - {(isLoading || loading) && ( + {((rulesCustomInstalled && rulesCustomInstalled > 0) || + (rulesInstalled != null && rulesInstalled > 0)) && ( + + + + )} + {isInitialLoad && ( + + )} + {isGlobalLoading && !isEmpty(tableData) && !isInitialLoad && ( )} + {rulesCustomInstalled != null && + rulesCustomInstalled === 0 && + prePackagedRuleStatus === 'ruleNotInstalled' && ( + + )} + {showRulesTable({ isInitialLoad, rulesCustomInstalled, rulesInstalled }) && ( + <> + + + + {i18n.SHOWING_RULES(pagination.total ?? 0)} + + + + {i18n.SELECTED_RULES(selectedItems.length)} + {!hasNoPermissions && ( + + {i18n.BATCH_ACTIONS} + + )} + dispatch({ type: 'refresh' })} + > + {i18n.REFRESH} + + + + + + + + )} - )} - - - ); -}); + + + ); + } +); AllRules.displayName = 'AllRules'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/reducer.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/reducer.ts index 22d6ca2195fe66..3634a16cbf6ac3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/reducer.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/reducer.ts @@ -31,9 +31,13 @@ export type Action = | { type: 'setExportPayload'; exportPayload?: Rule[] } | { type: 'setSelected'; selectedItems: TableData[] } | { type: 'updateLoading'; ids: string[]; isLoading: boolean } - | { type: 'updateRules'; rules: Rule[]; appendRuleId?: string; pagination?: PaginationOptions } - | { type: 'updatePagination'; pagination: PaginationOptions } - | { type: 'updateFilterOptions'; filterOptions: FilterOptions } + | { type: 'updateRules'; rules: Rule[]; pagination?: PaginationOptions } + | { type: 'updatePagination'; pagination: Partial } + | { + type: 'updateFilterOptions'; + filterOptions: Partial; + pagination: Partial; + } | { type: 'failure' }; export const allRulesReducer = (state: State, action: Action): State => { @@ -56,21 +60,15 @@ export const allRulesReducer = (state: State, action: Action): State => { } const ruleIds = state.rules.map(r => r.rule_id); - const appendIdx = - action.appendRuleId != null ? state.rules.findIndex(r => r.id === action.appendRuleId) : -1; - const updatedRules = action.rules.reduce( - (rules, updatedRule) => - ruleIds.includes(updatedRule.rule_id) - ? rules.map(r => (updatedRule.rule_id === r.rule_id ? updatedRule : r)) - : appendIdx !== -1 - ? [ - ...rules.slice(0, appendIdx + 1), - updatedRule, - ...rules.slice(appendIdx + 1, rules.length - 1), - ] - : [...rules, updatedRule], - [...state.rules] - ); + const updatedRules = action.rules.reverse().reduce((rules, updatedRule) => { + let newRules = rules; + if (ruleIds.includes(updatedRule.rule_id)) { + newRules = newRules.map(r => (updatedRule.rule_id === r.rule_id ? updatedRule : r)); + } else { + newRules = [...newRules, updatedRule]; + } + return newRules; + }, state.rules); // Update enabled on selectedItems so that batch actions show correct available actions const updatedRuleIdToState = action.rules.reduce>( @@ -93,13 +91,23 @@ export const allRulesReducer = (state: State, action: Action): State => { case 'updatePagination': { return { ...state, - pagination: action.pagination, + pagination: { + ...state.pagination, + ...action.pagination, + }, }; } case 'updateFilterOptions': { return { ...state, - filterOptions: action.filterOptions, + filterOptions: { + ...state.filterOptions, + ...action.filterOptions, + }, + pagination: { + ...state.pagination, + ...action.pagination, + }, }; } case 'deleteRules': { @@ -112,6 +120,7 @@ export const allRulesReducer = (state: State, action: Action): State => { ...state, rules: updatedRules, tableData: formatRules(updatedRules), + refreshToggle: !state.refreshToggle, }; } case 'setSelected': { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx new file mode 100644 index 00000000000000..c54a2e8d49844d --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback, useEffect, useState } from 'react'; + +import { + EuiFieldSearch, + EuiFilterButton, + EuiFilterGroup, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; +import * as i18n from '../../translations'; + +import { FilterOptions } from '../../../../../containers/detection_engine/rules'; +import { useTags } from '../../../../../containers/detection_engine/rules/use_tags'; +import { TagsFilterPopover } from './tags_filter_popover'; + +interface RulesTableFiltersProps { + onFilterChanged: (filterOptions: Partial) => void; + rulesCustomInstalled: number | null; + rulesInstalled: number | null; +} + +/** + * Collection of filters for filtering data within the RulesTable. Contains search bar, Elastic/Custom + * Rules filter button toggle, and tag selection + * + * @param onFilterChanged change listener to be notified on filter changes + */ +const RulesTableFiltersComponent = ({ + onFilterChanged, + rulesCustomInstalled, + rulesInstalled, +}: RulesTableFiltersProps) => { + const [filter, setFilter] = useState(''); + const [selectedTags, setSelectedTags] = useState([]); + const [showCustomRules, setShowCustomRules] = useState(false); + const [showElasticRules, setShowElasticRules] = useState(false); + const [isLoadingTags, tags] = useTags(); + + // Propagate filter changes to parent + useEffect(() => { + onFilterChanged({ filter, showCustomRules, showElasticRules, tags: selectedTags }); + }, [filter, selectedTags, showCustomRules, showElasticRules, onFilterChanged]); + + const handleOnSearch = useCallback(filterString => setFilter(filterString.trim()), [setFilter]); + + const handleElasticRulesClick = useCallback(() => { + setShowElasticRules(!showElasticRules); + setShowCustomRules(false); + }, [setShowElasticRules, showElasticRules, setShowCustomRules]); + + const handleCustomRulesClick = useCallback(() => { + setShowCustomRules(!showCustomRules); + setShowElasticRules(false); + }, [setShowElasticRules, showCustomRules, setShowCustomRules]); + + return ( + + + + + + + + + + + + + + + {i18n.ELASTIC_RULES} + {rulesInstalled != null ? ` (${rulesInstalled})` : ''} + + + <> + {i18n.CUSTOM_RULES} + {rulesCustomInstalled != null ? ` (${rulesCustomInstalled})` : ''} + + + + + + ); +}; + +RulesTableFiltersComponent.displayName = 'RulesTableFiltersComponent'; + +export const RulesTableFilters = React.memo(RulesTableFiltersComponent); + +RulesTableFilters.displayName = 'RulesTableFilters'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx new file mode 100644 index 00000000000000..b9d2c97f063b1e --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Dispatch, SetStateAction, useEffect, useState } from 'react'; +import { + EuiFilterButton, + EuiFilterSelectItem, + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiPopover, + EuiText, +} from '@elastic/eui'; +import styled from 'styled-components'; +import * as i18n from '../../translations'; +import { toggleSelectedGroup } from '../../../../../components/ml_popover/jobs_table/filters/toggle_selected_group'; + +interface TagsFilterPopoverProps { + tags: string[]; + onSelectedTagsChanged: Dispatch>; + isLoading: boolean; +} + +const ScrollableDiv = styled.div` + max-height: 250px; + overflow: auto; +`; + +/** + * Popover for selecting tags to filter on + * + * @param tags to display for filtering + * @param onSelectedTagsChanged change listener to be notified when tag selection changes + */ +export const TagsFilterPopoverComponent = ({ + tags, + onSelectedTagsChanged, +}: TagsFilterPopoverProps) => { + const [isTagPopoverOpen, setIsTagPopoverOpen] = useState(false); + const [selectedTags, setSelectedTags] = useState([]); + + useEffect(() => { + onSelectedTagsChanged(selectedTags); + }, [selectedTags.sort().join()]); + + return ( + setIsTagPopoverOpen(!isTagPopoverOpen)} + isSelected={isTagPopoverOpen} + hasActiveFilters={selectedTags.length > 0} + numActiveFilters={selectedTags.length} + > + {i18n.TAGS} + + } + isOpen={isTagPopoverOpen} + closePopover={() => setIsTagPopoverOpen(!isTagPopoverOpen)} + panelPaddingSize="none" + > + + {tags.map((tag, index) => ( + toggleSelectedGroup(tag, selectedTags, setSelectedTags)} + > + {`${tag}`} + + ))} + + {tags.length === 0 && ( + + + + {i18n.NO_TAGS_AVAILABLE} + + + + )} + + ); +}; + +TagsFilterPopoverComponent.displayName = 'TagsFilterPopoverComponent'; + +export const TagsFilterPopover = React.memo(TagsFilterPopoverComponent); + +TagsFilterPopover.displayName = 'TagsFilterPopover'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.tsx index 011c008c5b2d2b..e1cbc6ee92393f 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.tsx @@ -24,7 +24,7 @@ import { tacticsOptions, techniquesOptions } from '../../../mitre/mitre_tactics_ import { FilterLabel } from './filter_label'; import * as i18n from './translations'; -import { BuildQueryBarDescription, BuildThreatsDescription, ListItems } from './types'; +import { BuildQueryBarDescription, BuildThreatDescription, ListItems } from './types'; import { SeverityBadge } from '../severity_badge'; import ListTreeIcon from './assets/list_tree_icon.svg'; @@ -94,7 +94,7 @@ export const buildQueryBarDescription = ({ return items; }; -const ThreatsEuiFlexGroup = styled(EuiFlexGroup)` +const ThreatEuiFlexGroup = styled(EuiFlexGroup)` .euiFlexItem { margin-bottom: 0px; } @@ -114,25 +114,22 @@ const ReferenceLinkItem = styled(EuiButtonEmpty)` } `; -export const buildThreatsDescription = ({ - label, - threats, -}: BuildThreatsDescription): ListItems[] => { - if (threats.length > 0) { +export const buildThreatDescription = ({ label, threat }: BuildThreatDescription): ListItems[] => { + if (threat.length > 0) { return [ { title: label, description: ( - - {threats.map((threat, index) => { - const tactic = tacticsOptions.find(t => t.id === threat.tactic.id); + + {threat.map((singleThreat, index) => { + const tactic = tacticsOptions.find(t => t.id === singleThreat.tactic.id); return ( - - + + {tactic != null ? tactic.text : ''} - {threat.techniques.map(technique => { + {singleThreat.technique.map(technique => { const myTechnique = techniquesOptions.find(t => t.id === technique.id); return ( @@ -153,7 +150,7 @@ export const buildThreatsDescription = ({ ); })} - + ), }, ]; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx index 8cf1601e2c4b64..f1d2609cde8fe5 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx @@ -24,7 +24,7 @@ import { buildQueryBarDescription, buildSeverityDescription, buildStringArrayDescription, - buildThreatsDescription, + buildThreatDescription, buildUnorderedListArrayDescription, buildUrlsDescription, } from './helpers'; @@ -116,11 +116,11 @@ const getDescriptionItem = ( savedId, indexPatterns, }); - } else if (field === 'threats') { - const threats: IMitreEnterpriseAttack[] = get(field, value).filter( - (threat: IMitreEnterpriseAttack) => threat.tactic.name !== 'none' + } else if (field === 'threat') { + const threat: IMitreEnterpriseAttack[] = get(field, value).filter( + (singleThreat: IMitreEnterpriseAttack) => singleThreat.tactic.name !== 'none' ); - return buildThreatsDescription({ label, threats }); + return buildThreatDescription({ label, threat }); } else if (field === 'description') { return [ { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/types.ts index d32fbcd725d12f..c120d4a4106d02 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/types.ts @@ -27,7 +27,7 @@ export interface BuildQueryBarDescription { indexPatterns?: IIndexPattern; } -export interface BuildThreatsDescription { +export interface BuildThreatDescription { label: string; - threats: IMitreEnterpriseAttack[]; + threat: IMitreEnterpriseAttack[]; } diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/helpers.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/helpers.ts index 1202fe54ad194f..7a28a16214df63 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/helpers.ts @@ -9,9 +9,9 @@ import { IMitreAttack } from '../../types'; export const isMitreAttackInvalid = ( tacticName: string | null | undefined, - techniques: IMitreAttack[] | null | undefined + technique: IMitreAttack[] | null | undefined ) => { - if (isEmpty(tacticName) || (tacticName !== 'none' && isEmpty(techniques))) { + if (isEmpty(tacticName) || (tacticName !== 'none' && isEmpty(technique))) { return true; } return false; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/index.tsx index f9a22c37cfdf00..d85be053065fc2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/index.tsx @@ -21,7 +21,7 @@ import styled from 'styled-components'; import { tacticsOptions, techniquesOptions } from '../../../mitre/mitre_tactics_techniques'; import * as Rulei18n from '../../translations'; import { FieldHook, getFieldValidityAndErrorMessage } from '../shared_imports'; -import { threatsDefault } from '../step_about_rule/default_value'; +import { threatDefault } from '../step_about_rule/default_value'; import { IMitreEnterpriseAttack } from '../../types'; import { MyAddItemButton } from '../add_item_form'; import { isMitreAttackInvalid } from './helpers'; @@ -49,7 +49,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI const values = field.value as string[]; const newValues = [...values.slice(0, index), ...values.slice(index + 1)]; if (isEmpty(newValues)) { - field.setValue(threatsDefault); + field.setValue(threatDefault); } else { field.setValue(newValues); } @@ -62,10 +62,10 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI if (!isEmpty(values[values.length - 1])) { field.setValue([ ...values, - { tactic: { id: 'none', name: 'none', reference: 'none' }, techniques: [] }, + { tactic: { id: 'none', name: 'none', reference: 'none' }, technique: [] }, ]); } else { - field.setValue([{ tactic: { id: 'none', name: 'none', reference: 'none' }, techniques: [] }]); + field.setValue([{ tactic: { id: 'none', name: 'none', reference: 'none' }, technique: [] }]); } }, [field]); @@ -82,7 +82,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI { ...values[index], tactic: { id, reference, name }, - techniques: [], + technique: [], }, ...values.slice(index + 1), ]); @@ -96,7 +96,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI ...values.slice(0, index), { ...values[index], - techniques: selectedOptions, + technique: selectedOptions, }, ...values.slice(index + 1), ]); @@ -133,9 +133,9 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI ); const getSelectTechniques = (item: IMitreEnterpriseAttack, index: number, disabled: boolean) => { - const invalid = isMitreAttackInvalid(item.tactic.name, item.techniques); + const invalid = isMitreAttackInvalid(item.tactic.name, item.technique); const options = techniquesOptions.filter(t => t.tactics.includes(kebabCase(item.tactic.name))); - const selectedOptions = item.techniques.map(technic => ({ + const selectedOptions = item.technique.map(technic => ({ ...technic, label: `${technic.name} (${technic.id})`, // API doesn't allow for label field })); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/translations.ts index 557e91691b6c75..bbc12800b7df5a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/translations.ts @@ -13,7 +13,7 @@ export const TACTIC = i18n.translate('xpack.siem.detectionEngine.mitreAttack.tac export const TECHNIQUE = i18n.translate( 'xpack.siem.detectionEngine.mitreAttack.techniquesDescription', { - defaultMessage: 'technique', + defaultMessage: 'techniques', } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx index 873e0c2184c61d..f467d0ebede418 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx @@ -65,6 +65,7 @@ export const PickTimeline = ({ > void; + loading: boolean; + userHasNoPermissions: boolean; +} + +const PrePackagedRulesPromptComponent: React.FC = ({ + createPrePackagedRules, + loading = false, + userHasNoPermissions = true, +}) => { + const handlePreBuiltCreation = useCallback(() => { + createPrePackagedRules(); + }, [createPrePackagedRules]); + return ( + {i18n.PRE_BUILT_TITLE}} + body={

    {i18n.PRE_BUILT_MSG}

    } + actions={ + + + + {i18n.PRE_BUILT_ACTION} + + + + + {i18n.CREATE_RULE_ACTION} + + + + } + /> + ); +}; + +export const PrePackagedRulesPrompt = memo(PrePackagedRulesPromptComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pre_packaged_rules/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pre_packaged_rules/translations.ts new file mode 100644 index 00000000000000..e70eadda570858 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pre_packaged_rules/translations.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const PRE_BUILT_TITLE = i18n.translate( + 'xpack.siem.detectionEngine.rules.prePackagedRules.emptyPromptTitle', + { + defaultMessage: 'Load Elastic prebuilt detection rules', + } +); + +export const PRE_BUILT_MSG = i18n.translate( + 'xpack.siem.detectionEngine.rules.prePackagedRules.emptyPromptMessage', + { + defaultMessage: + 'Elastic SIEM comes with prebuilt detection rules that run in the background and create signals when their conditions are met. By default, all prebuilt rules are disabled and you select which rules you want to activate.', + } +); + +export const PRE_BUILT_ACTION = i18n.translate( + 'xpack.siem.detectionEngine.rules.prePackagedRules.loadPreBuiltButton', + { + defaultMessage: 'Load prebuilt detection rules', + } +); + +export const CREATE_RULE_ACTION = i18n.translate( + 'xpack.siem.detectionEngine.rules.prePackagedRules.createOwnRuletButton', + { + defaultMessage: 'Create your own rules', + } +); + +export const UPDATE_PREPACKAGED_RULES_TITLE = i18n.translate( + 'xpack.siem.detectionEngine.rules.updatePrePackagedRulesTitle', + { + defaultMessage: 'Update available for Elastic prebuilt rules', + } +); + +export const UPDATE_PREPACKAGED_RULES_MSG = (updateRules: number) => + i18n.translate('xpack.siem.detectionEngine.rules.updatePrePackagedRulesMsg', { + values: { updateRules }, + defaultMessage: + 'You can update {updateRules} Elastic prebuilt {updateRules, plural, =1 {rule} other {rules}}. Note that this will reload deleted Elastic prebuilt rules.', + }); + +export const UPDATE_PREPACKAGED_RULES = (updateRules: number) => + i18n.translate('xpack.siem.detectionEngine.rules.updatePrePackagedRulesButton', { + values: { updateRules }, + defaultMessage: + 'Update {updateRules} Elastic prebuilt {updateRules, plural, =1 {rule} other {rules}} ', + }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pre_packaged_rules/update_callout.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pre_packaged_rules/update_callout.tsx new file mode 100644 index 00000000000000..80a120ebc63ef0 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pre_packaged_rules/update_callout.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { memo } from 'react'; + +import { EuiCallOut, EuiButton } from '@elastic/eui'; +import * as i18n from './translations'; + +interface UpdatePrePackagedRulesCallOutProps { + loading: boolean; + numberOfUpdatedRules: number; + updateRules: () => void; +} + +const UpdatePrePackagedRulesCallOutComponent: React.FC = ({ + loading, + numberOfUpdatedRules, + updateRules, +}) => ( + +

    {i18n.UPDATE_PREPACKAGED_RULES_MSG(numberOfUpdatedRules)}

    + + {i18n.UPDATE_PREPACKAGED_RULES(numberOfUpdatedRules)} + +
    +); + +export const UpdatePrePackagedRulesCallOut = memo(UpdatePrePackagedRulesCallOutComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/translations.ts index e03cc252ad729f..d128696ec7253b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/translations.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; export const STATUS = i18n.translate('xpack.siem.detectionEngine.ruleStatus.statusDescription', { - defaultMessage: 'Status', + defaultMessage: 'Last response', }); export const STATUS_AT = i18n.translate( diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/default_value.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/default_value.ts index 92aca1cecf9f30..70bfc2bcddd628 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/default_value.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/default_value.ts @@ -7,11 +7,11 @@ import { AboutStepRule } from '../../types'; import { DEFAULT_TIMELINE_TITLE } from '../../../../../components/timeline/search_super_select/translations'; -export const threatsDefault = [ +export const threatDefault = [ { framework: 'MITRE ATT&CK', tactic: { id: 'none', name: 'none', reference: 'none' }, - techniques: [], + technique: [], }, ]; @@ -28,5 +28,5 @@ export const stepAboutDefaultValue: AboutStepRule = { id: null, title: DEFAULT_TIMELINE_TITLE, }, - threats: threatsDefault, + threat: threatDefault, }; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx index 73c07673a82f44..4ae88b3014d190 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx @@ -4,7 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiButton, EuiHorizontalRule, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { + EuiAccordion, + EuiButton, + EuiHorizontalRule, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiButtonEmpty, +} from '@elastic/eui'; import { isEqual } from 'lodash/fp'; import React, { FC, memo, useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; @@ -35,6 +43,28 @@ const TagContainer = styled.div` margin-top: 16px; `; +TagContainer.displayName = 'TagContainer'; + +const AdvancedSettingsAccordion = styled(EuiAccordion)` + .euiAccordion__iconWrapper { + display: none; + } + + .euiAccordion__childWrapper { + transition-duration: 1ms; /* hack to fire Step accordion to set proper content's height */ + } + + &.euiAccordion-isOpen .euiButtonEmpty__content > svg { + transform: rotate(90deg); + } +`; + +const AdvancedSettingsAccordionButton = ( + + {I18n.ADVANCED_SETTINGS} + +); + const StepAboutRuleComponent: FC = ({ addPadding = false, defaultValues, @@ -111,73 +141,41 @@ const StepAboutRuleComponent: FC = ({ }, }} /> - - - - - - + + + + + + + + + = ({ }} /> + + + + + + + + {({ severity }) => { const newRiskScore = defaultRiskScoreBySeverity[severity as SeverityValue]; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx index 3de0e7605f3d97..22033dcf6b0f76 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx @@ -95,7 +95,7 @@ export const schema: FormSchema = { label: i18n.translate( 'xpack.siem.detectionEngine.createRule.stepAboutRule.fieldTimelineTemplateLabel', { - defaultMessage: 'Timeline template', + defaultMessage: 'Investigate detections using this timeline template', } ), }, @@ -139,7 +139,7 @@ export const schema: FormSchema = { ), labelAppend: OptionalFieldLabel, }, - threats: { + threat: { label: i18n.translate( 'xpack.siem.detectionEngine.createRule.stepAboutRule.fieldMitreThreatLabel', { @@ -155,7 +155,7 @@ export const schema: FormSchema = { const [{ value, path }] = args; let hasError = false; (value as IMitreEnterpriseAttack[]).forEach(v => { - if (isMitreAttackInvalid(v.tactic.name, v.techniques)) { + if (isMitreAttackInvalid(v.tactic.name, v.technique)) { hasError = true; } }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/translations.ts index 93237697657399..3b6680fd4e6875 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/translations.ts @@ -6,6 +6,13 @@ import { i18n } from '@kbn/i18n'; +export const ADVANCED_SETTINGS = i18n.translate( + 'xpack.siem.detectionEngine.createRule.stepAboutRuleForm.advancedSettingsButton', + { + defaultMessage: 'Advanced settings', + } +); + export const ADD_REFERENCE = i18n.translate( 'xpack.siem.detectionEngine.createRule.stepAboutRuleForm.addReferenceDescription', { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.ts index ce91e15cdcf0d3..de6678b42df6f2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.ts @@ -72,15 +72,7 @@ const formatScheduleStepData = (scheduleData: ScheduleStepRule): ScheduleStepRul }; const formatAboutStepData = (aboutStepData: AboutStepRule): AboutStepRuleJson => { - const { - falsePositives, - references, - riskScore, - threats, - timeline, - isNew, - ...rest - } = aboutStepData; + const { falsePositives, references, riskScore, threat, timeline, isNew, ...rest } = aboutStepData; return { false_positives: falsePositives.filter(item => !isEmpty(item)), references: references.filter(item => !isEmpty(item)), @@ -91,12 +83,12 @@ const formatAboutStepData = (aboutStepData: AboutStepRule): AboutStepRuleJson => timeline_title: timeline.title, } : {}), - threats: threats - .filter(threat => threat.tactic.name !== 'none') - .map(threat => ({ - ...threat, + threat: threat + .filter(singleThreat => singleThreat.tactic.name !== 'none') + .map(singleThreat => ({ + ...singleThreat, framework: 'MITRE ATT&CK', - techniques: threat.techniques.map(technique => { + technique: singleThreat.technique.map(technique => { const { id, name, reference } = technique; return { id, name, reference }; }), diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx index cbc60015d9c875..55b838077988cc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx @@ -7,10 +7,10 @@ import { EuiButtonEmpty, EuiAccordion, EuiHorizontalRule, EuiPanel, EuiSpacer } from '@elastic/eui'; import React, { useCallback, useRef, useState } from 'react'; import { Redirect } from 'react-router-dom'; -import styled from 'styled-components'; +import styled, { StyledComponent } from 'styled-components'; import { usePersistRule } from '../../../../containers/detection_engine/rules'; -import { HeaderPage } from '../../../../components/header_page'; + import { DETECTION_ENGINE_PAGE_NAME } from '../../../../components/link_to/redirect_to_detection_engine'; import { WrapperPage } from '../../../../components/wrapper_page'; import { displaySuccessToast, useStateToaster } from '../../../../components/toasters'; @@ -21,6 +21,7 @@ import { FormData, FormHook } from '../components/shared_imports'; import { StepAboutRule } from '../components/step_about_rule'; import { StepDefineRule } from '../components/step_define_rule'; import { StepScheduleRule } from '../components/step_schedule_rule'; +import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page'; import * as RuleI18n from '../translations'; import { AboutStepRule, DefineStepRule, RuleStep, RuleStepData, ScheduleStepRule } from '../types'; import { formatRule } from './helpers'; @@ -29,26 +30,41 @@ import * as i18n from './translations'; const stepsRuleOrder = [RuleStep.defineRule, RuleStep.aboutRule, RuleStep.scheduleRule]; const MyEuiPanel = styled(EuiPanel)<{ - zIndex?: number; + zindex?: number; }>` position: relative; - z-index: ${props => props.zIndex}; /* ugly fix to allow searchBar to overflow the EuiPanel */ + z-index: ${props => props.zindex}; /* ugly fix to allow searchBar to overflow the EuiPanel */ - .euiAccordion__iconWrapper { - display: none; + > .euiAccordion > .euiAccordion__triggerWrapper { + .euiAccordion__button { + cursor: default !important; + &:hover { + text-decoration: none !important; + } + } + + .euiAccordion__iconWrapper { + display: none; + } } +`; + +MyEuiPanel.displayName = 'MyEuiPanel'; + +const StepDefineRuleAccordion: StyledComponent< + typeof EuiAccordion, + any, // eslint-disable-line + { ref: React.MutableRefObject }, + never +> = styled(EuiAccordion)` .euiAccordion__childWrapper { overflow: visible; } - .euiAccordion__button { - cursor: default !important; - &:hover { - text-decoration: none !important; - } - } `; -export const CreateRuleComponent = React.memo(() => { +StepDefineRuleAccordion.displayName = 'StepDefineRuleAccordion'; + +const CreateRulePageComponent: React.FC = () => { const { loading, isSignalIndexExists, @@ -80,16 +96,7 @@ export const CreateRuleComponent = React.memo(() => { const userHasNoPermissions = canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; - if ( - isSignalIndexExists != null && - isAuthenticated != null && - (!isSignalIndexExists || !isAuthenticated) - ) { - return ; - } else if (userHasNoPermissions) { - return ; - } - + // eslint-disable-next-line react-hooks/rules-of-hooks const setStepData = useCallback( (step: RuleStep, data: unknown, isValid: boolean) => { stepsData.current[step] = { ...stepsData.current[step], data, isValid }; @@ -129,10 +136,12 @@ export const CreateRuleComponent = React.memo(() => { [isStepRuleInReadOnlyView, openAccordionId, stepsData.current, setRule] ); + // eslint-disable-next-line react-hooks/rules-of-hooks const setStepsForm = useCallback((step: RuleStep, form: FormHook) => { stepsForm.current[step] = form; }, []); + // eslint-disable-next-line react-hooks/rules-of-hooks const getAccordionType = useCallback( (accordionId: RuleStep) => { if (accordionId === openAccordionId) { @@ -181,6 +190,7 @@ export const CreateRuleComponent = React.memo(() => { } }; + // eslint-disable-next-line react-hooks/rules-of-hooks const manageAccordions = useCallback( (id: RuleStep, isOpen: boolean) => { const activeRuleIdx = stepsRuleOrder.findIndex(step => step === openAccordionId); @@ -202,6 +212,7 @@ export const CreateRuleComponent = React.memo(() => { [isStepRuleInReadOnlyView, openAccordionId, stepsData] ); + // eslint-disable-next-line react-hooks/rules-of-hooks const manageIsEditable = useCallback( async (id: RuleStep) => { const activeForm = await stepsForm.current[openAccordionId]?.submit(); @@ -228,17 +239,27 @@ export const CreateRuleComponent = React.memo(() => { return ; } + if ( + isSignalIndexExists != null && + isAuthenticated != null && + (!isSignalIndexExists || !isAuthenticated) + ) { + return ; + } else if (userHasNoPermissions) { + return ; + } + return ( <> - - - + { setStepData={setStepData} descriptionDirection="row" /> - + - + { - + { ); -}); -CreateRuleComponent.displayName = 'CreateRuleComponent'; +}; + +export const CreateRulePage = React.memo(CreateRulePageComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx index a23c681a5aab2f..1914f967813a15 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +/* eslint-disable react-hooks/rules-of-hooks */ + import { EuiButton, EuiLoadingSpinner, @@ -14,7 +16,7 @@ import { EuiTabs, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import React, { memo, useCallback, useMemo, useState } from 'react'; +import React, { FC, memo, useCallback, useMemo, useState } from 'react'; import { Redirect, useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; @@ -22,7 +24,6 @@ import { ActionCreator } from 'typescript-fsa'; import { connect } from 'react-redux'; import { FiltersGlobal } from '../../../../components/filters_global'; import { FormattedDate } from '../../../../components/formatted_date'; -import { HeaderPage } from '../../../../components/header_page'; import { DETECTION_ENGINE_PAGE_NAME } from '../../../../components/link_to/redirect_to_detection_engine'; import { SiemSearchBar } from '../../../../components/search_bar'; import { WrapperPage } from '../../../../components/wrapper_page'; @@ -34,6 +35,7 @@ import { } from '../../../../containers/source'; import { SpyRoute } from '../../../../utils/route/spy_routes'; +import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page'; import { SignalsHistogramPanel } from '../../components/signals_histogram_panel'; import { SignalsTable } from '../../components/signals'; import { useUserInfo } from '../../components/user_info'; @@ -98,296 +100,304 @@ const ruleDetailTabs = [ type RuleDetailsComponentProps = ReduxProps & DispatchProps; -const RuleDetailsComponent = memo( - ({ filters, query, setAbsoluteRangeDatePicker }) => { - const { - loading, - isSignalIndexExists, - isAuthenticated, - canUserCRUD, - hasManageApiKey, - hasIndexWrite, - signalIndexName, - } = useUserInfo(); - const { ruleId } = useParams(); - const [isLoading, rule] = useRule(ruleId); - // This is used to re-trigger api rule status when user de/activate rule - const [ruleEnabled, setRuleEnabled] = useState(null); - const [ruleDetailTab, setRuleDetailTab] = useState(RuleDetailTabs.signals); - const { aboutRuleData, defineRuleData, scheduleRuleData } = getStepsData({ - rule, - detailsView: true, - }); - const [lastSignals] = useSignalInfo({ ruleId }); - const userHasNoPermissions = - canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; - - if ( - isSignalIndexExists != null && - isAuthenticated != null && - (!isSignalIndexExists || !isAuthenticated) - ) { - return ; - } +const RuleDetailsPageComponent: FC = ({ + filters, + query, + setAbsoluteRangeDatePicker, +}) => { + const { + loading, + isSignalIndexExists, + isAuthenticated, + canUserCRUD, + hasManageApiKey, + hasIndexWrite, + signalIndexName, + } = useUserInfo(); + const { detailName: ruleId } = useParams(); + const [isLoading, rule] = useRule(ruleId); + // This is used to re-trigger api rule status when user de/activate rule + const [ruleEnabled, setRuleEnabled] = useState(null); + const [ruleDetailTab, setRuleDetailTab] = useState(RuleDetailTabs.signals); + const { aboutRuleData, defineRuleData, scheduleRuleData } = + rule != null + ? getStepsData({ + rule, + detailsView: true, + }) + : { aboutRuleData: null, defineRuleData: null, scheduleRuleData: null }; + const [lastSignals] = useSignalInfo({ ruleId }); + const userHasNoPermissions = + canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; - const title = isLoading === true || rule === null ? : rule.name; - const subTitle = useMemo( - () => - isLoading === true || rule === null ? ( - - ) : ( - [ + const title = isLoading === true || rule === null ? : rule.name; + const subTitle = useMemo( + () => + isLoading === true || rule === null ? ( + + ) : ( + [ + + ), + }} + />, + rule?.updated_by != null ? ( ), }} - />, - rule?.updated_by != null ? ( - - ), - }} - /> - ) : ( - '' - ), - ] - ), - [isLoading, rule] - ); + /> + ) : ( + '' + ), + ] + ), + [isLoading, rule] + ); - const signalDefaultFilters = useMemo( - () => (ruleId != null ? buildSignalsRuleIdFilter(ruleId) : []), - [ruleId] - ); + const signalDefaultFilters = useMemo( + () => (ruleId != null ? buildSignalsRuleIdFilter(ruleId) : []), + [ruleId] + ); - const signalMergedFilters = useMemo(() => [...signalDefaultFilters, ...filters], [ - signalDefaultFilters, - filters, - ]); + const signalMergedFilters = useMemo(() => [...signalDefaultFilters, ...filters], [ + signalDefaultFilters, + filters, + ]); - const tabs = useMemo( - () => ( - - {ruleDetailTabs.map(tab => ( - setRuleDetailTab(tab.id)} - isSelected={tab.id === ruleDetailTab} - disabled={tab.disabled} - key={tab.id} - > - {tab.name} - - ))} - - ), - [ruleDetailTabs, ruleDetailTab, setRuleDetailTab] - ); - const ruleError = useMemo( - () => - rule?.status === 'failed' && - ruleDetailTab === RuleDetailTabs.signals && - rule?.last_failure_at != null ? ( - - ) : null, - [rule, ruleDetailTab] - ); + const tabs = useMemo( + () => ( + + {ruleDetailTabs.map(tab => ( + setRuleDetailTab(tab.id)} + isSelected={tab.id === ruleDetailTab} + disabled={tab.disabled} + key={tab.id} + > + {tab.name} + + ))} + + ), + [ruleDetailTabs, ruleDetailTab, setRuleDetailTab] + ); + const ruleError = useMemo( + () => + rule?.status === 'failed' && + ruleDetailTab === RuleDetailTabs.signals && + rule?.last_failure_at != null ? ( + + ) : null, + [rule, ruleDetailTab] + ); - const updateDateRangeCallback = useCallback( - (min: number, max: number) => { - setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); - }, - [setAbsoluteRangeDatePicker] - ); + const indexToAdd = useMemo(() => (signalIndexName == null ? [] : [signalIndexName]), [ + signalIndexName, + ]); - const handleOnChangeEnabledRule = useCallback( - (enabled: boolean) => { - if (ruleEnabled == null || enabled !== ruleEnabled) { - setRuleEnabled(enabled); - } - }, - [ruleEnabled, setRuleEnabled] - ); + const updateDateRangeCallback = useCallback( + (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + [setAbsoluteRangeDatePicker] + ); - return ( - <> - {hasIndexWrite != null && !hasIndexWrite && } - {userHasNoPermissions && } - - {({ indicesExist, indexPattern }) => { - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - {({ to, from }) => ( - - - - + const handleOnChangeEnabledRule = useCallback( + (enabled: boolean) => { + if (ruleEnabled == null || enabled !== ruleEnabled) { + setRuleEnabled(enabled); + } + }, + [ruleEnabled, setRuleEnabled] + ); - - - {detectionI18n.LAST_SIGNAL} - {': '} - {lastSignals} - , - ] - : []), - , - ]} - title={title} - > - - - - + if ( + isSignalIndexExists != null && + isAuthenticated != null && + (!isSignalIndexExists || !isAuthenticated) + ) { + return ; + } - - - - - {ruleI18n.EDIT_RULE_SETTINGS} - - - - - - - - - - {ruleError} - {tabs} - - {ruleDetailTab === RuleDetailTabs.signals && ( - <> - - - - {defineRuleData != null && ( - - )} - - + return ( + <> + {hasIndexWrite != null && !hasIndexWrite && } + {userHasNoPermissions && } + + {({ indicesExist, indexPattern }) => { + return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( + + {({ to, from, deleteQuery, setQuery }) => ( + + + + - - - {aboutRuleData != null && ( - - )} - - + + + {detectionI18n.LAST_SIGNAL} + {': '} + {lastSignals} + , + ] + : []), + , + ]} + title={title} + > + + + + - - - {scheduleRuleData != null && ( - - )} - + + + + + {ruleI18n.EDIT_RULE_SETTINGS} + + + + - - + + + {ruleError} + {tabs} + + {ruleDetailTab === RuleDetailTabs.signals && ( + <> + + + + {defineRuleData != null && ( + + )} + + + + + + {aboutRuleData != null && ( + + )} + + + + + + {scheduleRuleData != null && ( + + )} + + + + + + + {ruleId != null && ( + - - {ruleId != null && ( - - )} - - )} - {ruleDetailTab === RuleDetailTabs.failures && ( - - )} - - - )} - - ) : ( - - - - - - ); - }} - + )} + + )} + {ruleDetailTab === RuleDetailTabs.failures && } + + + )} + + ) : ( + + - - - ); - } -); + + + ); + }} + -RuleDetailsComponent.displayName = 'RuleDetailsComponent'; + + + ); +}; const makeMapStateToProps = () => { const getGlobalInputs = inputsSelectors.globalSelector(); @@ -402,8 +412,11 @@ const makeMapStateToProps = () => { }; }; -export const RuleDetails = connect(makeMapStateToProps, { +const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, -})(RuleDetailsComponent); +}; -RuleDetails.displayName = 'RuleDetails'; +export const RuleDetailsPage = connect( + makeMapStateToProps, + mapDispatchToProps +)(memo(RuleDetailsPageComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx index 9b7833afd7f4da..65f4bd2edf7cd0 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +/* eslint-disable react-hooks/rules-of-hooks */ + import { EuiButton, EuiCallOut, @@ -14,16 +16,16 @@ import { EuiTabbedContentTab, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { FC, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Redirect, useParams } from 'react-router-dom'; import { useRule, usePersistRule } from '../../../../containers/detection_engine/rules'; -import { HeaderPage } from '../../../../components/header_page'; import { WrapperPage } from '../../../../components/wrapper_page'; import { DETECTION_ENGINE_PAGE_NAME } from '../../../../components/link_to/redirect_to_detection_engine'; import { displaySuccessToast, useStateToaster } from '../../../../components/toasters'; import { SpyRoute } from '../../../../utils/route/spy_routes'; import { useUserInfo } from '../../components/user_info'; +import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page'; import { FormHook, FormData } from '../components/shared_imports'; import { StepPanel } from '../components/step_panel'; import { StepAboutRule } from '../components/step_about_rule'; @@ -48,7 +50,7 @@ interface ScheduleStepRuleForm extends StepRuleForm { data: ScheduleStepRule | null; } -export const EditRuleComponent = memo(() => { +const EditRulePageComponent: FC = () => { const [, dispatchToaster] = useStateToaster(); const { loading: initLoading, @@ -57,20 +59,11 @@ export const EditRuleComponent = memo(() => { canUserCRUD, hasManageApiKey, } = useUserInfo(); - const { ruleId } = useParams(); + const { detailName: ruleId } = useParams(); const [loading, rule] = useRule(ruleId); const userHasNoPermissions = canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; - if ( - isSignalIndexExists != null && - isAuthenticated != null && - (!isSignalIndexExists || !isAuthenticated) - ) { - return ; - } else if (userHasNoPermissions) { - return ; - } const [initForm, setInitForm] = useState(false); const [myAboutRuleForm, setMyAboutRuleForm] = useState({ @@ -277,10 +270,20 @@ export const EditRuleComponent = memo(() => { return ; } + if ( + isSignalIndexExists != null && + isAuthenticated != null && + (!isSignalIndexExists || !isAuthenticated) + ) { + return ; + } else if (userHasNoPermissions) { + return ; + } + return ( <> - { - + ); -}); -EditRuleComponent.displayName = 'EditRuleComponent'; +}; + +export const EditRulePage = memo(EditRulePageComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx index cfe6cb8da1cb09..ce0d50d9b61065 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx @@ -4,7 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import dateMath from '@elastic/datemath'; import { get, pick } from 'lodash/fp'; +import moment from 'moment'; import { useLocation } from 'react-router-dom'; import { esFilters } from '../../../../../../../../src/plugins/data/public'; @@ -22,7 +24,7 @@ export const getStepsData = ({ rule, detailsView = false, }: { - rule: Rule | null; + rule: Rule; detailsView?: boolean; }): GetStepsData => { const defineRuleData: DefineStepRule | null = @@ -41,9 +43,9 @@ export const getStepsData = ({ rule != null ? { isNew: false, - ...pick(['description', 'name', 'references', 'severity', 'tags', 'threats'], rule), + ...pick(['description', 'name', 'references', 'severity', 'tags', 'threat'], rule), ...(detailsView ? { name: '' } : {}), - threats: rule.threats as IMitreEnterpriseAttack[], + threat: rule.threat as IMitreEnterpriseAttack[], falsePositives: rule.false_positives, riskScore: rule.risk_score, timeline: { @@ -52,15 +54,25 @@ export const getStepsData = ({ }, } : null; + + const from = dateMath.parse(rule.from) ?? moment(); + const interval = dateMath.parse(`now-${rule.interval}`) ?? moment(); + + const fromDuration = moment.duration(interval.diff(from)); + let fromHumanize = `${Math.floor(fromDuration.asHours())}h`; + + if (fromDuration.asSeconds() < 60) { + fromHumanize = `${Math.floor(fromDuration.asSeconds())}s`; + } else if (fromDuration.asMinutes() < 60) { + fromHumanize = `${Math.floor(fromDuration.asMinutes())}m`; + } + const scheduleRuleData: ScheduleStepRule | null = rule != null ? { isNew: false, ...pick(['enabled', 'interval'], rule), - from: - rule?.meta?.from != null - ? rule.meta.from.replace('now-', '') - : rule.from.replace('now-', ''), + from: fromHumanize, } : null; @@ -69,6 +81,52 @@ export const getStepsData = ({ export const useQuery = () => new URLSearchParams(useLocation().search); +export type PrePackagedRuleStatus = + | 'ruleInstalled' + | 'ruleNotInstalled' + | 'ruleNeedUpdate' + | 'someRuleUninstall' + | 'unknown'; + +export const getPrePackagedRuleStatus = ( + rulesInstalled: number | null, + rulesNotInstalled: number | null, + rulesNotUpdated: number | null +): PrePackagedRuleStatus => { + if ( + rulesNotInstalled != null && + rulesInstalled === 0 && + rulesNotInstalled > 0 && + rulesNotUpdated === 0 + ) { + return 'ruleNotInstalled'; + } else if ( + rulesInstalled != null && + rulesInstalled > 0 && + rulesNotInstalled === 0 && + rulesNotUpdated === 0 + ) { + return 'ruleInstalled'; + } else if ( + rulesInstalled != null && + rulesNotInstalled != null && + rulesInstalled > 0 && + rulesNotInstalled > 0 && + rulesNotUpdated === 0 + ) { + return 'someRuleUninstall'; + } else if ( + rulesInstalled != null && + rulesNotInstalled != null && + rulesNotUpdated != null && + rulesInstalled > 0 && + rulesNotInstalled >= 0 && + rulesNotUpdated > 0 + ) { + return 'ruleNeedUpdate'; + } + return 'unknown'; +}; export const setFieldValue = ( form: FormHook, schema: FormSchema, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx index dd46b33ca72578..1c0ed34e927938 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx @@ -5,44 +5,92 @@ */ import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React, { useState } from 'react'; +import React, { useCallback, useRef, useState } from 'react'; import { Redirect } from 'react-router-dom'; -import { DETECTION_ENGINE_PAGE_NAME } from '../../../components/link_to/redirect_to_detection_engine'; -import { FormattedRelativePreferenceDate } from '../../../components/formatted_date'; -import { getEmptyTagValue } from '../../../components/empty_value'; -import { HeaderPage } from '../../../components/header_page'; +import { usePrePackagedRules } from '../../../containers/detection_engine/rules'; +import { + getDetectionEngineUrl, + getCreateRuleUrl, +} from '../../../components/link_to/redirect_to_detection_engine'; +import { DetectionEngineHeaderPage } from '../components/detection_engine_header_page'; import { WrapperPage } from '../../../components/wrapper_page'; import { SpyRoute } from '../../../utils/route/spy_routes'; +import { useUserInfo } from '../components/user_info'; import { AllRules } from './all'; import { ImportRuleModal } from './components/import_rule_modal'; import { ReadOnlyCallOut } from './components/read_only_callout'; -import { useUserInfo } from '../components/user_info'; +import { UpdatePrePackagedRulesCallOut } from './components/pre_packaged_rules/update_callout'; +import { getPrePackagedRuleStatus } from './helpers'; import * as i18n from './translations'; -export const RulesComponent = React.memo(() => { +type Func = () => void; + +const RulesPageComponent: React.FC = () => { const [showImportModal, setShowImportModal] = useState(false); const [importCompleteToggle, setImportCompleteToggle] = useState(false); + const refreshRulesData = useRef(null); const { loading, isSignalIndexExists, isAuthenticated, canUserCRUD, + hasIndexWrite, hasManageApiKey, } = useUserInfo(); + const { + createPrePackagedRules, + loading: prePackagedRuleLoading, + loadingCreatePrePackagedRules, + refetchPrePackagedRulesStatus, + rulesCustomInstalled, + rulesInstalled, + rulesNotInstalled, + rulesNotUpdated, + } = usePrePackagedRules({ + canUserCRUD, + hasIndexWrite, + hasManageApiKey, + isSignalIndexExists, + isAuthenticated, + }); + const prePackagedRuleStatus = getPrePackagedRuleStatus( + rulesInstalled, + rulesNotInstalled, + rulesNotUpdated + ); + + const userHasNoPermissions = + canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; + + const handleCreatePrePackagedRules = useCallback(async () => { + if (createPrePackagedRules != null) { + await createPrePackagedRules(); + if (refreshRulesData.current != null) { + refreshRulesData.current(); + } + } + }, [createPrePackagedRules, refreshRulesData]); + + const handleRefetchPrePackagedRulesStatus = useCallback(() => { + if (refetchPrePackagedRulesStatus != null) { + refetchPrePackagedRulesStatus(); + } + }, [refetchPrePackagedRulesStatus]); + + const handleSetRefreshRulesData = useCallback((refreshRule: Func) => { + refreshRulesData.current = refreshRule; + }, []); if ( isSignalIndexExists != null && isAuthenticated != null && (!isSignalIndexExists || !isAuthenticated) ) { - return ; + return ; } - const userHasNoPermissions = - canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; - const lastCompletedRun = undefined; + return ( <> {userHasNoPermissions && } @@ -52,27 +100,38 @@ export const RulesComponent = React.memo(() => { importComplete={() => setImportCompleteToggle(!importCompleteToggle)} /> - , - }} - /> - ) : ( - getEmptyTagValue() - ) - } title={i18n.PAGE_TITLE} > + {prePackagedRuleStatus === 'ruleNotInstalled' && ( + + + {i18n.LOAD_PREPACKAGED_RULES} + + + )} + {prePackagedRuleStatus === 'someRuleUninstall' && ( + + + {i18n.RELOAD_MISSING_PREPACKAGED_RULES(rulesNotInstalled ?? 0)} + + + )} { @@ -95,17 +154,32 @@ export const RulesComponent = React.memo(() => { - + + {prePackagedRuleStatus === 'ruleNeedUpdate' && ( + + )} ); -}); +}; -RulesComponent.displayName = 'RulesComponent'; +export const RulesPage = React.memo(RulesPageComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts index e1257007d44a3b..5b1ee049371d28 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts @@ -25,6 +25,14 @@ export const PAGE_TITLE = i18n.translate('xpack.siem.detectionEngine.rules.pageT defaultMessage: 'Signal detection rules', }); +export const ADD_PAGE_TITLE = i18n.translate('xpack.siem.detectionEngine.rules.addPageTitle', { + defaultMessage: 'Create', +}); + +export const EDIT_PAGE_TITLE = i18n.translate('xpack.siem.detectionEngine.rules.editPageTitle', { + defaultMessage: 'Edit', +}); + export const REFRESH = i18n.translate('xpack.siem.detectionEngine.rules.allRules.refreshTitle', { defaultMessage: 'Refresh', }); @@ -205,10 +213,10 @@ export const COLUMN_RULE = i18n.translate( } ); -export const COLUMN_METHOD = i18n.translate( - 'xpack.siem.detectionEngine.rules.allRules.columns.methodTitle', +export const COLUMN_RISK_SCORE = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.columns.riskScoreTitle', { - defaultMessage: 'Method', + defaultMessage: 'Risk score', } ); @@ -247,16 +255,42 @@ export const COLUMN_ACTIVATE = i18n.translate( } ); -export const COLUMN_STATUS = i18n.translate( - 'xpack.siem.detectionEngine.rules.allRules.columns.currentStatusTitle', +export const CUSTOM_RULES = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.customRulesTitle', + { + defaultMessage: 'Custom rules', + } +); + +export const ELASTIC_RULES = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.elasticRulesTitle', + { + defaultMessage: 'Elastic rules', + } +); + +export const TAGS = i18n.translate('xpack.siem.detectionEngine.rules.allRules.filters.tagsLabel', { + defaultMessage: 'Tags', +}); + +export const NO_TAGS_AVAILABLE = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.noTagsAvailableDescription', + { + defaultMessage: 'No tags available', + } +); + +export const NO_RULES = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.noRulesTitle', { - defaultMessage: 'Current status', + defaultMessage: 'No rules found', } ); -export const NO_STATUS = i18n.translate( - 'xpack.siem.detectionEngine.rules.allRules.columns.unknownStatusDescription', + +export const NO_RULES_BODY = i18n.translate( + 'xpack.siem.detectionEngine.rules.allRules.filters.noRulesBodyTitle', { - defaultMessage: 'Unknown', + defaultMessage: "We weren't able to find any rules with the above filters.", } ); @@ -302,3 +336,17 @@ export const UPDATE = i18n.translate('xpack.siem.detectionEngine.rules.updateBut export const DELETE = i18n.translate('xpack.siem.detectionEngine.rules.deleteDescription', { defaultMessage: 'Delete', }); + +export const LOAD_PREPACKAGED_RULES = i18n.translate( + 'xpack.siem.detectionEngine.rules.loadPrePackagedRulesButton', + { + defaultMessage: 'Load Elastic prebuilt rules', + } +); + +export const RELOAD_MISSING_PREPACKAGED_RULES = (missingRules: number) => + i18n.translate('xpack.siem.detectionEngine.rules.reloadMissingPrePackagedRulesButton', { + values: { missingRules }, + defaultMessage: + 'Reload {missingRules} deleted Elastic prebuilt {missingRules, plural, =1 {rule} other {rules}} ', + }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts index 5ae516dda5b389..effaa90d685df4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts @@ -30,15 +30,9 @@ export interface TableData { rule: { href: string; name: string; - status: string; }; - method: string; + risk_score: number; severity: string; - lastCompletedRun: string | undefined; - lastResponse: { - type: string; - message?: string; - }; tags: string[]; activate: boolean; isLoading: boolean; @@ -82,7 +76,7 @@ export interface AboutStepRule extends StepRuleData { falsePositives: string[]; tags: string[]; timeline: FieldValueTimeline; - threats: IMitreEnterpriseAttack[]; + threat: IMitreEnterpriseAttack[]; } export interface DefineStepRule extends StepRuleData { @@ -115,7 +109,7 @@ export interface AboutStepRuleJson { tags: string[]; timeline_id?: string; timeline_title?: string; - threats: IMitreEnterpriseAttack[]; + threat: IMitreEnterpriseAttack[]; } export interface ScheduleStepRuleJson { @@ -140,5 +134,5 @@ export interface IMitreAttack { export interface IMitreEnterpriseAttack { framework: string; tactic: IMitreAttack; - techniques: IMitreAttack[]; + technique: IMitreAttack[]; } diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/utils.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/utils.ts new file mode 100644 index 00000000000000..55772aa73ecf33 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/utils.ts @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Breadcrumb } from 'ui/chrome'; +import { isEmpty } from 'lodash/fp'; + +import { + getDetectionEngineUrl, + getDetectionEngineTabUrl, + getRulesUrl, + getRuleDetailsUrl, + getCreateRuleUrl, + getEditRuleUrl, +} from '../../../components/link_to/redirect_to_detection_engine'; +import * as i18nDetections from '../translations'; +import * as i18nRules from './translations'; +import { RouteSpyState } from '../../../utils/route/types'; + +const getTabBreadcrumb = (pathname: string, search: string[]) => { + const tabPath = pathname.split('/')[2]; + + if (tabPath === 'alerts') { + return { + text: i18nDetections.ALERT, + href: `${getDetectionEngineTabUrl(tabPath)}${!isEmpty(search[0]) ? search[0] : ''}`, + }; + } + + if (tabPath === 'signals') { + return { + text: i18nDetections.SIGNAL, + href: `${getDetectionEngineTabUrl(tabPath)}${!isEmpty(search[0]) ? search[0] : ''}`, + }; + } + + if (tabPath === 'rules') { + return { + text: i18nRules.PAGE_TITLE, + href: `${getRulesUrl()}${!isEmpty(search[0]) ? search[0] : ''}`, + }; + } +}; + +const isRuleCreatePage = (pathname: string) => + pathname.includes('/rules') && pathname.includes('/create'); + +const isRuleEditPage = (pathname: string) => + pathname.includes('/rules') && pathname.includes('/edit'); + +export const getBreadcrumbs = (params: RouteSpyState, search: string[]): Breadcrumb[] => { + let breadcrumb = [ + { + text: i18nDetections.PAGE_TITLE, + href: `${getDetectionEngineUrl()}${!isEmpty(search[0]) ? search[0] : ''}`, + }, + ]; + + const tabBreadcrumb = getTabBreadcrumb(params.pathName, search); + + if (tabBreadcrumb) { + breadcrumb = [...breadcrumb, tabBreadcrumb]; + } + + if (params.detailName && params.state?.ruleName) { + breadcrumb = [ + ...breadcrumb, + { + text: params.state.ruleName, + href: `${getRuleDetailsUrl(params.detailName)}${!isEmpty(search[1]) ? search[1] : ''}`, + }, + ]; + } + + if (isRuleCreatePage(params.pathName)) { + breadcrumb = [ + ...breadcrumb, + { + text: i18nRules.ADD_PAGE_TITLE, + href: `${getCreateRuleUrl()}${!isEmpty(search[1]) ? search[1] : ''}`, + }, + ]; + } + + if (isRuleEditPage(params.pathName) && params.detailName && params.state?.ruleName) { + breadcrumb = [ + ...breadcrumb, + { + text: i18nRules.EDIT_PAGE_TITLE, + href: `${getEditRuleUrl(params.detailName)}${!isEmpty(search[1]) ? search[1] : ''}`, + }, + ]; + } + + return breadcrumb; +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/translations.ts index ab785a8ad2c6d8..dd4acaeaf5a028 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/translations.ts @@ -19,11 +19,11 @@ export const TOTAL_SIGNAL = i18n.translate('xpack.siem.detectionEngine.totalSign }); export const SIGNAL = i18n.translate('xpack.siem.detectionEngine.signalTitle', { - defaultMessage: 'Signals', + defaultMessage: 'Signals (SIEM Detections)', }); export const ALERT = i18n.translate('xpack.siem.detectionEngine.alertTitle', { - defaultMessage: 'Third-party alerts', + defaultMessage: 'External alerts', }); export const BUTTON_MANAGE_RULES = i18n.translate('xpack.siem.detectionEngine.buttonManageRules', { diff --git a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx index b5bfdbde306caf..5cfed4121ba77f 100644 --- a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx @@ -19,7 +19,7 @@ import { MlNetworkConditionalContainer } from '../../components/ml/conditional_l import { StatefulTimeline } from '../../components/timeline'; import { AutoSaveWarningMsg } from '../../components/timeline/auto_save_warning'; import { UseUrlState } from '../../components/url_state'; -import { WithSource } from '../../containers/source'; +import { WithSource, indicesExistOrDataTemporarilyUnavailable } from '../../containers/source'; import { SpyRoute } from '../../utils/route/spy_routes'; import { NotFoundPage } from '../404'; import { DetectionEngineContainer } from '../detection_engine'; @@ -63,28 +63,32 @@ export const HomePage: React.FC = () => (
    - {({ browserFields, indexPattern }) => ( + {({ browserFields, indexPattern, indicesExist }) => ( - - - - + {indicesExistOrDataTemporarilyUnavailable(indicesExist) && ( + <> + + + + + + )} diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/utils.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/details/utils.ts index 52e016502940b1..c321478f101741 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/utils.ts +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/utils.ts @@ -5,8 +5,8 @@ */ import { Breadcrumb } from 'ui/chrome'; +import { get, isEmpty } from 'lodash/fp'; -import { get } from 'lodash/fp'; import { hostsModel } from '../../../store'; import { HostsTableType } from '../../../store/hosts/model'; import { getHostsUrl, getHostDetailsUrl } from '../../../components/link_to/redirect_to_hosts'; @@ -29,7 +29,7 @@ export const getBreadcrumbs = (params: HostRouteSpyState, search: string[]): Bre let breadcrumb = [ { text: i18n.PAGE_TITLE, - href: `${getHostsUrl()}${search && search[0] ? search[0] : ''}`, + href: `${getHostsUrl()}${!isEmpty(search[0]) ? search[0] : ''}`, }, ]; @@ -38,7 +38,7 @@ export const getBreadcrumbs = (params: HostRouteSpyState, search: string[]): Bre ...breadcrumb, { text: params.detailName, - href: `${getHostDetailsUrl(params.detailName)}${search && search[1] ? search[1] : ''}`, + href: `${getHostDetailsUrl(params.detailName)}${!isEmpty(search[1]) ? search[1] : ''}`, }, ]; } diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/translations.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/translations.ts index 011e1a8574ae4b..b8c8779ae0f24b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/translations.ts @@ -47,7 +47,7 @@ export const NAVIGATION_EVENTS_TITLE = i18n.translate('xpack.siem.hosts.navigati }); export const NAVIGATION_ALERTS_TITLE = i18n.translate('xpack.siem.hosts.navigation.alertsTitle', { - defaultMessage: 'Alerts', + defaultMessage: 'External alerts', }); export const ERROR_FETCHING_AUTHENTICATIONS_DATA = i18n.translate( diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/utils.ts b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/utils.ts index fed832167a60e7..a468812e2718d3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/utils.ts +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/utils.ts @@ -5,8 +5,8 @@ */ import { Breadcrumb } from 'ui/chrome'; +import { get, isEmpty } from 'lodash/fp'; -import { get } from 'lodash/fp'; import { decodeIpv6 } from '../../../lib/helpers'; import { getNetworkUrl, getIPDetailsUrl } from '../../../components/link_to/redirect_to_network'; import { networkModel } from '../../../store/network'; @@ -28,7 +28,7 @@ export const getBreadcrumbs = (params: NetworkRouteSpyState, search: string[]): let breadcrumb = [ { text: i18n.PAGE_TITLE, - href: `${getNetworkUrl()}${search && search[0] ? search[0] : ''}`, + href: `${getNetworkUrl()}${!isEmpty(search[0]) ? search[0] : ''}`, }, ]; if (params.detailName != null) { @@ -37,7 +37,7 @@ export const getBreadcrumbs = (params: NetworkRouteSpyState, search: string[]): { text: decodeIpv6(params.detailName), href: `${getIPDetailsUrl(params.detailName, params.flowTarget)}${ - search && search[1] ? search[1] : '' + !isEmpty(search[1]) ? search[1] : '' }`, }, ]; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/translations.ts b/x-pack/legacy/plugins/siem/public/pages/network/translations.ts index e5e7144c3ca0e9..5d80ded0aa66b9 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/network/translations.ts @@ -45,7 +45,7 @@ export const NAVIGATION_ANOMALIES_TITLE = i18n.translate( ); export const NAVIGATION_ALERTS_TITLE = i18n.translate('xpack.siem.network.navigation.alertsTitle', { - defaultMessage: 'Alerts', + defaultMessage: 'External alerts', }); export const DOMAINS_COUNT_BY = (groupByField: string) => diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/event_counts/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/event_counts/index.tsx index d0bb46a1965dc6..2a35dbf96d6d7e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/event_counts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/event_counts/index.tsx @@ -37,44 +37,49 @@ interface Props { to: number; } -export const EventCounts = React.memo( - ({ filters = NO_FILTERS, from, indexPattern, query = DEFAULT_QUERY, setQuery, to }) => { - const kibana = useKibana(); +const EventCountsComponent: React.FC = ({ + filters = NO_FILTERS, + from, + indexPattern, + query = DEFAULT_QUERY, + setQuery, + to, +}) => { + const kibana = useKibana(); - return ( - - - - + return ( + + + + - + - - - - - ); - } -); + + + + + ); +}; -EventCounts.displayName = 'EventCounts'; +export const EventCounts = React.memo(EventCountsComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx index 572a19ca67b8a8..9ce7b8b0f71dc2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx @@ -14,7 +14,6 @@ import styled from 'styled-components'; import { AlertsByCategory } from './alerts_by_category'; import { FiltersGlobal } from '../../components/filters_global'; -import { HeaderPage } from '../../components/header_page'; import { SiemSearchBar } from '../../components/search_bar'; import { WrapperPage } from '../../components/wrapper_page'; import { GlobalTime } from '../../containers/global_time'; @@ -29,10 +28,9 @@ import { inputsSelectors, State } from '../../store'; import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { SpyRoute } from '../../utils/route/spy_routes'; -import * as i18n from './translations'; - const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; const NO_FILTERS: esFilters.Filter[] = []; + const SidebarFlexItem = styled(EuiFlexItem)` margin-right: 24px; `; @@ -43,95 +41,94 @@ interface OverviewComponentReduxProps { setAbsoluteRangeDatePicker?: SetAbsoluteRangeDatePicker; } -const OverviewComponent = React.memo( - ({ filters = NO_FILTERS, query = DEFAULT_QUERY, setAbsoluteRangeDatePicker }) => ( - <> - - {({ indicesExist, indexPattern }) => - indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - - - - - - - - - - - {({ from, deleteQuery, setQuery, to }) => ( - <> - - - - - - - - - - - - - - - )} - - - - - - ) : ( - - ) - } - - - - - ) +const OverviewComponent: React.FC = ({ + filters = NO_FILTERS, + query = DEFAULT_QUERY, + setAbsoluteRangeDatePicker, +}) => ( + <> + + {({ indicesExist, indexPattern }) => + indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( + + + + + + + + + + + + + + {({ from, deleteQuery, setQuery, to }) => ( + <> + + + + + + + + + + + + + + + )} + + + + + + ) : ( + + ) + } + + + + ); -OverviewComponent.displayName = 'OverviewComponent'; - const makeMapStateToProps = () => { const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); @@ -144,6 +141,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; +const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker }; + export const StatefulOverview = compose>( - connect(makeMapStateToProps, { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker }) -)(OverviewComponent); + connect(makeMapStateToProps, mapDispatchToProps) +)(React.memo(OverviewComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/signals_by_category/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/signals_by_category/index.tsx index ce6e6ccf4e9e30..fcf726723bdc1c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/signals_by_category/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/signals_by_category/index.tsx @@ -7,16 +7,17 @@ import React, { useCallback } from 'react'; import { esFilters, IIndexPattern, Query } from 'src/plugins/data/public'; +import { useSignalIndex } from '../../../containers/detection_engine/signals/use_signal_index'; import { SignalsHistogramPanel } from '../../detection_engine/components/signals_histogram_panel'; import { SetAbsoluteRangeDatePicker } from '../../network/types'; import { inputsModel } from '../../../store'; - import * as i18n from '../translations'; const NO_FILTERS: esFilters.Filter[] = []; const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; interface Props { + deleteQuery?: ({ id }: { id: string }) => void; filters?: esFilters.Filter[]; from: number; indexPattern: IIndexPattern; @@ -32,26 +33,40 @@ interface Props { } export const SignalsByCategory = React.memo( - ({ filters = NO_FILTERS, from, query = DEFAULT_QUERY, setAbsoluteRangeDatePicker, to }) => { + ({ + deleteQuery, + filters = NO_FILTERS, + from, + query = DEFAULT_QUERY, + setAbsoluteRangeDatePicker, + setQuery, + to, + }) => { const updateDateRangeCallback = useCallback( (min: number, max: number) => { setAbsoluteRangeDatePicker!({ id: 'global', from: min, to: max }); }, [setAbsoluteRangeDatePicker] ); + const defaultStackByOption = { + text: `${i18n.SIGNALS_BY_CATEGORY}`, + value: 'signal.rule.threat', + }; + + const { signalIndexName } = useSignalIndex(); return ( }); export const ALERTS_GRAPH_TITLE = i18n.translate('xpack.siem.overview.alertsGraphTitle', { - defaultMessage: 'Alert detection frequency', + defaultMessage: 'External alerts count', }); export const EVENTS_COUNT_BY = (groupByField: string) => @@ -34,15 +34,6 @@ export const PAGE_SUBTITLE = i18n.translate('xpack.siem.overview.pageSubtitle', defaultMessage: 'Security Information & Event Management with the Elastic Stack', }); -export const PAGE_BADGE_LABEL = i18n.translate('xpack.siem.overview.pageBadgeLabel', { - defaultMessage: 'Beta', -}); - -export const PAGE_BADGE_TOOLTIP = i18n.translate('xpack.siem.overview.pageBadgeTooltip', { - defaultMessage: - 'SIEM is still in beta. Please help us improve by reporting issues or bugs in the Kibana repo.', -}); - export const RECENT_TIMELINES = i18n.translate('xpack.siem.overview.recentTimelinesSidebarTitle', { defaultMessage: 'Recent timelines', }); diff --git a/x-pack/legacy/plugins/siem/public/plugin.tsx b/x-pack/legacy/plugins/siem/public/plugin.tsx index 44624f497a91be..057ed3a91c3b9e 100644 --- a/x-pack/legacy/plugins/siem/public/plugin.tsx +++ b/x-pack/legacy/plugins/siem/public/plugin.tsx @@ -16,11 +16,14 @@ import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; import { IEmbeddableStart } from '../../../../../src/plugins/embeddable/public'; import { Start as InspectorStart } from '../../../../../src/plugins/inspector/public'; import { IUiActionsStart } from '../../../../../src/plugins/ui_actions/public'; +import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public'; +import { initTelemetry } from './lib/telemetry'; export { AppMountParameters, CoreSetup, CoreStart, PluginInitializerContext }; export interface SetupPlugins { home: HomePublicPluginSetup; + usageCollection: UsageCollectionSetup; } export interface StartPlugins { data: DataPublicPluginStart; @@ -43,6 +46,8 @@ export class Plugin implements IPlugin { ) {} public setup(core: CoreSetup, plugins: SetupPlugins) { + initTelemetry(plugins.usageCollection, this.id); + core.application.register({ id: this.id, title: this.name, diff --git a/x-pack/legacy/plugins/siem/public/store/store.ts b/x-pack/legacy/plugins/siem/public/store/store.ts index b56132967d1e3a..d3559e7a7adde9 100644 --- a/x-pack/legacy/plugins/siem/public/store/store.ts +++ b/x-pack/legacy/plugins/siem/public/store/store.ts @@ -10,6 +10,7 @@ import { createEpicMiddleware } from 'redux-observable'; import { Observable } from 'rxjs'; import { AppApolloClient } from '../lib/lib'; +import { telemetryMiddleware } from '../lib/telemetry'; import { appSelectors } from './app'; import { timelineSelectors } from './timeline'; import { inputsSelectors } from './inputs'; @@ -42,7 +43,11 @@ export const createStore = ( } ); - store = createReduxStore(reducer, state, composeEnhancers(applyMiddleware(epicMiddleware))); + store = createReduxStore( + reducer, + state, + composeEnhancers(applyMiddleware(epicMiddleware, telemetryMiddleware)) + ); epicMiddleware.run(createRootEpic()); diff --git a/x-pack/legacy/plugins/siem/public/utils/route/helpers.ts b/x-pack/legacy/plugins/siem/public/utils/route/helpers.ts index 188ae9c6c1866d..39efccc9f45b85 100644 --- a/x-pack/legacy/plugins/siem/public/utils/route/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/utils/route/helpers.ts @@ -15,6 +15,7 @@ export const initRouteSpy: RouteSpyState = { tabName: undefined, search: '', pathName: '/', + state: undefined, }; export const RouterSpyStateContext = createContext<[RouteSpyState, Dispatch]>([ diff --git a/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx b/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx index 5c24b2f48488d8..c88562abef6ae0 100644 --- a/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx +++ b/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx @@ -8,6 +8,7 @@ import * as H from 'history'; import { isEqual } from 'lodash/fp'; import { memo, useEffect, useState } from 'react'; import { withRouter } from 'react-router-dom'; +import deepEqual from 'fast-deep-equal'; import { SpyRouteProps } from './types'; import { useRouteSpy } from './use_route_spy'; @@ -19,6 +20,7 @@ export const SpyRouteComponent = memo( match: { params: { pageName, detailName, tabName, flowTarget }, }, + state, }) => { const [isInitializing, setIsInitializing] = useState(true); const [route, dispatch] = useRouteSpy(); @@ -61,8 +63,24 @@ export const SpyRouteComponent = memo( }, }); } + } else { + if (pageName && !deepEqual(state, route.state)) { + dispatch({ + type: 'updateRoute', + route: { + pageName, + detailName, + tabName, + search, + pathName: pathname, + history, + flowTarget, + state, + }, + }); + } } - }, [pathname, search, pageName, detailName, tabName, flowTarget]); + }, [pathname, search, pageName, detailName, tabName, flowTarget, state]); return null; } ); diff --git a/x-pack/legacy/plugins/siem/public/utils/route/types.ts b/x-pack/legacy/plugins/siem/public/utils/route/types.ts index 79d2677eff06f6..d3eca36bd0d96d 100644 --- a/x-pack/legacy/plugins/siem/public/utils/route/types.ts +++ b/x-pack/legacy/plugins/siem/public/utils/route/types.ts @@ -21,6 +21,7 @@ export interface RouteSpyState { pathName: string; history?: H.History; flowTarget?: FlowTarget; + state?: Record; } export interface HostRouteSpyState extends RouteSpyState { @@ -38,7 +39,10 @@ export type RouteSpyAction = } | { type: 'updateRouteWithOutSearch'; - route: Pick; + route: Pick< + RouteSpyState, + 'pageName' & 'detailName' & 'tabName' & 'pathName' & 'history' & 'state' + >; } | { type: 'updateRoute'; @@ -55,4 +59,6 @@ export type SpyRouteProps = RouteComponentProps<{ tabName: HostsTableType | undefined; search: string; flowTarget: FlowTarget | undefined; -}>; +}> & { + state?: Record; +}; diff --git a/x-pack/legacy/plugins/siem/scripts/convert_saved_search_to_rules.js b/x-pack/legacy/plugins/siem/scripts/convert_saved_search_to_rules.js index 4243e67ca1320c..233d4dd7de721e 100644 --- a/x-pack/legacy/plugins/siem/scripts/convert_saved_search_to_rules.js +++ b/x-pack/legacy/plugins/siem/scripts/convert_saved_search_to_rules.js @@ -114,7 +114,6 @@ async function main() { ); return [...accum, parsedLine]; } catch (err) { - console.log('error parsing a line in this file:', json, line); return accum; } }, []); diff --git a/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts index 9f57155d4d1890..730e6b884a1825 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts @@ -399,7 +399,7 @@ export const ecsSchema = gql` references: ToStringArray severity: ToStringArray tags: ToStringArray - threats: ToAny + threat: ToAny type: ToStringArray size: ToStringArray to: ToStringArray diff --git a/x-pack/legacy/plugins/siem/server/graphql/overview/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/overview/schema.gql.ts index bbb93ac42b6da1..7ab4f9fdb18d6c 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/overview/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/overview/schema.gql.ts @@ -35,7 +35,8 @@ export const overviewSchema = gql` endgameRegistry: Float endgameSecurity: Float filebeatSystemModule: Float - winlogbeat: Float + winlogbeatSecurity: Float + winlogbeatMWSysmonOperational: Float inspect: Inspect } diff --git a/x-pack/legacy/plugins/siem/server/graphql/types.ts b/x-pack/legacy/plugins/siem/server/graphql/types.ts index 4a2119b6f76313..303262ece5c7f1 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/types.ts @@ -1017,7 +1017,7 @@ export interface RuleField { tags?: Maybe; - threats?: Maybe; + threat?: Maybe; type?: Maybe; @@ -1849,7 +1849,9 @@ export interface OverviewHostData { filebeatSystemModule?: Maybe; - winlogbeat?: Maybe; + winlogbeatSecurity?: Maybe; + + winlogbeatMWSysmonOperational?: Maybe; inspect?: Maybe; } @@ -4992,7 +4994,7 @@ export namespace RuleFieldResolvers { tags?: TagsResolver, TypeParent, TContext>; - threats?: ThreatsResolver, TypeParent, TContext>; + threat?: ThreatResolver, TypeParent, TContext>; type?: TypeResolver, TypeParent, TContext>; @@ -5110,7 +5112,7 @@ export namespace RuleFieldResolvers { Parent = RuleField, TContext = SiemContext > = Resolver; - export type ThreatsResolver< + export type ThreatResolver< R = Maybe, Parent = RuleField, TContext = SiemContext @@ -7831,7 +7833,13 @@ export namespace OverviewHostDataResolvers { filebeatSystemModule?: FilebeatSystemModuleResolver, TypeParent, TContext>; - winlogbeat?: WinlogbeatResolver, TypeParent, TContext>; + winlogbeatSecurity?: WinlogbeatSecurityResolver, TypeParent, TContext>; + + winlogbeatMWSysmonOperational?: WinlogbeatMwSysmonOperationalResolver< + Maybe, + TypeParent, + TContext + >; inspect?: InspectResolver, TypeParent, TContext>; } @@ -7906,7 +7914,12 @@ export namespace OverviewHostDataResolvers { Parent = OverviewHostData, TContext = SiemContext > = Resolver; - export type WinlogbeatResolver< + export type WinlogbeatSecurityResolver< + R = Maybe, + Parent = OverviewHostData, + TContext = SiemContext + > = Resolver; + export type WinlogbeatMwSysmonOperationalResolver< R = Maybe, Parent = OverviewHostData, TContext = SiemContext diff --git a/x-pack/legacy/plugins/siem/server/lib/alerts/query.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/alerts/query.dsl.ts index 08015c3508b868..eb823271975439 100644 --- a/x-pack/legacy/plugins/siem/server/lib/alerts/query.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/alerts/query.dsl.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query'; +import { createQueryFilterClauses, calculateTimeSeriesInterval } from '../../utils/build_query'; import { buildTimelineQuery } from '../events/query.dsl'; import { RequestOptions, MatrixHistogramRequestOptions } from '../framework'; @@ -68,18 +68,17 @@ export const buildAlertsHistogramQuery = ({ ]; const getHistogramAggregation = () => { - const interval = calculateTimeseriesInterval(from, to); + const interval = calculateTimeSeriesInterval(from, to); const histogramTimestampField = '@timestamp'; const dateHistogram = { date_histogram: { field: histogramTimestampField, - fixed_interval: `${interval}s`, - }, - }; - const autoDateHistogram = { - auto_date_histogram: { - field: histogramTimestampField, - buckets: 36, + fixed_interval: interval, + min_doc_count: 0, + extended_bounds: { + min: from, + max: to, + }, }, }; return { @@ -93,7 +92,7 @@ export const buildAlertsHistogramQuery = ({ size: 10, }, aggs: { - alerts: interval ? dateHistogram : autoDateHistogram, + alerts: dateHistogram, }, }, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/anomalies/query.anomalies_over_time.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/anomalies/query.anomalies_over_time.dsl.ts index b0892a68f0a2e8..38e8387f43ffde 100644 --- a/x-pack/legacy/plugins/siem/server/lib/anomalies/query.anomalies_over_time.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/anomalies/query.anomalies_over_time.dsl.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query'; +import { createQueryFilterClauses, calculateTimeSeriesInterval } from '../../utils/build_query'; import { MatrixHistogramRequestOptions } from '../framework'; export const buildAnomaliesOverTimeQuery = ({ @@ -26,18 +26,17 @@ export const buildAnomaliesOverTimeQuery = ({ ]; const getHistogramAggregation = () => { - const interval = calculateTimeseriesInterval(from, to); + const interval = calculateTimeSeriesInterval(from, to); const histogramTimestampField = 'timestamp'; const dateHistogram = { date_histogram: { field: histogramTimestampField, - fixed_interval: `${interval}s`, - }, - }; - const autoDateHistogram = { - auto_date_histogram: { - field: histogramTimestampField, - buckets: 36, + fixed_interval: interval, + min_doc_count: 0, + extended_bounds: { + min: from, + max: to, + }, }, }; return { @@ -50,7 +49,7 @@ export const buildAnomaliesOverTimeQuery = ({ size: 10, }, aggs: { - anomalies: interval ? dateHistogram : autoDateHistogram, + anomalies: dateHistogram, }, }, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/authentications/query.authentications_over_time.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/authentications/query.authentications_over_time.dsl.ts index 77b35fef77dcaf..ccf0d235abdd3a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/authentications/query.authentications_over_time.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/authentications/query.authentications_over_time.dsl.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query'; +import { createQueryFilterClauses, calculateTimeSeriesInterval } from '../../utils/build_query'; import { MatrixHistogramRequestOptions } from '../framework'; export const buildAuthenticationsOverTimeQuery = ({ @@ -28,18 +28,17 @@ export const buildAuthenticationsOverTimeQuery = ({ ]; const getHistogramAggregation = () => { - const interval = calculateTimeseriesInterval(from, to); + const interval = calculateTimeSeriesInterval(from, to); const histogramTimestampField = '@timestamp'; const dateHistogram = { date_histogram: { field: histogramTimestampField, - fixed_interval: `${interval}s`, - }, - }; - const autoDateHistogram = { - auto_date_histogram: { - field: histogramTimestampField, - buckets: 36, + fixed_interval: interval, + min_doc_count: 0, + extended_bounds: { + min: from, + max: to, + }, }, }; return { @@ -53,7 +52,7 @@ export const buildAuthenticationsOverTimeQuery = ({ size: 2, }, aggs: { - events: interval ? dateHistogram : autoDateHistogram, + events: dateHistogram, }, }, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/README.md b/x-pack/legacy/plugins/siem/server/lib/detection_engine/README.md index 7c22d6334a2d13..1d33466a458d23 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/README.md +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/README.md @@ -94,7 +94,7 @@ You should see the new rules created like so: "interval": "5m", "rule_id": "rule-1", "language": "kuery", - "output_index": ".siem-signals-frank-hassanabad", + "output_index": ".siem-signals-some-name", "max_signals": 100, "risk_score": 1, "name": "Detect Root/Admin Users", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/create_bootstrap_index.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/create_bootstrap_index.ts index d7cb922b5b6c38..dff6e7136bff2b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/create_bootstrap_index.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/create_bootstrap_index.ts @@ -19,7 +19,7 @@ export const createBootstrapIndex = async ( index: string ): Promise => { return callWithRequest('transport.request', { - path: `${index}-000001`, + path: `/${index}-000001`, method: 'PUT', body: { aliases: { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/delete_policy.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/delete_policy.ts index 92003f165d9962..aa31c427ec84f8 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/delete_policy.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/delete_policy.ts @@ -11,7 +11,7 @@ export const deletePolicy = async ( policy: string ): Promise => { return callWithRequest('transport.request', { - path: `_ilm/policy/${policy}`, + path: `/_ilm/policy/${policy}`, method: 'DELETE', }); }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/get_policy_exists.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/get_policy_exists.ts index 7541c4217b387e..d5ab1a10180c0e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/get_policy_exists.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/get_policy_exists.ts @@ -12,7 +12,7 @@ export const getPolicyExists = async ( ): Promise => { try { await callWithRequest('transport.request', { - path: `_ilm/policy/${policy}`, + path: `/_ilm/policy/${policy}`, method: 'GET', }); // Return true that there exists a policy which is not 404 or some error diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/set_policy.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/set_policy.ts index 115f0af75898c7..fae28bab749cad 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/set_policy.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/index/set_policy.ts @@ -12,7 +12,7 @@ export const setPolicy = async ( body: unknown ): Promise => { return callWithRequest('transport.request', { - path: `_ilm/policy/${policy}`, + path: `/_ilm/policy/${policy}`, method: 'PUT', body, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/privileges/read_privileges.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/privileges/read_privileges.ts index 3b84075b9e435a..a93be40738e570 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/privileges/read_privileges.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/privileges/read_privileges.ts @@ -11,7 +11,7 @@ export const readPrivileges = async ( index: string ): Promise => { return callWithRequest('transport.request', { - path: `_security/user/_has_privileges`, + path: '/_security/user/_has_privileges', method: 'POST', body: { cluster: [ diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/_mock_server.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/_mock_server.ts index 8bddd4a1ef456b..4bf7b3279374b8 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/_mock_server.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/_mock_server.ts @@ -9,7 +9,7 @@ import { KibanaConfig } from 'src/legacy/server/kbn_server'; import { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch'; import { savedObjectsClientMock } from '../../../../../../../../../src/core/server/mocks'; import { alertsClientMock } from '../../../../../../alerting/server/alerts_client.mock'; -import { actionsClientMock } from '../../../../../../actions/server/actions_client.mock'; +import { actionsClientMock } from '../../../../../../../../plugins/actions/server/mocks'; import { APP_ID, SIGNALS_INDEX_KEY } from '../../../../../common/constants'; import { ServerFacade } from '../../../../types'; @@ -59,9 +59,12 @@ export const createMockServer = (config: Record = defaultConfig) }; server.decorate('request', 'getAlertsClient', () => alertsClient); server.decorate('request', 'getBasePath', () => '/s/default'); - server.decorate('request', 'getActionsClient', () => actionsClient); server.plugins.elasticsearch = (elasticsearch as unknown) as ElasticsearchPlugin; server.plugins.spaces = { getSpaceId: () => 'default' }; + server.plugins.actions = { + getActionsClientWithRequest: () => actionsClient, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any; // The types have really bad conflicts at the moment so I have to use any server.decorate('request', 'getSavedObjectsClient', () => savedObjectsClient); return { server: server as ServerFacade & Hapi.Server, @@ -79,11 +82,16 @@ export const createMockServerWithoutAlertClientDecoration = ( port: 0, }); + const savedObjectsClient = savedObjectsClientMock.create(); serverWithoutAlertClient.config = () => createMockKibanaConfig(config); + serverWithoutAlertClient.decorate('request', 'getSavedObjectsClient', () => savedObjectsClient); + serverWithoutAlertClient.plugins.actions = { + getActionsClientWithRequest: () => actionsClient, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any; // The types have really bad conflicts at the moment so I have to use any const actionsClient = actionsClientMock.create(); serverWithoutAlertClient.decorate('request', 'getBasePath', () => '/s/default'); - serverWithoutAlertClient.decorate('request', 'getActionsClient', () => actionsClient); return { serverWithoutAlertClient: serverWithoutAlertClient as ServerFacade & Hapi.Server, @@ -91,40 +99,6 @@ export const createMockServerWithoutAlertClientDecoration = ( }; }; -export const createMockServerWithoutActionClientDecoration = ( - config: Record = defaultConfig -) => { - const serverWithoutActionClient = new Hapi.Server({ - port: 0, - }); - - serverWithoutActionClient.config = () => createMockKibanaConfig(config); - - const alertsClient = alertsClientMock.create(); - serverWithoutActionClient.decorate('request', 'getBasePath', () => '/s/default'); - serverWithoutActionClient.decorate('request', 'getAlertsClient', () => alertsClient); - - return { - serverWithoutActionClient: serverWithoutActionClient as ServerFacade & Hapi.Server, - alertsClient, - }; -}; - -export const createMockServerWithoutActionOrAlertClientDecoration = ( - config: Record = defaultConfig -) => { - const serverWithoutActionOrAlertClient = new Hapi.Server({ - port: 0, - }); - - serverWithoutActionOrAlertClient.config = () => createMockKibanaConfig(config); - - return { - serverWithoutActionOrAlertClient: serverWithoutActionOrAlertClient as ServerFacade & - Hapi.Server, - }; -}; - export const getMockIndexName = () => jest.fn().mockImplementation(() => ({ callWithRequest: jest.fn().mockImplementationOnce(() => 'index-name'), diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts index a84fcb64d9ff7c..d950d89eb22a68 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -6,7 +6,7 @@ import { ServerInjectOptions } from 'hapi'; import { SavedObjectsFindResponse } from 'kibana/server'; -import { ActionResult } from '../../../../../../actions/server/types'; +import { ActionResult } from '../../../../../../../../plugins/actions/server'; import { SignalsStatusRestParams, SignalsQueryRestParams } from '../../signals/types'; import { DETECTION_ENGINE_RULES_URL, @@ -34,11 +34,11 @@ export const mockPrepackagedRule = (): PrepackagedRules => ({ severity: 'high', query: 'user.name: root or user.name: admin', language: 'kuery', - threats: [ + threat: [ { framework: 'fake', tactic: { id: 'fakeId', name: 'fakeName', reference: 'fakeRef' }, - techniques: [{ id: 'techniqueId', name: 'techniqueName', reference: 'techniqueRef' }], + technique: [{ id: 'techniqueId', name: 'techniqueName', reference: 'techniqueRef' }], }, ], enabled: true, @@ -69,11 +69,11 @@ export const typicalPayload = (): Partial => ({ severity: 'high', query: 'user.name: root or user.name: admin', language: 'kuery', - threats: [ + threat: [ { framework: 'fake', tactic: { id: 'fakeId', name: 'fakeName', reference: 'fakeRef' }, - techniques: [{ id: 'techniqueId', name: 'techniqueName', reference: 'techniqueRef' }], + technique: [{ id: 'techniqueId', name: 'techniqueName', reference: 'techniqueRef' }], }, ], }); @@ -298,7 +298,7 @@ export const getResult = (): RuleAlertType => ({ severity: 'high', to: 'now', type: 'query', - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -306,7 +306,7 @@ export const getResult = (): RuleAlertType => ({ name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -371,7 +371,7 @@ export const getMockPrivileges = () => ({ create_snapshot: true, }, index: { - '.siem-signals-frank-hassanabad-test-space': { + '.siem-signals-test-space': { all: false, manage_ilm: true, read: false, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/index/signals_mapping.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/index/signals_mapping.json index 00ae5b1f7426bf..4986c100f1b0b5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/index/signals_mapping.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/index/signals_mapping.json @@ -5,6 +5,9 @@ "properties": { "parent": { "properties": { + "rule": { + "type": "keyword" + }, "index": { "type": "keyword" }, @@ -19,6 +22,9 @@ } } }, + "ancestors": { + "type": "object" + }, "rule": { "properties": { "id": { @@ -81,8 +87,38 @@ "tags": { "type": "keyword" }, - "threats": { - "type": "object" + "threat": { + "properties": { + "framework": { + "type": "keyword" + }, + "tactic": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + } + } + } + } }, "type": { "type": "keyword" diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts index ed193b6473a9e7..4b04cb257d4ac5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, getMockEmptyIndex, getMockNonEmptyIndex, } from '../__mocks__/_mock_server'; @@ -34,7 +32,7 @@ jest.mock('../../rules/get_prepackaged_rules', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', version: 2, // set one higher than the mocks which is set to 1 to trigger updates @@ -67,30 +65,12 @@ describe('add_prepackaged_rules_route', () => { expect(statusCode).toBe(200); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - createRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(addPrepackagedRulesRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); createRulesRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(addPrepackagedRulesRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - createRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject( - addPrepackagedRulesRequest() - ); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.ts index 3c9cad8dc4d4b1..28af530272bc77 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.ts @@ -18,6 +18,7 @@ import { updatePrepackagedRules } from '../../rules/update_prepacked_rules'; import { getRulesToInstall } from '../../rules/get_rules_to_install'; import { getRulesToUpdate } from '../../rules/get_rules_to_update'; import { getExistingPrepackagedRules } from '../../rules/get_existing_prepackaged_rules'; +import { KibanaRequest } from '../../../../../../../../../src/core/server'; export const createAddPrepackedRulesRoute = (server: ServerFacade): Hapi.ServerRoute => { return { @@ -33,13 +34,13 @@ export const createAddPrepackedRulesRoute = (server: ServerFacade): Hapi.ServerR }, async handler(request: RequestFacade, headers) { const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) - ? request.getActionsClient() - : null; + const actionsClient = await server.plugins.actions.getActionsClientWithRequest( + KibanaRequest.from((request as unknown) as Hapi.Request) + ); const savedObjectsClient = isFunction(request.getSavedObjectsClient) ? request.getSavedObjectsClient() : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { + if (!alertsClient || !savedObjectsClient) { return headers.response().code(404); } @@ -60,7 +61,9 @@ export const createAddPrepackedRulesRoute = (server: ServerFacade): Hapi.ServerR ); } } - await installPrepackagedRules(alertsClient, actionsClient, rulesToInstall, spaceIndex); + await Promise.all( + installPrepackagedRules(alertsClient, actionsClient, rulesToInstall, spaceIndex) + ); await updatePrepackagedRules( alertsClient, actionsClient, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts index 0931e941f8e464..5cf6d8955d8b2a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, getMockEmptyIndex, } from '../__mocks__/_mock_server'; import { createRulesRoute } from './create_rules_route'; @@ -42,28 +40,12 @@ describe('create_rules_bulk', () => { expect(statusCode).toBe(200); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - createRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(getReadBulkRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); createRulesRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(getReadBulkRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - createRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject(getReadBulkRequest()); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts index 00a1d2eb980ec3..68375043070f89 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts @@ -21,6 +21,7 @@ import { createBulkErrorObject, } from '../utils'; import { createRulesBulkSchema } from '../schemas/create_rules_bulk_schema'; +import { KibanaRequest } from '../../../../../../../../../src/core/server'; export const createCreateRulesBulkRoute = (server: ServerFacade): Hapi.ServerRoute => { return { @@ -37,17 +38,17 @@ export const createCreateRulesBulkRoute = (server: ServerFacade): Hapi.ServerRou }, async handler(request: BulkRulesRequest, headers) { const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) - ? request.getActionsClient() - : null; + const actionsClient = await server.plugins.actions.getActionsClientWithRequest( + KibanaRequest.from((request as unknown) as Hapi.Request) + ); const savedObjectsClient = isFunction(request.getSavedObjectsClient) ? request.getSavedObjectsClient() : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { + if (!alertsClient || !savedObjectsClient) { return headers.response().code(404); } - const rules = Promise.all( + const rules = await Promise.all( request.payload.map(async payloadRule => { const { created_at: createdAt, @@ -69,7 +70,7 @@ export const createCreateRulesBulkRoute = (server: ServerFacade): Hapi.ServerRou name, severity, tags, - threats, + threat, to, type, updated_at: updatedAt, @@ -127,7 +128,7 @@ export const createCreateRulesBulkRoute = (server: ServerFacade): Hapi.ServerRou tags, to, type, - threats, + threat, updatedAt, references, version, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts index 77c6f6f3b4840d..27575fb264f7b4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, getMockNonEmptyIndex, getMockEmptyIndex, } from '../__mocks__/_mock_server'; @@ -58,28 +56,12 @@ describe('create_rules', () => { expect(statusCode).toBe(200); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - createRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(getCreateRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); createRulesRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(getCreateRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - createRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject(getCreateRequest()); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.ts index 23acd12d341ed8..060659d0e1897c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.ts @@ -18,6 +18,7 @@ import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; import { transformOrError } from './utils'; import { getIndexExists } from '../../index/get_index_exists'; import { callWithRequestFactory, getIndex, transformError } from '../utils'; +import { KibanaRequest } from '../../../../../../../../../src/core/server'; export const createCreateRulesRoute = (server: ServerFacade): Hapi.ServerRoute => { return { @@ -55,20 +56,20 @@ export const createCreateRulesRoute = (server: ServerFacade): Hapi.ServerRoute = name, severity, tags, - threats, + threat, to, type, updated_at: updatedAt, references, } = request.payload; const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) - ? request.getActionsClient() - : null; + const actionsClient = await server.plugins.actions.getActionsClientWithRequest( + KibanaRequest.from((request as unknown) as Hapi.Request) + ); const savedObjectsClient = isFunction(request.getSavedObjectsClient) ? request.getSavedObjectsClient() : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { + if (!alertsClient || !savedObjectsClient) { return headers.response().code(404); } @@ -114,7 +115,7 @@ export const createCreateRulesRoute = (server: ServerFacade): Hapi.ServerRoute = tags, to, type, - threats, + threat, updatedAt, references, version: 1, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts index 7b8496b2fe7251..e66fc765c08bf5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, } from '../__mocks__/_mock_server'; import { ServerInjectOptions } from 'hapi'; @@ -97,28 +95,12 @@ describe('delete_rules', () => { expect(parsed).toEqual(expected); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - deleteRulesBulkRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(getDeleteBulkRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); deleteRulesBulkRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(getDeleteBulkRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - deleteRulesBulkRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject(getDeleteBulkRequest()); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts index b77ae56a486c87..c2b5576c091835 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts @@ -15,64 +15,69 @@ import { transformOrBulkError, getIdBulkError } from './utils'; import { transformBulkError } from '../utils'; import { QueryBulkRequest, IRuleSavedAttributesSavedObjectAttributes } from '../../rules/types'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; +import { KibanaRequest } from '../../../../../../../../../src/core/server'; -export const createDeleteRulesBulkRoute: Hapi.ServerRoute = { - method: ['POST', 'DELETE'], // allow both POST and DELETE in case their client does not support bodies in DELETE - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, - options: { - tags: ['access:siem'], - validate: { - options: { - abortEarly: false, +export const createDeleteRulesBulkRoute = (server: ServerFacade): Hapi.ServerRoute => { + return { + method: ['POST', 'DELETE'], // allow both POST and DELETE in case their client does not support bodies in DELETE + path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, + options: { + tags: ['access:siem'], + validate: { + options: { + abortEarly: false, + }, + payload: queryRulesBulkSchema, }, - payload: queryRulesBulkSchema, }, - }, - async handler(request: QueryBulkRequest, headers) { - const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) ? request.getActionsClient() : null; - const savedObjectsClient = isFunction(request.getSavedObjectsClient) - ? request.getSavedObjectsClient() - : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { - return headers.response().code(404); - } - const rules = Promise.all( - request.payload.map(async payloadRule => { - const { id, rule_id: ruleId } = payloadRule; - const idOrRuleIdOrUnknown = id ?? ruleId ?? '(unknown id)'; - try { - const rule = await deleteRules({ - actionsClient, - alertsClient, - id, - ruleId, - }); - if (rule != null) { - const ruleStatuses = await savedObjectsClient.find< - IRuleSavedAttributesSavedObjectAttributes - >({ - type: ruleStatusSavedObjectType, - perPage: 6, - search: rule.id, - searchFields: ['alertId'], + async handler(request: QueryBulkRequest, headers) { + const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; + const actionsClient = await server.plugins.actions.getActionsClientWithRequest( + KibanaRequest.from((request as unknown) as Hapi.Request) + ); + const savedObjectsClient = isFunction(request.getSavedObjectsClient) + ? request.getSavedObjectsClient() + : null; + if (!alertsClient || !savedObjectsClient) { + return headers.response().code(404); + } + const rules = Promise.all( + request.payload.map(async payloadRule => { + const { id, rule_id: ruleId } = payloadRule; + const idOrRuleIdOrUnknown = id ?? ruleId ?? '(unknown id)'; + try { + const rule = await deleteRules({ + actionsClient, + alertsClient, + id, + ruleId, }); - ruleStatuses.saved_objects.forEach(async obj => - savedObjectsClient.delete(ruleStatusSavedObjectType, obj.id) - ); - return transformOrBulkError(idOrRuleIdOrUnknown, rule); - } else { - return getIdBulkError({ id, ruleId }); + if (rule != null) { + const ruleStatuses = await savedObjectsClient.find< + IRuleSavedAttributesSavedObjectAttributes + >({ + type: ruleStatusSavedObjectType, + perPage: 6, + search: rule.id, + searchFields: ['alertId'], + }); + ruleStatuses.saved_objects.forEach(async obj => + savedObjectsClient.delete(ruleStatusSavedObjectType, obj.id) + ); + return transformOrBulkError(idOrRuleIdOrUnknown, rule); + } else { + return getIdBulkError({ id, ruleId }); + } + } catch (err) { + return transformBulkError(idOrRuleIdOrUnknown, err); } - } catch (err) { - return transformBulkError(idOrRuleIdOrUnknown, err); - } - }) - ); - return rules; - }, + }) + ); + return rules; + }, + }; }; export const deleteRulesBulkRoute = (server: ServerFacade): void => { - server.route(createDeleteRulesBulkRoute); + server.route(createDeleteRulesBulkRoute(server)); }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts index 2854312246c5f1..0aa60d3bbd9229 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, } from '../__mocks__/_mock_server'; import { deleteRulesRoute } from './delete_rules_route'; @@ -67,28 +65,12 @@ describe('delete_rules', () => { expect(statusCode).toBe(404); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - deleteRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(getDeleteRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); deleteRulesRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(getDeleteRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - deleteRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject(getDeleteRequest()); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.ts index ea8b54a79a5e3c..33f181cfbb5a5c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.ts @@ -15,59 +15,64 @@ import { getIdError, transformOrError } from './utils'; import { transformError } from '../utils'; import { QueryRequest, IRuleSavedAttributesSavedObjectAttributes } from '../../rules/types'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; +import { KibanaRequest } from '../../../../../../../../../src/core/server'; -export const createDeleteRulesRoute: Hapi.ServerRoute = { - method: 'DELETE', - path: DETECTION_ENGINE_RULES_URL, - options: { - tags: ['access:siem'], - validate: { - options: { - abortEarly: false, +export const createDeleteRulesRoute = (server: ServerFacade): Hapi.ServerRoute => { + return { + method: 'DELETE', + path: DETECTION_ENGINE_RULES_URL, + options: { + tags: ['access:siem'], + validate: { + options: { + abortEarly: false, + }, + query: queryRulesSchema, }, - query: queryRulesSchema, }, - }, - async handler(request: QueryRequest, headers) { - const { id, rule_id: ruleId } = request.query; - const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) ? request.getActionsClient() : null; - const savedObjectsClient = isFunction(request.getSavedObjectsClient) - ? request.getSavedObjectsClient() - : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { - return headers.response().code(404); - } + async handler(request: QueryRequest, headers) { + const { id, rule_id: ruleId } = request.query; + const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; + const actionsClient = await server.plugins.actions.getActionsClientWithRequest( + KibanaRequest.from((request as unknown) as Hapi.Request) + ); + const savedObjectsClient = isFunction(request.getSavedObjectsClient) + ? request.getSavedObjectsClient() + : null; + if (!alertsClient || !savedObjectsClient) { + return headers.response().code(404); + } - try { - const rule = await deleteRules({ - actionsClient, - alertsClient, - id, - ruleId, - }); - if (rule != null) { - const ruleStatuses = await savedObjectsClient.find< - IRuleSavedAttributesSavedObjectAttributes - >({ - type: ruleStatusSavedObjectType, - perPage: 6, - search: rule.id, - searchFields: ['alertId'], + try { + const rule = await deleteRules({ + actionsClient, + alertsClient, + id, + ruleId, }); - ruleStatuses.saved_objects.forEach(async obj => - savedObjectsClient.delete(ruleStatusSavedObjectType, obj.id) - ); - return transformOrError(rule, ruleStatuses.saved_objects[0]); - } else { - return getIdError({ id, ruleId }); + if (rule != null) { + const ruleStatuses = await savedObjectsClient.find< + IRuleSavedAttributesSavedObjectAttributes + >({ + type: ruleStatusSavedObjectType, + perPage: 6, + search: rule.id, + searchFields: ['alertId'], + }); + ruleStatuses.saved_objects.forEach(async obj => + savedObjectsClient.delete(ruleStatusSavedObjectType, obj.id) + ); + return transformOrError(rule, ruleStatuses.saved_objects[0]); + } else { + return getIdError({ id, ruleId }); + } + } catch (err) { + return transformError(err); } - } catch (err) { - return transformError(err); - } - }, + }, + }; }; export const deleteRulesRoute = (server: ServerFacade): void => { - server.route(createDeleteRulesRoute); + server.route(createDeleteRulesRoute(server)); }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/export_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/export_rules_route.ts index aa17946849027c..b9ff2e60186242 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/export_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/export_rules_route.ts @@ -31,11 +31,8 @@ export const createExportRulesRoute = (server: ServerFacade): Hapi.ServerRoute = }, async handler(request: ExportRulesRequest, headers) { const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) - ? request.getActionsClient() - : null; - if (!alertsClient || !actionsClient) { + if (!alertsClient) { return headers.response().code(404); } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.test.ts index 0aab02281a5364..62c9f44da1e332 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, } from '../__mocks__/_mock_server'; import { findRulesRoute } from './find_rules_route'; @@ -43,28 +41,12 @@ describe('find_rules', () => { expect(statusCode).toBe(200); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - findRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(getFindRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); findRulesRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(getFindRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - findRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject(getFindRequest()); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.ts index 6cbc794751f9fb..5b12703590407c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.ts @@ -15,58 +15,61 @@ import { transformFindAlertsOrError } from './utils'; import { transformError } from '../utils'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; -export const createFindRulesRoute: Hapi.ServerRoute = { - method: 'GET', - path: `${DETECTION_ENGINE_RULES_URL}/_find`, - options: { - tags: ['access:siem'], - validate: { - options: { - abortEarly: false, +export const createFindRulesRoute = (): Hapi.ServerRoute => { + return { + method: 'GET', + path: `${DETECTION_ENGINE_RULES_URL}/_find`, + options: { + tags: ['access:siem'], + validate: { + options: { + abortEarly: false, + }, + query: findRulesSchema, }, - query: findRulesSchema, }, - }, - async handler(request: FindRulesRequest, headers) { - const { query } = request; - const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) ? request.getActionsClient() : null; - const savedObjectsClient = isFunction(request.getSavedObjectsClient) - ? request.getSavedObjectsClient() - : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { - return headers.response().code(404); - } + async handler(request: FindRulesRequest, headers) { + const { query } = request; + const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; + const savedObjectsClient = isFunction(request.getSavedObjectsClient) + ? request.getSavedObjectsClient() + : null; + if (!alertsClient || !savedObjectsClient) { + return headers.response().code(404); + } - try { - const rules = await findRules({ - alertsClient, - perPage: query.per_page, - page: query.page, - sortField: query.sort_field, - sortOrder: query.sort_order, - filter: query.filter, - }); - const ruleStatuses = await Promise.all( - rules.data.map(async rule => { - const results = await savedObjectsClient.find({ - type: ruleStatusSavedObjectType, - perPage: 1, - sortField: 'statusDate', - sortOrder: 'desc', - search: rule.id, - searchFields: ['alertId'], - }); - return results; - }) - ); - return transformFindAlertsOrError(rules, ruleStatuses); - } catch (err) { - return transformError(err); - } - }, + try { + const rules = await findRules({ + alertsClient, + perPage: query.per_page, + page: query.page, + sortField: query.sort_field, + sortOrder: query.sort_order, + filter: query.filter, + }); + const ruleStatuses = await Promise.all( + rules.data.map(async rule => { + const results = await savedObjectsClient.find< + IRuleSavedAttributesSavedObjectAttributes + >({ + type: ruleStatusSavedObjectType, + perPage: 1, + sortField: 'statusDate', + sortOrder: 'desc', + search: rule.id, + searchFields: ['alertId'], + }); + return results; + }) + ); + return transformFindAlertsOrError(rules, ruleStatuses); + } catch (err) { + return transformError(err); + } + }, + }; }; export const findRulesRoute = (server: ServerFacade) => { - server.route(createFindRulesRoute); + server.route(createFindRulesRoute()); }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts index 545c2e488b1c8b..8b3113a044b5ac 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts @@ -44,11 +44,10 @@ export const createFindRulesStatusRoute: Hapi.ServerRoute = { async handler(request: FindRulesStatusesRequest, headers) { const { query } = request; const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) ? request.getActionsClient() : null; const savedObjectsClient = isFunction(request.getSavedObjectsClient) ? request.getSavedObjectsClient() : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { + if (!alertsClient || !savedObjectsClient) { return headers.response().code(404); } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rule_status_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rule_status_route.test.ts index 1ae9e87b8eefe7..de7f0fe26cc745 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rule_status_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rule_status_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, getMockNonEmptyIndex, } from '../__mocks__/_mock_server'; import { createRulesRoute } from './create_rules_route'; @@ -33,7 +31,7 @@ jest.mock('../../rules/get_prepackaged_rules', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', version: 2, // set one higher than the mocks which is set to 1 to trigger updates @@ -65,15 +63,6 @@ describe('get_prepackaged_rule_status_route', () => { expect(statusCode).toBe(200); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - createRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject( - getPrepackagedRulesStatusRequest() - ); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); createRulesRoute(serverWithoutAlertClient); @@ -82,40 +71,31 @@ describe('get_prepackaged_rule_status_route', () => { ); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - createRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject( - getPrepackagedRulesStatusRequest() - ); - expect(statusCode).toBe(404); - }); }); describe('payload', () => { - test('0 rules installed, 1 rules not installed, and 1 rule not updated', async () => { + test('0 rules installed, 0 custom rules, 1 rules not installed, and 1 rule not updated', async () => { alertsClient.find.mockResolvedValue(getFindResult()); alertsClient.get.mockResolvedValue(getResult()); actionsClient.create.mockResolvedValue(createActionResult()); alertsClient.create.mockResolvedValue(getResult()); const { payload } = await server.inject(getPrepackagedRulesStatusRequest()); expect(JSON.parse(payload)).toEqual({ + rules_custom_installed: 0, rules_installed: 0, rules_not_installed: 1, rules_not_updated: 0, }); }); - test('1 rule installed, 0 rules not installed, and 1 rule to not updated', async () => { + test('1 rule installed, 1 custom rules, 0 rules not installed, and 1 rule to not updated', async () => { alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); alertsClient.get.mockResolvedValue(getResult()); actionsClient.create.mockResolvedValue(createActionResult()); alertsClient.create.mockResolvedValue(getResult()); const { payload } = await server.inject(getPrepackagedRulesStatusRequest()); expect(JSON.parse(payload)).toEqual({ + rules_custom_installed: 1, rules_installed: 1, rules_not_installed: 0, rules_not_updated: 1, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.ts index 99e29242bced07..ab6ee8e97a70f7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.ts @@ -13,6 +13,7 @@ import { transformError } from '../utils'; import { getPrepackagedRules } from '../../rules/get_prepackaged_rules'; import { getRulesToInstall } from '../../rules/get_rules_to_install'; import { getRulesToUpdate } from '../../rules/get_rules_to_update'; +import { findRules } from '../../rules/find_rules'; import { getExistingPrepackagedRules } from '../../rules/get_existing_prepackaged_rules'; export const createGetPrepackagedRulesStatusRoute = (): Hapi.ServerRoute => { @@ -29,20 +30,26 @@ export const createGetPrepackagedRulesStatusRoute = (): Hapi.ServerRoute => { }, async handler(request: RequestFacade, headers) { const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) - ? request.getActionsClient() - : null; - if (!alertsClient || !actionsClient) { + if (!alertsClient) { return headers.response().code(404); } try { const rulesFromFileSystem = getPrepackagedRules(); + const customRules = await findRules({ + alertsClient, + perPage: 1, + page: 1, + sortField: 'enabled', + sortOrder: 'desc', + filter: 'alert.attributes.tags:"__internal_immutable:false"', + }); const prepackagedRules = await getExistingPrepackagedRules({ alertsClient }); const rulesToInstall = getRulesToInstall(rulesFromFileSystem, prepackagedRules); const rulesToUpdate = getRulesToUpdate(rulesFromFileSystem, prepackagedRules); return { + rules_custom_installed: customRules.total, rules_installed: prepackagedRules.length, rules_not_installed: rulesToInstall.length, rules_not_updated: rulesToUpdate.length, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts index 6efaa1fea60d08..88a31c36a87fcf 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts @@ -27,6 +27,7 @@ import { ImportRuleAlertRest } from '../../types'; import { transformOrImportError } from './utils'; import { updateRules } from '../../rules/update_rules'; import { importRulesQuerySchema, importRulesPayloadSchema } from '../schemas/import_rules_schema'; +import { KibanaRequest } from '../../../../../../../../../src/core/server'; export const createImportRulesRoute = (server: ServerFacade): Hapi.ServerRoute => { return { @@ -49,13 +50,13 @@ export const createImportRulesRoute = (server: ServerFacade): Hapi.ServerRoute = }, async handler(request: ImportRulesRequest, headers) { const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) - ? request.getActionsClient() - : null; + const actionsClient = await server.plugins.actions.getActionsClientWithRequest( + KibanaRequest.from((request as unknown) as Hapi.Request) + ); const savedObjectsClient = isFunction(request.getSavedObjectsClient) ? request.getSavedObjectsClient() : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { + if (!alertsClient || !savedObjectsClient) { return headers.response().code(404); } const { filename } = request.payload.file.hapi; @@ -104,7 +105,7 @@ export const createImportRulesRoute = (server: ServerFacade): Hapi.ServerRoute = name, severity, tags, - threats, + threat, to, type, references, @@ -153,7 +154,7 @@ export const createImportRulesRoute = (server: ServerFacade): Hapi.ServerRoute = tags, to, type, - threats, + threat, updatedAt: new Date().toISOString(), references, version, @@ -188,7 +189,7 @@ export const createImportRulesRoute = (server: ServerFacade): Hapi.ServerRoute = tags, to, type, - threats, + threat, references, version, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.test.ts index 4190225bea1f1e..000cd29af8ba9c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, } from '../__mocks__/_mock_server'; import { readRulesRoute } from './read_rules_route'; @@ -44,28 +42,12 @@ describe('read_signals', () => { expect(statusCode).toBe(200); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - readRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(getReadRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); readRulesRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(getReadRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - readRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject(getReadRequest()); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.ts index 25d8e6770f6999..55fecdc14f7558 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.ts @@ -31,11 +31,10 @@ export const createReadRulesRoute: Hapi.ServerRoute = { async handler(request: QueryRequest, headers) { const { id, rule_id: ruleId } = request.query; const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) ? request.getActionsClient() : null; const savedObjectsClient = isFunction(request.getSavedObjectsClient) ? request.getSavedObjectsClient() : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { + if (!alertsClient || !savedObjectsClient) { return headers.response().code(404); } try { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk.test.ts index cc41800671d7d1..81b6444f386031 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, } from '../__mocks__/_mock_server'; import { updateRulesRoute } from './update_rules_route'; @@ -70,28 +68,12 @@ describe('update_rules_bulk', () => { expect(parsed).toEqual(expected); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - updateRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(getUpdateBulkRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); updateRulesRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(getUpdateBulkRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - updateRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject(getUpdateBulkRequest()); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts index e0d2672cf356a5..8c7558d6d4fb57 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts @@ -17,6 +17,7 @@ import { transformBulkError } from '../utils'; import { updateRulesBulkSchema } from '../schemas/update_rules_bulk_schema'; import { updateRules } from '../../rules/update_rules'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; +import { KibanaRequest } from '../../../../../../../../../src/core/server'; export const createUpdateRulesBulkRoute = (server: ServerFacade): Hapi.ServerRoute => { return { @@ -33,13 +34,13 @@ export const createUpdateRulesBulkRoute = (server: ServerFacade): Hapi.ServerRou }, async handler(request: BulkUpdateRulesRequest, headers) { const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) - ? request.getActionsClient() - : null; + const actionsClient = await server.plugins.actions.getActionsClientWithRequest( + KibanaRequest.from((request as unknown) as Hapi.Request) + ); const savedObjectsClient = isFunction(request.getSavedObjectsClient) ? request.getSavedObjectsClient() : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { + if (!alertsClient || !savedObjectsClient) { return headers.response().code(404); } @@ -69,7 +70,7 @@ export const createUpdateRulesBulkRoute = (server: ServerFacade): Hapi.ServerRou tags, to, type, - threats, + threat, references, version, } = payloadRule; @@ -102,7 +103,7 @@ export const createUpdateRulesBulkRoute = (server: ServerFacade): Hapi.ServerRou tags, to, type, - threats, + threat, references, version, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts index a7e8f1b1c0a7e5..c4f10d7a203271 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts @@ -6,9 +6,7 @@ import { createMockServer, - createMockServerWithoutActionClientDecoration, createMockServerWithoutAlertClientDecoration, - createMockServerWithoutActionOrAlertClientDecoration, } from '../__mocks__/_mock_server'; import { updateRulesRoute } from './update_rules_route'; @@ -55,28 +53,12 @@ describe('update_rules', () => { expect(statusCode).toBe(404); }); - test('returns 404 if actionClient is not available on the route', async () => { - const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); - updateRulesRoute(serverWithoutActionClient); - const { statusCode } = await serverWithoutActionClient.inject(getUpdateRequest()); - expect(statusCode).toBe(404); - }); - test('returns 404 if alertClient is not available on the route', async () => { const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); updateRulesRoute(serverWithoutAlertClient); const { statusCode } = await serverWithoutAlertClient.inject(getUpdateRequest()); expect(statusCode).toBe(404); }); - - test('returns 404 if alertClient and actionClient are both not available on the route', async () => { - const { - serverWithoutActionOrAlertClient, - } = createMockServerWithoutActionOrAlertClientDecoration(); - updateRulesRoute(serverWithoutActionOrAlertClient); - const { statusCode } = await serverWithoutActionOrAlertClient.inject(getUpdateRequest()); - expect(statusCode).toBe(404); - }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.ts index 49c9304ae2d25a..f51cea0753f1ab 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.ts @@ -14,111 +14,116 @@ import { ServerFacade } from '../../../../types'; import { getIdError, transformOrError } from './utils'; import { transformError } from '../utils'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; +import { KibanaRequest } from '../../../../../../../../../src/core/server'; -export const createUpdateRulesRoute: Hapi.ServerRoute = { - method: 'PUT', - path: DETECTION_ENGINE_RULES_URL, - options: { - tags: ['access:siem'], - validate: { - options: { - abortEarly: false, +export const createUpdateRulesRoute = (server: ServerFacade): Hapi.ServerRoute => { + return { + method: 'PUT', + path: DETECTION_ENGINE_RULES_URL, + options: { + tags: ['access:siem'], + validate: { + options: { + abortEarly: false, + }, + payload: updateRulesSchema, }, - payload: updateRulesSchema, }, - }, - async handler(request: UpdateRulesRequest, headers) { - const { - description, - enabled, - false_positives: falsePositives, - from, - query, - language, - output_index: outputIndex, - saved_id: savedId, - timeline_id: timelineId, - timeline_title: timelineTitle, - meta, - filters, - rule_id: ruleId, - id, - index, - interval, - max_signals: maxSignals, - risk_score: riskScore, - name, - severity, - tags, - to, - type, - threats, - references, - version, - } = request.payload; - - const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) ? request.getActionsClient() : null; - const savedObjectsClient = isFunction(request.getSavedObjectsClient) - ? request.getSavedObjectsClient() - : null; - if (!alertsClient || !actionsClient || !savedObjectsClient) { - return headers.response().code(404); - } - - try { - const rule = await updateRules({ - alertsClient, - actionsClient, + async handler(request: UpdateRulesRequest, headers) { + const { description, enabled, - falsePositives, + false_positives: falsePositives, from, query, language, - outputIndex, - savedId, - savedObjectsClient, - timelineId, - timelineTitle, + output_index: outputIndex, + saved_id: savedId, + timeline_id: timelineId, + timeline_title: timelineTitle, meta, filters, + rule_id: ruleId, id, - ruleId, index, interval, - maxSignals, - riskScore, + max_signals: maxSignals, + risk_score: riskScore, name, severity, tags, to, type, - threats, + threat, references, version, - }); - if (rule != null) { - const ruleStatuses = await savedObjectsClient.find< - IRuleSavedAttributesSavedObjectAttributes - >({ - type: ruleStatusSavedObjectType, - perPage: 1, - sortField: 'statusDate', - sortOrder: 'desc', - search: rule.id, - searchFields: ['alertId'], + } = request.payload; + + const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; + const actionsClient = await server.plugins.actions.getActionsClientWithRequest( + KibanaRequest.from((request as unknown) as Hapi.Request) + ); + const savedObjectsClient = isFunction(request.getSavedObjectsClient) + ? request.getSavedObjectsClient() + : null; + if (!alertsClient || !savedObjectsClient) { + return headers.response().code(404); + } + + try { + const rule = await updateRules({ + alertsClient, + actionsClient, + description, + enabled, + falsePositives, + from, + query, + language, + outputIndex, + savedId, + savedObjectsClient, + timelineId, + timelineTitle, + meta, + filters, + id, + ruleId, + index, + interval, + maxSignals, + riskScore, + name, + severity, + tags, + to, + type, + threat, + references, + version, }); - return transformOrError(rule, ruleStatuses.saved_objects[0]); - } else { - return getIdError({ id, ruleId }); + if (rule != null) { + const ruleStatuses = await savedObjectsClient.find< + IRuleSavedAttributesSavedObjectAttributes + >({ + type: ruleStatusSavedObjectType, + perPage: 1, + sortField: 'statusDate', + sortOrder: 'desc', + search: rule.id, + searchFields: ['alertId'], + }); + return transformOrError(rule, ruleStatuses.saved_objects[0]); + } else { + return getIdError({ id, ruleId }); + } + } catch (err) { + return transformError(err); } - } catch (err) { - return transformError(err); - } - }, + }, + }; }; export const updateRulesRoute = (server: ServerFacade) => { - server.route(createUpdateRulesRoute); + server.route(createUpdateRulesRoute(server)); }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.test.ts index c1b4c7de73f688..ec11a8fb2da39d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.test.ts @@ -52,7 +52,7 @@ describe('utils', () => { severity: 'high', updated_by: 'elastic', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -60,7 +60,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -115,7 +115,7 @@ describe('utils', () => { severity: 'high', updated_by: 'elastic', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -123,7 +123,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -180,7 +180,7 @@ describe('utils', () => { severity: 'high', updated_by: 'elastic', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -188,7 +188,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -245,7 +245,7 @@ describe('utils', () => { severity: 'high', updated_by: 'elastic', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -253,7 +253,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -308,7 +308,7 @@ describe('utils', () => { severity: 'high', updated_by: 'elastic', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -316,7 +316,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -374,7 +374,7 @@ describe('utils', () => { severity: 'high', updated_by: 'elastic', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -382,7 +382,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -440,7 +440,7 @@ describe('utils', () => { severity: 'high', updated_by: 'elastic', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -448,7 +448,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -506,7 +506,7 @@ describe('utils', () => { severity: 'high', updated_by: 'elastic', tags: ['tag 1', 'tag 2'], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -514,7 +514,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -623,7 +623,7 @@ describe('utils', () => { tags: [], to: 'now', type: 'query', - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -631,7 +631,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -696,7 +696,7 @@ describe('utils', () => { tags: [], to: 'now', type: 'query', - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -704,7 +704,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -858,7 +858,7 @@ describe('utils', () => { tags: [], to: 'now', type: 'query', - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -866,7 +866,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -979,7 +979,7 @@ describe('utils', () => { saved_id: 'some-id', severity: 'high', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -987,7 +987,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -1039,7 +1039,7 @@ describe('utils', () => { saved_id: 'some-id', severity: 'high', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -1047,7 +1047,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', @@ -1088,7 +1088,7 @@ describe('utils', () => { saved_id: 'some-id', severity: 'high', tags: [], - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -1096,7 +1096,7 @@ describe('utils', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts index ae79b571b2b625..663ddf3a835a60 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts @@ -110,7 +110,7 @@ export const transformAlertToRule = ( tags: transformTags(alert.tags), to: alert.params.to, type: alert.params.type, - threats: alert.params.threats, + threat: alert.params.threat, version: alert.params.version, status: ruleStatus?.attributes.status, status_date: ruleStatus?.attributes.statusDate, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/add_prepackaged_rules_schema.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/add_prepackaged_rules_schema.test.ts index abdd5a0c7b5084..b536cfac05df3c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/add_prepackaged_rules_schema.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/add_prepackaged_rules_schema.test.ts @@ -78,7 +78,7 @@ describe('add prepackaged rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', }).error ).toBeTruthy(); }); @@ -91,7 +91,7 @@ describe('add prepackaged rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', }).error ).toBeTruthy(); @@ -105,7 +105,7 @@ describe('add prepackaged rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -120,7 +120,7 @@ describe('add prepackaged rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', interval: '5m', index: ['index-1'], @@ -137,7 +137,7 @@ describe('add prepackaged rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', query: 'some query', index: ['index-1'], @@ -156,7 +156,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -175,7 +175,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -196,7 +196,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -215,7 +215,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', risk_score: 50, @@ -224,7 +224,7 @@ describe('add prepackaged rules schema', () => { ).toBeFalsy(); }); - test('You can send in an empty array to threats', () => { + test('You can send in an empty array to threat', () => { expect( addPrepackagedRulesSchema.validate>({ rule_id: 'rule-1', @@ -234,19 +234,19 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [], + threat: [], version: 1, }).error ).toBeFalsy(); }); - test('[rule_id, description, from, to, index, name, severity, interval, type, filter, risk_score, version, threats] does validate', () => { + test('[rule_id, description, from, to, index, name, severity, interval, type, filter, risk_score, version, s] does validate', () => { expect( addPrepackagedRulesSchema.validate>({ rule_id: 'rule-1', @@ -256,10 +256,10 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', - threats: [ + threat: [ { framework: 'someFramework', tactic: { @@ -267,7 +267,7 @@ describe('add prepackaged rules schema', () => { name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -291,7 +291,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -312,7 +312,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -332,7 +332,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -342,28 +342,7 @@ describe('add prepackaged rules schema', () => { ).toEqual(true); }); - test('immutable cannot be false', () => { - expect( - addPrepackagedRulesSchema.validate>({ - rule_id: 'rule-1', - risk_score: 50, - description: 'some description', - from: 'now-5m', - to: 'now', - index: ['index-1'], - immutable: false, - name: 'some-name', - severity: 'severity', - interval: '5m', - type: 'query', - query: 'some-query', - language: 'kuery', - version: 1, - }).error.message - ).toEqual('child "immutable" fails because ["immutable" must be one of [true]]'); - }); - - test('immutable can be true', () => { + test('immutable cannot be set in a pre-packaged rule', () => { expect( addPrepackagedRulesSchema.validate>({ rule_id: 'rule-1', @@ -374,14 +353,14 @@ describe('add prepackaged rules schema', () => { index: ['index-1'], immutable: true, name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', language: 'kuery', version: 1, - }).error - ).toBeFalsy(); + }).error.message + ).toEqual('child "immutable" fails because ["immutable" is not allowed]'); }); test('defaults enabled to false', () => { @@ -394,7 +373,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -413,7 +392,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -435,7 +414,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -460,7 +439,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: [5], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -482,7 +461,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', version: 1, }).value.interval @@ -499,7 +478,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', version: 1, @@ -517,7 +496,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', version: 1, @@ -535,7 +514,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -554,7 +533,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -576,7 +555,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -596,7 +575,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -617,7 +596,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -638,7 +617,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -659,7 +638,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -681,7 +660,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -703,7 +682,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -725,7 +704,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -750,7 +729,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -765,11 +744,11 @@ describe('add prepackaged rules schema', () => { ); }); - test('You cannot send in an array of threats that are missing "framework"', () => { + test('You cannot send in an array of threat that are missing "framework"', () => { expect( addPrepackagedRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -779,21 +758,21 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { tactic: { id: 'fakeId', name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -805,15 +784,15 @@ describe('add prepackaged rules schema', () => { version: 1, }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "framework" fails because ["framework" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "framework" fails because ["framework" is required]]]' ); }); - test('You cannot send in an array of threats that are missing "tactic"', () => { + test('You cannot send in an array of threat that are missing "tactic"', () => { expect( addPrepackagedRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -823,17 +802,17 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -845,15 +824,15 @@ describe('add prepackaged rules schema', () => { version: 1, }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "tactic" fails because ["tactic" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "tactic" fails because ["tactic" is required]]]' ); }); - test('You cannot send in an array of threats that are missing "techniques"', () => { + test('You cannot send in an array of threat that are missing "technique"', () => { expect( addPrepackagedRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -863,14 +842,14 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', tactic: { @@ -883,7 +862,7 @@ describe('add prepackaged rules schema', () => { version: 1, }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "techniques" fails because ["techniques" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "technique" fails because ["technique" is required]]]' ); }); @@ -898,7 +877,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -923,7 +902,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -937,54 +916,6 @@ describe('add prepackaged rules schema', () => { ); }); - test('You can optionally set the immutable to be true', () => { - expect( - addPrepackagedRulesSchema.validate>({ - rule_id: 'rule-1', - risk_score: 50, - description: 'some description', - from: 'now-5m', - to: 'now', - immutable: true, - index: ['index-1'], - name: 'some-name', - severity: 'severity', - interval: '5m', - type: 'query', - references: ['index-1'], - query: 'some query', - language: 'kuery', - max_signals: 1, - version: 1, - }).error - ).toBeFalsy(); - }); - - test('You cannot set the immutable to be a number', () => { - expect( - addPrepackagedRulesSchema.validate< - Partial> & { immutable: number } - >({ - rule_id: 'rule-1', - risk_score: 50, - description: 'some description', - from: 'now-5m', - to: 'now', - immutable: 5, - index: ['index-1'], - name: 'some-name', - severity: 'severity', - interval: '5m', - type: 'query', - references: ['index-1'], - query: 'some query', - language: 'kuery', - max_signals: 1, - version: 1, - }).error.message - ).toEqual('child "immutable" fails because ["immutable" must be a boolean]'); - }); - test('You cannot set the risk_score to 101', () => { expect( addPrepackagedRulesSchema.validate>({ @@ -993,10 +924,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1016,10 +946,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1039,10 +968,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1062,10 +990,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1085,10 +1012,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1113,10 +1039,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1137,10 +1062,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1162,7 +1086,7 @@ describe('add prepackaged rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1183,10 +1107,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1207,10 +1130,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1232,10 +1154,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1257,10 +1178,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1282,10 +1202,9 @@ describe('add prepackaged rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1297,4 +1216,62 @@ describe('add prepackaged rules schema', () => { }).error.message ).toEqual('child "timeline_title" fails because ["timeline_title" is not allowed]'); }); + + test('The default for "from" will be "now-6m"', () => { + expect( + addPrepackagedRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'low', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).value.from + ).toEqual('now-6m'); + }); + + test('The default for "to" will be "now"', () => { + expect( + addPrepackagedRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + index: ['auditbeat-*'], + name: 'some-name', + severity: 'low', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).value.to + ).toEqual('now'); + }); + + test('You cannot set the severity to a value other than low, medium, high, or critical', () => { + expect( + addPrepackagedRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + index: ['auditbeat-*'], + name: 'some-name', + severity: 'junk', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).error.message + ).toEqual( + 'child "severity" fails because ["severity" must be one of [low, medium, high, critical]]' + ); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/add_prepackaged_rules_schema.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/add_prepackaged_rules_schema.ts index 9311371d630f78..b62c480492c84c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/add_prepackaged_rules_schema.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/add_prepackaged_rules_schema.ts @@ -30,7 +30,7 @@ import { tags, to, type, - threats, + threat, references, version, } from './schemas'; @@ -42,19 +42,23 @@ import { DEFAULT_MAX_SIGNALS } from '../../../../../common/constants'; * Big differences between this schema and the createRulesSchema * - rule_id is required here * - output_index is not allowed (and instead the space index must be used) - * - immutable defaults to true instead of to false and if it is there can only be true + * - immutable is forbidden but defaults to true instead of to false and it can only ever be true * - enabled defaults to false instead of true * - version is a required field that must exist + * - index is a required field that must exist */ export const addPrepackagedRulesSchema = Joi.object({ description: description.required(), enabled: enabled.default(false), false_positives: false_positives.default([]), filters, - from: from.required(), + from: from.default('now-6m'), rule_id: rule_id.required(), - immutable: immutable.default(true).valid(true), - index, + immutable: immutable + .forbidden() + .default(true) + .valid(true), + index: index.required(), interval: interval.default('5m'), query: query.allow('').default(''), language: language.default('kuery'), @@ -71,9 +75,9 @@ export const addPrepackagedRulesSchema = Joi.object({ name: name.required(), severity: severity.required(), tags: tags.default([]), - to: to.required(), + to: to.default('now'), type: type.required(), - threats: threats.default([]), + threat: threat.default([]), references: references.default([]), version: version.required(), }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_bulk_schema.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_bulk_schema.test.ts index 17fb5320daa013..1eab50848b822a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_bulk_schema.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_bulk_schema.test.ts @@ -37,7 +37,7 @@ describe('create_rules_bulk_schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', query: 'some query', index: ['index-1'], @@ -57,7 +57,7 @@ describe('create_rules_bulk_schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', query: 'some query', index: ['index-1'], @@ -70,7 +70,7 @@ describe('create_rules_bulk_schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', query: 'some query', index: ['index-1'], @@ -79,4 +79,66 @@ describe('create_rules_bulk_schema', () => { ]).error ).toBeFalsy(); }); + + test('The default for "from" will be "now-6m"', () => { + expect( + createRulesBulkSchema.validate>([ + { + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'low', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }, + ]).value[0].from + ).toEqual('now-6m'); + }); + + test('The default for "to" will be "now"', () => { + expect( + createRulesBulkSchema.validate>([ + { + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'low', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }, + ]).value[0].to + ).toEqual('now'); + }); + + test('You cannot set the severity to a value other than low, medium, high, or critical', () => { + expect( + createRulesBulkSchema.validate>([ + { + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'junk', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }, + ]).error.message + ).toEqual( + '"value" at position 0 fails because [child "severity" fails because ["severity" must be one of [low, medium, high, critical]]]' + ); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.test.ts index c76071047434c6..d9605a265d28b8 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.test.ts @@ -79,7 +79,7 @@ describe('create rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', }).error ).toBeTruthy(); }); @@ -92,7 +92,7 @@ describe('create rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', }).error ).toBeTruthy(); @@ -106,7 +106,7 @@ describe('create rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -121,7 +121,7 @@ describe('create rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', interval: '5m', index: ['index-1'], @@ -138,7 +138,7 @@ describe('create rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', query: 'some query', index: ['index-1'], @@ -156,7 +156,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -175,7 +175,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -195,7 +195,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -213,7 +213,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', risk_score: 50, @@ -232,14 +232,14 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error ).toBeFalsy(); }); - test('You can send in an empty array to threats', () => { + test('You can send in an empty array to threat', () => { expect( createRulesSchema.validate>({ rule_id: 'rule-1', @@ -250,19 +250,19 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [], + threat: [], }).error ).toBeFalsy(); }); - test('[rule_id, description, from, to, index, name, severity, interval, type, filter, risk_score, output_index, threats] does validate', () => { + test('[rule_id, description, from, to, index, name, severity, interval, type, filter, risk_score, output_index, threat] does validate', () => { expect( createRulesSchema.validate>({ rule_id: 'rule-1', @@ -273,10 +273,10 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', - threats: [ + threat: [ { framework: 'someFramework', tactic: { @@ -284,7 +284,7 @@ describe('create rules schema', () => { name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -308,7 +308,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -329,7 +329,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -351,7 +351,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -375,7 +375,7 @@ describe('create rules schema', () => { to: 'now', index: [5], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -398,7 +398,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', }).value.interval ).toEqual('5m'); @@ -415,7 +415,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).value.max_signals @@ -433,7 +433,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', }).error.message @@ -451,7 +451,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -470,7 +470,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -492,7 +492,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -512,7 +512,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -533,7 +533,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -554,7 +554,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -575,7 +575,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -597,7 +597,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -619,7 +619,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -641,7 +641,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -664,7 +664,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -678,11 +678,11 @@ describe('create rules schema', () => { ); }); - test('You cannot send in an array of threats that are missing "framework"', () => { + test('You cannot send in an array of threat that are missing "framework"', () => { expect( createRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -693,21 +693,21 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { tactic: { id: 'fakeId', name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -718,15 +718,15 @@ describe('create rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "framework" fails because ["framework" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "framework" fails because ["framework" is required]]]' ); }); - test('You cannot send in an array of threats that are missing "tactic"', () => { + test('You cannot send in an array of threat that are missing "tactic"', () => { expect( createRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -737,17 +737,17 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -758,15 +758,15 @@ describe('create rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "tactic" fails because ["tactic" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "tactic" fails because ["tactic" is required]]]' ); }); - test('You cannot send in an array of threats that are missing "techniques"', () => { + test('You cannot send in an array of threat that are missing "technique"', () => { expect( createRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -777,14 +777,14 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', tactic: { @@ -796,7 +796,7 @@ describe('create rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "techniques" fails because ["techniques" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "technique" fails because ["technique" is required]]]' ); }); @@ -812,7 +812,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -837,7 +837,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -864,7 +864,7 @@ describe('create rules schema', () => { immutable: 5, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -886,7 +886,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -908,7 +908,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -930,7 +930,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -952,7 +952,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -974,7 +974,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -999,7 +999,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1022,7 +1022,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1044,7 +1044,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1067,7 +1067,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1089,7 +1089,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1112,7 +1112,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1135,7 +1135,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1158,7 +1158,7 @@ describe('create rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1168,4 +1168,60 @@ describe('create rules schema', () => { }).error.message ).toEqual('child "timeline_title" fails because ["timeline_title" is not allowed]'); }); + + test('The default for "from" will be "now-6m"', () => { + expect( + createRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'low', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).value.from + ).toEqual('now-6m'); + }); + + test('The default for "to" will be "now"', () => { + expect( + createRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'low', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).value.to + ).toEqual('now'); + }); + + test('You cannot set the severity to a value other than low, medium, high, or critical', () => { + expect( + createRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'junk', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).error.message + ).toEqual( + 'child "severity" fails because ["severity" must be one of [low, medium, high, critical]]' + ); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.ts index 5d9972453fb1a2..eb79e06c8efa68 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.ts @@ -30,7 +30,7 @@ import { tags, to, type, - threats, + threat, references, version, } from './schemas'; @@ -43,7 +43,7 @@ export const createRulesSchema = Joi.object({ enabled: enabled.default(true), false_positives: false_positives.default([]), filters, - from: from.required(), + from: from.default('now-6m'), rule_id, index, interval: interval.default('5m'), @@ -63,9 +63,9 @@ export const createRulesSchema = Joi.object({ name: name.required(), severity: severity.required(), tags: tags.default([]), - to: to.required(), + to: to.default('now'), type: type.required(), - threats: threats.default([]), + threat: threat.default([]), references: references.default([]), version: version.default(1), }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/import_rules_schema.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/import_rules_schema.test.ts index 20f418c57b5dbe..c72e1b7ef2a63c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/import_rules_schema.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/import_rules_schema.test.ts @@ -84,7 +84,7 @@ describe('import rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', }).error ).toBeTruthy(); }); @@ -97,7 +97,7 @@ describe('import rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', }).error ).toBeTruthy(); @@ -111,7 +111,7 @@ describe('import rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -126,7 +126,7 @@ describe('import rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', interval: '5m', index: ['index-1'], @@ -143,7 +143,7 @@ describe('import rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', query: 'some query', index: ['index-1'], @@ -161,7 +161,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -180,7 +180,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -200,7 +200,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -218,7 +218,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', risk_score: 50, @@ -237,14 +237,14 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error ).toBeFalsy(); }); - test('You can send in an empty array to threats', () => { + test('You can send in an empty array to threat', () => { expect( importRulesSchema.validate>({ rule_id: 'rule-1', @@ -255,19 +255,19 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [], + threat: [], }).error ).toBeFalsy(); }); - test('[rule_id, description, from, to, index, name, severity, interval, type, filter, risk_score, output_index, threats] does validate', () => { + test('[rule_id, description, from, to, index, name, severity, interval, type, filter, risk_score, output_index, threat] does validate', () => { expect( importRulesSchema.validate>({ rule_id: 'rule-1', @@ -278,10 +278,10 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', - threats: [ + threat: [ { framework: 'someFramework', tactic: { @@ -289,7 +289,7 @@ describe('import rules schema', () => { name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -313,7 +313,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -334,7 +334,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -356,7 +356,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -381,7 +381,7 @@ describe('import rules schema', () => { to: 'now', index: [5], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -403,7 +403,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', }).value.interval ).toEqual('5m'); @@ -420,7 +420,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).value.max_signals @@ -438,7 +438,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', }).error.message @@ -456,7 +456,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -475,7 +475,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -497,7 +497,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -517,7 +517,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -538,7 +538,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -559,7 +559,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -580,7 +580,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -602,7 +602,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -624,7 +624,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -646,7 +646,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -670,7 +670,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -685,11 +685,11 @@ describe('import rules schema', () => { ); }); - test('You cannot send in an array of threats that are missing "framework"', () => { + test('You cannot send in an array of threat that are missing "framework"', () => { expect( importRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -700,21 +700,21 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { tactic: { id: 'fakeId', name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -725,15 +725,15 @@ describe('import rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "framework" fails because ["framework" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "framework" fails because ["framework" is required]]]' ); }); - test('You cannot send in an array of threats that are missing "tactic"', () => { + test('You cannot send in an array of threat that are missing "tactic"', () => { expect( importRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -744,17 +744,17 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -765,15 +765,15 @@ describe('import rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "tactic" fails because ["tactic" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "tactic" fails because ["tactic" is required]]]' ); }); - test('You cannot send in an array of threats that are missing "techniques"', () => { + test('You cannot send in an array of threat that are missing "technique"', () => { expect( importRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ rule_id: 'rule-1', @@ -784,14 +784,14 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', tactic: { @@ -803,7 +803,7 @@ describe('import rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "techniques" fails because ["techniques" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "technique" fails because ["technique" is required]]]' ); }); @@ -819,7 +819,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -844,7 +844,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -857,7 +857,7 @@ describe('import rules schema', () => { ); }); - test('You can optionally set the immutable to be true', () => { + test('You can optionally set the immutable to be false', () => { expect( importRulesSchema.validate>({ rule_id: 'rule-1', @@ -866,10 +866,10 @@ describe('import rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, + immutable: false, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -880,6 +880,29 @@ describe('import rules schema', () => { ).toBeFalsy(); }); + test('You cannnot set immutable to be true', () => { + expect( + importRulesSchema.validate>({ + rule_id: 'rule-1', + output_index: '.siem-signals', + risk_score: 50, + description: 'some description', + from: 'now-5m', + to: 'now', + immutable: true, + index: ['index-1'], + name: 'some-name', + severity: 'low', + interval: '5m', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + }).error.message + ).toEqual('child "immutable" fails because ["immutable" must be one of [false]]'); + }); + test('You cannot set the immutable to be a number', () => { expect( importRulesSchema.validate< @@ -894,7 +917,7 @@ describe('import rules schema', () => { immutable: 5, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -914,10 +937,10 @@ describe('import rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, + immutable: false, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -937,10 +960,10 @@ describe('import rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, + immutable: false, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -960,10 +983,10 @@ describe('import rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, + immutable: false, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -983,10 +1006,10 @@ describe('import rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, + immutable: false, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1006,10 +1029,10 @@ describe('import rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, + immutable: false, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1032,10 +1055,10 @@ describe('import rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, + immutable: false, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1056,10 +1079,10 @@ describe('import rules schema', () => { description: 'some description', from: 'now-5m', to: 'now', - immutable: true, + immutable: false, index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1081,7 +1104,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1104,7 +1127,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1126,7 +1149,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1149,7 +1172,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1174,7 +1197,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1197,7 +1220,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1219,7 +1242,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1240,7 +1263,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1265,7 +1288,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1290,7 +1313,7 @@ describe('import rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -1344,4 +1367,59 @@ describe('import rules schema', () => { expect(importRulesPayloadSchema.validate({ file: {} }).error).toBeFalsy(); }); }); + + test('The default for "from" will be "now-6m"', () => { + expect( + importRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'low', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).value.from + ).toEqual('now-6m'); + }); + + test('The default for "to" will be "now"', () => { + expect( + importRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'low', + type: 'query', + references: ['index-1'], + language: 'kuery', + max_signals: 1, + version: 1, + }).value.to + ).toEqual('now'); + }); + + test('You cannot set the severity to a value other than low, medium, high, or critical', () => { + expect( + importRulesSchema.validate>({ + rule_id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'junk', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).error.message + ).toEqual( + 'child "severity" fails because ["severity" must be one of [low, medium, high, critical]]' + ); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/import_rules_schema.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/import_rules_schema.ts index df825c442fff65..1254694645b9c0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/import_rules_schema.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/import_rules_schema.ts @@ -36,7 +36,7 @@ import { tags, to, type, - threats, + threat, references, version, } from './schemas'; @@ -59,9 +59,9 @@ export const importRulesSchema = Joi.object({ enabled: enabled.default(true), false_positives: false_positives.default([]), filters, - from: from.required(), + from: from.default('now-6m'), rule_id: rule_id.required(), - immutable: immutable.default(false), + immutable: immutable.default(false).valid(false), index, interval: interval.default('5m'), query: query.allow('').default(''), @@ -80,9 +80,9 @@ export const importRulesSchema = Joi.object({ name: name.required(), severity: severity.required(), tags: tags.default([]), - to: to.required(), + to: to.default('now'), type: type.required(), - threats: threats.default([]), + threat: threat.default([]), references: references.default([]), version: version.default(1), created_at, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/query_signals_index_schema.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/query_signals_index_schema.ts index 0a6fceb44f845a..26a32d2e4980b2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/query_signals_index_schema.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/query_signals_index_schema.ts @@ -9,7 +9,7 @@ import Joi from 'joi'; export const querySignalsSchema = Joi.object({ query: Joi.object(), aggs: Joi.object(), - size: Joi.number(), + size: Joi.number().integer(), track_total_hits: Joi.boolean(), _source: Joi.array().items(Joi.string()), }).min(1); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/schemas.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/schemas.ts index ecca661d2b8565..9b311b1b58ea74 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/schemas.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/schemas.ts @@ -37,12 +37,15 @@ export const timeline_title = Joi.string().when('timeline_id', { otherwise: Joi.forbidden(), }); export const meta = Joi.object(); -export const max_signals = Joi.number().greater(0); +export const max_signals = Joi.number() + .integer() + .greater(0); export const name = Joi.string(); export const risk_score = Joi.number() + .integer() .greater(-1) .less(101); -export const severity = Joi.string(); +export const severity = Joi.string().valid('low', 'medium', 'high', 'critical'); export const status = Joi.string().valid('open', 'closed'); export const to = Joi.string(); export const type = Joi.string().valid('query', 'saved_query'); @@ -51,9 +54,11 @@ export const references = Joi.array() .items(Joi.string()) .single(); export const per_page = Joi.number() + .integer() .min(0) .default(20); export const page = Joi.number() + .integer() .min(1) .default(1); export const signal_ids = Joi.array().items(Joi.string()); @@ -82,11 +87,11 @@ export const threat_technique = Joi.object({ reference: threat_technique_reference.required(), }); export const threat_techniques = Joi.array().items(threat_technique.required()); -export const threats = Joi.array().items( +export const threat = Joi.array().items( Joi.object({ framework: threat_framework.required(), tactic: threat_tactic.required(), - techniques: threat_techniques.required(), + technique: threat_techniques.required(), }) ); export const created_at = Joi.string() @@ -97,4 +102,6 @@ export const updated_at = Joi.string() .strict(); export const created_by = Joi.string(); export const updated_by = Joi.string(); -export const version = Joi.number().min(1); +export const version = Joi.number() + .integer() + .min(1); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.test.ts index 823ebb90a3b3cb..0dc9f3df3da1ce 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.test.ts @@ -147,7 +147,7 @@ describe('update rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', }).error ).toBeFalsy(); }); @@ -160,7 +160,7 @@ describe('update rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', }).error ).toBeFalsy(); }); @@ -173,7 +173,7 @@ describe('update rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', }).error ).toBeFalsy(); @@ -187,7 +187,7 @@ describe('update rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', }).error ).toBeFalsy(); @@ -201,7 +201,7 @@ describe('update rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -216,7 +216,7 @@ describe('update rules schema', () => { from: 'now-5m', to: 'now', name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -232,7 +232,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -248,7 +248,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -264,7 +264,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -281,7 +281,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -298,7 +298,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -316,7 +316,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some query', @@ -334,7 +334,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -350,7 +350,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).error @@ -366,7 +366,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -385,7 +385,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -403,7 +403,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', type: 'query', }).value.interval ).toEqual(undefined); @@ -418,7 +418,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }).value.max_signals @@ -436,7 +436,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -459,7 +459,7 @@ describe('update rules schema', () => { to: 'now', index: [5], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', query: 'some-query', @@ -479,7 +479,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', }).error @@ -495,7 +495,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -512,7 +512,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -530,7 +530,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -549,7 +549,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -568,7 +568,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -587,7 +587,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -607,7 +607,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -627,7 +627,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], @@ -670,7 +670,7 @@ describe('update rules schema', () => { ).toEqual('child "filters" fails because ["filters" must be an array]'); }); - test('threats is not defaulted to empty array on update', () => { + test('threat is not defaulted to empty array on update', () => { expect( updateRulesSchema.validate>({ id: 'rule-1', @@ -679,18 +679,18 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - }).value.threats + }).value.threat ).toBe(undefined); }); - test('threats is not defaulted to undefined on update with empty array', () => { + test('threat is not defaulted to undefined on update with empty array', () => { expect( updateRulesSchema.validate>({ id: 'rule-1', @@ -699,19 +699,19 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [], - }).value.threats + threat: [], + }).value.threat ).toMatchObject([]); }); - test('threats is valid when updated with all sub-objects', () => { + test('threat is valid when updated with all sub-objects', () => { const expected: ThreatParams[] = [ { framework: 'fake', @@ -720,7 +720,7 @@ describe('update rules schema', () => { name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -737,14 +737,14 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', tactic: { @@ -752,7 +752,7 @@ describe('update rules schema', () => { name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -761,15 +761,15 @@ describe('update rules schema', () => { ], }, ], - }).value.threats + }).value.threat ).toMatchObject(expected); }); - test('threats is invalid when updated with missing property framework', () => { + test('threat is invalid when updated with missing property framework', () => { expect( updateRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ id: 'rule-1', @@ -778,21 +778,21 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { tactic: { id: 'fakeId', name: 'fakeName', reference: 'fakeRef', }, - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -803,15 +803,15 @@ describe('update rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "framework" fails because ["framework" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "framework" fails because ["framework" is required]]]' ); }); - test('threats is invalid when updated with missing tactic sub-object', () => { + test('threat is invalid when updated with missing tactic sub-object', () => { expect( updateRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ id: 'rule-1', @@ -820,17 +820,17 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', - techniques: [ + technique: [ { id: 'techniqueId', name: 'techniqueName', @@ -841,15 +841,15 @@ describe('update rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "tactic" fails because ["tactic" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "tactic" fails because ["tactic" is required]]]' ); }); - test('threats is invalid when updated with missing techniques', () => { + test('threat is invalid when updated with missing technique', () => { expect( updateRulesSchema.validate< - Partial> & { - threats: Array>>; + Partial> & { + threat: Array>>; } >({ id: 'rule-1', @@ -858,14 +858,14 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', references: ['index-1'], query: 'some query', language: 'kuery', max_signals: 1, - threats: [ + threat: [ { framework: 'fake', tactic: { @@ -877,7 +877,7 @@ describe('update rules schema', () => { ], }).error.message ).toEqual( - 'child "threats" fails because ["threats" at position 0 fails because [child "techniques" fails because ["techniques" is required]]]' + 'child "threat" fails because ["threat" at position 0 fails because [child "technique" fails because ["technique" is required]]]' ); }); @@ -890,7 +890,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -909,7 +909,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -927,7 +927,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -946,7 +946,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -965,7 +965,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -984,7 +984,7 @@ describe('update rules schema', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'saved_query', saved_id: 'some id', @@ -992,4 +992,24 @@ describe('update rules schema', () => { }).error.message ).toEqual('child "timeline_title" fails because ["timeline_title" is not allowed]'); }); + + test('You cannot set the severity to a value other than low, medium, high, or critical', () => { + expect( + updateRulesSchema.validate>({ + id: 'rule-1', + risk_score: 50, + description: 'some description', + name: 'some-name', + severity: 'junk', + type: 'query', + references: ['index-1'], + query: 'some query', + language: 'kuery', + max_signals: 1, + version: 1, + }).error.message + ).toEqual( + 'child "severity" fails because ["severity" must be one of [low, medium, high, critical]]' + ); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.ts index d363bfca984666..3aa8e007a8cbdb 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.ts @@ -30,7 +30,7 @@ import { tags, to, type, - threats, + threat, references, id, version, @@ -61,7 +61,7 @@ export const updateRulesSchema = Joi.object({ tags, to, type, - threats, + threat, references, version, }).xor('id', 'rule_id'); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/tags/read_tags_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/tags/read_tags_route.ts index beef8b4199c15e..c598e22ff596c5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/tags/read_tags_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/tags/read_tags_route.ts @@ -24,9 +24,7 @@ export const createReadTagsRoute: Hapi.ServerRoute = { }, async handler(request: RequestFacade, headers) { const alertsClient = isFunction(request.getAlertsClient) ? request.getAlertsClient() : null; - const actionsClient = isFunction(request.getActionsClient) ? request.getActionsClient() : null; - - if (!alertsClient || !actionsClient) { + if (!alertsClient) { return headers.response().code(404); } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules.ts index d2f76907d7aa3e..d65f5f84c6d644 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules.ts @@ -8,7 +8,7 @@ import { APP_ID, SIGNALS_ID } from '../../../../common/constants'; import { RuleParams } from './types'; import { addTags } from './add_tags'; -export const createRules = async ({ +export const createRules = ({ alertsClient, actionsClient, // TODO: Use this actionsClient once we have actions such as email, etc... description, @@ -32,7 +32,7 @@ export const createRules = async ({ name, severity, tags, - threats, + threat, to, type, references, @@ -63,7 +63,7 @@ export const createRules = async ({ maxSignals, riskScore, severity, - threats, + threat, to, type, updatedAt: new Date().toISOString(), diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.test.ts index fce3c90ef18e79..d4b7c252e3e380 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.test.ts @@ -21,7 +21,7 @@ export const getOutputSample = (): Partial => ({ to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', }); @@ -55,7 +55,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -65,7 +65,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }, @@ -78,7 +78,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -88,7 +88,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }, @@ -120,7 +120,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -130,7 +130,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }, @@ -143,7 +143,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -153,7 +153,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }, @@ -184,7 +184,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -194,7 +194,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }, @@ -207,7 +207,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -217,7 +217,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }, @@ -248,7 +248,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -258,7 +258,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }); @@ -272,7 +272,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -282,7 +282,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }); @@ -312,7 +312,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -322,7 +322,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }); @@ -338,7 +338,7 @@ describe('create_rules_stream_from_ndjson', () => { to: 'now', index: ['index-1'], name: 'some-name', - severity: 'severity', + severity: 'low', interval: '5m', type: 'query', enabled: true, @@ -348,7 +348,7 @@ describe('create_rules_stream_from_ndjson', () => { language: 'kuery', max_signals: 100, tags: [], - threats: [], + threat: [], references: [], version: 1, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_all.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_all.test.ts index eb9756af8fde10..ff48b9f5f7c33e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_all.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_all.test.ts @@ -23,7 +23,7 @@ describe('getExportAll', () => { const exports = await getExportAll(unsafeCast); expect(exports).toEqual({ rulesNdjson: - '{"created_at":"2019-12-13T16:40:33.400Z","updated_at":"2019-12-13T16:40:33.400Z","created_by":"elastic","description":"Detecting root and admin users","enabled":true,"false_positives":[],"filters":[{"query":{"match_phrase":{"host.name":"some-host"}}}],"from":"now-6m","id":"04128c15-0d1b-4716-a4c5-46997ac7f3bd","immutable":false,"index":["auditbeat-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"rule-1","language":"kuery","output_index":".siem-signals","max_signals":100,"risk_score":50,"name":"Detect Root/Admin Users","query":"user.name: root or user.name: admin","references":["http://www.example.com","https://ww.example.com"],"saved_id":"some-id","timeline_id":"some-timeline-id","timeline_title":"some-timeline-title","meta":{"someMeta":"someField"},"severity":"high","updated_by":"elastic","tags":[],"to":"now","type":"query","threats":[{"framework":"MITRE ATT&CK","tactic":{"id":"TA0040","name":"impact","reference":"https://attack.mitre.org/tactics/TA0040/"},"techniques":[{"id":"T1499","name":"endpoint denial of service","reference":"https://attack.mitre.org/techniques/T1499/"}]}],"version":1}\n', + '{"created_at":"2019-12-13T16:40:33.400Z","updated_at":"2019-12-13T16:40:33.400Z","created_by":"elastic","description":"Detecting root and admin users","enabled":true,"false_positives":[],"filters":[{"query":{"match_phrase":{"host.name":"some-host"}}}],"from":"now-6m","id":"04128c15-0d1b-4716-a4c5-46997ac7f3bd","immutable":false,"index":["auditbeat-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"rule-1","language":"kuery","output_index":".siem-signals","max_signals":100,"risk_score":50,"name":"Detect Root/Admin Users","query":"user.name: root or user.name: admin","references":["http://www.example.com","https://ww.example.com"],"saved_id":"some-id","timeline_id":"some-timeline-id","timeline_title":"some-timeline-title","meta":{"someMeta":"someField"},"severity":"high","updated_by":"elastic","tags":[],"to":"now","type":"query","threat":[{"framework":"MITRE ATT&CK","tactic":{"id":"TA0040","name":"impact","reference":"https://attack.mitre.org/tactics/TA0040/"},"technique":[{"id":"T1499","name":"endpoint denial of service","reference":"https://attack.mitre.org/techniques/T1499/"}]}],"version":1}\n', exportDetails: '{"exported_count":1,"missing_rules":[],"missing_rules_count":0}\n', }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts index a861d80a66fd53..05e455efb3f22e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts @@ -25,7 +25,7 @@ describe('get_export_by_object_ids', () => { const exports = await getExportByObjectIds(unsafeCast, objects); expect(exports).toEqual({ rulesNdjson: - '{"created_at":"2019-12-13T16:40:33.400Z","updated_at":"2019-12-13T16:40:33.400Z","created_by":"elastic","description":"Detecting root and admin users","enabled":true,"false_positives":[],"filters":[{"query":{"match_phrase":{"host.name":"some-host"}}}],"from":"now-6m","id":"04128c15-0d1b-4716-a4c5-46997ac7f3bd","immutable":false,"index":["auditbeat-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"rule-1","language":"kuery","output_index":".siem-signals","max_signals":100,"risk_score":50,"name":"Detect Root/Admin Users","query":"user.name: root or user.name: admin","references":["http://www.example.com","https://ww.example.com"],"saved_id":"some-id","timeline_id":"some-timeline-id","timeline_title":"some-timeline-title","meta":{"someMeta":"someField"},"severity":"high","updated_by":"elastic","tags":[],"to":"now","type":"query","threats":[{"framework":"MITRE ATT&CK","tactic":{"id":"TA0040","name":"impact","reference":"https://attack.mitre.org/tactics/TA0040/"},"techniques":[{"id":"T1499","name":"endpoint denial of service","reference":"https://attack.mitre.org/techniques/T1499/"}]}],"version":1}\n', + '{"created_at":"2019-12-13T16:40:33.400Z","updated_at":"2019-12-13T16:40:33.400Z","created_by":"elastic","description":"Detecting root and admin users","enabled":true,"false_positives":[],"filters":[{"query":{"match_phrase":{"host.name":"some-host"}}}],"from":"now-6m","id":"04128c15-0d1b-4716-a4c5-46997ac7f3bd","immutable":false,"index":["auditbeat-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"rule-1","language":"kuery","output_index":".siem-signals","max_signals":100,"risk_score":50,"name":"Detect Root/Admin Users","query":"user.name: root or user.name: admin","references":["http://www.example.com","https://ww.example.com"],"saved_id":"some-id","timeline_id":"some-timeline-id","timeline_title":"some-timeline-title","meta":{"someMeta":"someField"},"severity":"high","updated_by":"elastic","tags":[],"to":"now","type":"query","threat":[{"framework":"MITRE ATT&CK","tactic":{"id":"TA0040","name":"impact","reference":"https://attack.mitre.org/tactics/TA0040/"},"technique":[{"id":"T1499","name":"endpoint denial of service","reference":"https://attack.mitre.org/techniques/T1499/"}]}],"version":1}\n', exportDetails: '{"exported_count":1,"missing_rules":[],"missing_rules_count":0}\n', }); }); @@ -98,7 +98,7 @@ describe('get_export_by_object_ids', () => { tags: [], to: 'now', type: 'query', - threats: [ + threat: [ { framework: 'MITRE ATT&CK', tactic: { @@ -106,7 +106,7 @@ describe('get_export_by_object_ids', () => { name: 'impact', reference: 'https://attack.mitre.org/tactics/TA0040/', }, - techniques: [ + technique: [ { id: 'T1499', name: 'endpoint denial of service', diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/install_prepacked_rules.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/install_prepacked_rules.ts index 98c04f95387f42..7e8ed62baf1cff 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/install_prepacked_rules.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/install_prepacked_rules.ts @@ -4,18 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ActionsClient } from '../../../../../actions'; +import { ActionsClient } from '../../../../../../../plugins/actions/server'; import { AlertsClient } from '../../../../../alerting'; +import { Alert } from '../../../../../alerting/server/types'; import { createRules } from './create_rules'; import { PrepackagedRules } from '../types'; -export const installPrepackagedRules = async ( +export const installPrepackagedRules = ( alertsClient: AlertsClient, actionsClient: ActionsClient, rules: PrepackagedRules[], outputIndex: string -): Promise => { - await rules.forEach(async rule => { +): Array> => + rules.reduce>>((acc, rule) => { const { description, enabled, @@ -39,41 +40,43 @@ export const installPrepackagedRules = async ( tags, to, type, - threats, + threat, references, version, } = rule; - createRules({ - alertsClient, - actionsClient, - description, - enabled, - falsePositives, - from, - immutable, - query, - language, - outputIndex, - savedId, - timelineId, - timelineTitle, - meta, - filters, - ruleId, - index, - interval, - maxSignals, - riskScore, - name, - severity, - tags, - to, - type, - threats, - references, - version, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }); - }); -}; + return [ + ...acc, + createRules({ + alertsClient, + actionsClient, + description, + enabled, + falsePositives, + from, + immutable, + query, + language, + outputIndex, + savedId, + timelineId, + timelineTitle, + meta, + filters, + ruleId, + index, + interval, + maxSignals, + riskScore, + name, + severity, + tags, + to, + type, + threat, + references, + version, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }), + ]; + }, []); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json index 932f1986045574..c685d96cdf57b6 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json @@ -1,17 +1,25 @@ { - "description": "403 Response to a POST", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "A POST request to web application returned a 403 response which indicates the web application declined to process the request because the action requested was disallowed.", + "false_positives": [ + "Security scans and tests may result in these errors. Misconfigured or buggy applications may produce large numbers of these errors. If the source is unexpected, or the user is unauthorized, or the request is unusual, these may be suspicious or malicious activity." + ], + "index": [ + "apm-*-transaction*" + ], "language": "kuery", - "name": "403 Response to a POST", + "max_signals": 33, + "name": "Web Application Suspicious Activity: POST Request Declined", "query": "http.response.status_code:403 and http.request.method:post", - "risk_score": 50, + "references": [ + "https://en.wikipedia.org/wiki/HTTP_403" + ], + "risk_score": 47, "rule_id": "a87a4e42-1d82-44bd-b0bf-d9b7f91fb89e", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "APM" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json index d4c9a40ddb45f1..64264452d468be 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json @@ -1,17 +1,25 @@ { - "description": "405 Response (Method Not Allowed)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "A request to web application returned a 405 response which indicates the web application declined to process the request because the HTTP method was not allowed for the resource.", + "false_positives": [ + "Security scans and tests may result in these errors. Misconfigured or buggy applications may produce large numbers of these errors. If the source is unexpected, or the user is unauthorized, or the request is unusual, these may be suspicious or malicious activity." + ], + "index": [ + "apm-*-transaction*" + ], "language": "kuery", - "name": "405 Response (Method Not Allowed)", + "max_signals": 33, + "name": "Web Application Suspicious Activity: Unauthorized Method", "query": "http.response.status_code:405", - "risk_score": 50, + "references": [ + "https://en.wikipedia.org/wiki/HTTP_405" + ], + "risk_score": 47, "rule_id": "75ee75d8-c180-481c-ba88-ee50129a6aef", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "APM" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/500_response_on_admin_page.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/500_response_on_admin_page.json deleted file mode 100644 index 62312003797326..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/500_response_on_admin_page.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "500 Response on Admin page", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "500 Response on Admin page", - "query": "url.path:\"/admin/\" and http.response.status_code:500", - "risk_score": 50, - "rule_id": "054f669c-b065-492e-acd9-15e44fc42380", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/NOTICE.txt b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/NOTICE.txt new file mode 100644 index 00000000000000..cd5f1cc6f886cf --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/NOTICE.txt @@ -0,0 +1,20 @@ +This product bundles rules based on https://github.com/BlueTeamLabs/sentinel-attack +which is available under a "MIT" license. The files based on this license are: + +- windows_defense_evasion_via_filter_manager.json +- windows_process_discovery_via_tasklist_command.json +- windows_priv_escalation_via_accessibility_features.json +- windows_persistence_via_application_shimming.json +- windows_execution_via_trusted_developer_utilities.json +- windows_execution_via_net_com_assemblies.json +- windows_execution_via_connection_manager.json + +MIT License + +Copyright (c) 2019 Edoardo Gerosa, Olaf Hartong + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json new file mode 100644 index 00000000000000..56d142fdf3ef8e --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Adversary behavior detected.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Adversary Behavior - Detected - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:rules_engine_event", + "risk_score": 47, + "rule_id": "77a3c3df-8ec4-4da4-b758-878f551dee69", + "severity": "medium", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_detected.json new file mode 100644 index 00000000000000..6805696ce6bc9e --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_detected.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Credential dumping detected.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Cred Dumping - Detected - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:cred_theft_event and endgame.metadata.type:detection", + "risk_score": 73, + "rule_id": "571afc56-5ed9-465d-a2a9-045f099f6e7e", + "severity": "high", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json new file mode 100644 index 00000000000000..68c0f5cad82521 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Credential dumping prevented.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Cred Dumping - Prevented - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:cred_theft_event and endgame.metadata.type:prevention", + "risk_score": 47, + "rule_id": "db8c33a8-03cd-4988-9e2c-d0a4863adb13", + "severity": "medium", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json new file mode 100644 index 00000000000000..0d0d9c71a2ec18 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Credential manipulation detected.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Cred Manipulation - Detected - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:token_manipulation_event and endgame.metadata.type:detection", + "risk_score": 73, + "rule_id": "c0be5f31-e180-48ed-aa08-96b36899d48f", + "severity": "high", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json new file mode 100644 index 00000000000000..df49c80e3097b4 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json @@ -0,0 +1,18 @@ +{ + "description": "Elastic Endpoint Security Alert - Credential manipulation prevented.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Cred Manipulation - Prevented - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:token_manipulation_event and endgame.metadata.type:prevention", + "risk_score": 47, + "rule_id": "c9e38e64-3f4c-4bf3-ad48-0e61a60ea1fa", + "severity": "medium", + "tags": [ + "Elastic" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json new file mode 100644 index 00000000000000..9c3896a70b3a02 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Exploit detected.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Exploit - Detected - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:exploit_event and endgame.metadata.type:detection", + "risk_score": 73, + "rule_id": "2003cdc8-8d83-4aa5-b132-1f9a8eb48514", + "severity": "high", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json new file mode 100644 index 00000000000000..4632ae6a1487bf --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Exploit prevented.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Exploit - Prevented - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:exploit_event and endgame.metadata.type:prevention", + "risk_score": 47, + "rule_id": "2863ffeb-bf77-44dd-b7a5-93ef94b72036", + "severity": "medium", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json new file mode 100644 index 00000000000000..68831392942d45 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Malware detected.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Malware - Detected - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:file_classification_event and endgame.metadata.type:detection", + "risk_score": 99, + "rule_id": "0a97b20f-4144-49ea-be32-b540ecc445de", + "severity": "critical", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json new file mode 100644 index 00000000000000..56b41df2a33496 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Malware prevented.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Malware - Prevented - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:file_classification_event and endgame.metadata.type:prevention", + "risk_score": 73, + "rule_id": "3b382770-efbb-44f4-beed-f5e0a051b895", + "severity": "high", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json new file mode 100644 index 00000000000000..268dc9cf891214 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Permission theft detected.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Permission Theft - Detected - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:token_protection_event and endgame.metadata.type:detection", + "risk_score": 73, + "rule_id": "c3167e1b-f73c-41be-b60b-87f4df707fe3", + "severity": "high", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json new file mode 100644 index 00000000000000..6deda3d0453b2a --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Permission theft prevented.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Permission Theft - Prevented - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:token_protection_event and endgame.metadata.type:prevention", + "risk_score": 47, + "rule_id": "453f659e-0429-40b1-bfdb-b6957286e04b", + "severity": "medium", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json new file mode 100644 index 00000000000000..25a03e611fe3e7 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Process injection detected.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Process Injection - Detected - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:kernel_shellcode_event and endgame.metadata.type:detection", + "risk_score": 73, + "rule_id": "80c52164-c82a-402c-9964-852533d58be1", + "severity": "high", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json new file mode 100644 index 00000000000000..6c549d70a9d41a --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Process injection prevented.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Process Injection - Prevented - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:kernel_shellcode_event and endgame.metadata.type:prevention", + "risk_score": 47, + "rule_id": "990838aa-a953-4f3e-b3cb-6ddf7584de9e", + "severity": "medium", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json new file mode 100644 index 00000000000000..4a118cf8ab861c --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Ransomware detected.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Ransomware - Detected - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:ransomware_event and endgame.metadata.type:detection", + "risk_score": 99, + "rule_id": "8cb4f625-7743-4dfb-ae1b-ad92be9df7bd", + "severity": "critical", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json new file mode 100644 index 00000000000000..8b48e8f4c17580 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json @@ -0,0 +1,19 @@ +{ + "description": "Elastic Endpoint Security Alert - Ransomware prevented.", + "index": [ + "endgame-*" + ], + "language": "kuery", + "max_signals": 33, + "name": "Ransomware - Prevented - Elastic Endpoint", + "query": "event.kind:alert and event.module:endgame and event.action:ransomware_event and endgame.metadata.type:prevention", + "risk_score": 73, + "rule_id": "e3c5d5cb-41d5-4206-805c-f30561eae3ac", + "severity": "high", + "tags": [ + "Elastic", + "Endpoint" + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json index a65a386cb827e7..374691f670b740 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json @@ -1,17 +1,51 @@ { - "description": "EQL - Adding the Hidden File Attribute with via attrib.exe", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Adversaries can add the 'hidden' attribute to files to hide them from the user in an attempt to evade detection", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Adding the Hidden File Attribute with via attrib.exe", + "max_signals": 33, + "name": "Adding Hidden File Attribute via Attrib", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"attrib.exe\" and process.args:\"+h\"", - "risk_score": 50, + "risk_score": 21, "rule_id": "4630d948-40d4-4cef-ac69-4002e29bc3db", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1158", + "name": "Hidden Files and Directories", + "reference": "https://attack.mitre.org/techniques/T1158/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1158", + "name": "Hidden Files and Directories", + "reference": "https://attack.mitre.org/techniques/T1158/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adobe_hijack_persistence.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adobe_hijack_persistence.json index e5d797f3fc1319..47f171dd7be0ef 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adobe_hijack_persistence.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adobe_hijack_persistence.json @@ -1,17 +1,36 @@ { - "description": "EQL - Adobe Hijack Persistence", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Detects writing executable files that will be automatically launched by Adobe on launch.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Adobe Hijack Persistence", + "max_signals": 33, + "name": "Adobe Hijack Persistence", "query": "file.path:(\"C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader\\AcroCEF\\RdrCEF.exe\" or \"C:\\Program Files\\Adobe\\Acrobat Reader DC\\Reader\\AcroCEF\\RdrCEF.exe\") and event.action:\"File created (rule: FileCreate)\" and not process.name:msiexeec.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "2bf78aa2-9c56-48de-b139-f169bf99cf86", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1044", + "name": "File System Permissions Weakness", + "reference": "https://attack.mitre.org/techniques/T1044/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_audio_capture_via_powershell.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_audio_capture_via_powershell.json index ef65bd3ecef35d..7ec960eea63028 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_audio_capture_via_powershell.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_audio_capture_via_powershell.json @@ -1,17 +1,36 @@ { - "description": "EQL - Audio Capture via PowerShell", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "An adversary can leverage a computer's peripheral devices or applications to capture audio recordings for the purpose of listening into sensitive conversations to gather information.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Audio Capture via PowerShell", + "max_signals": 33, + "name": "Audio Capture via PowerShell", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"powershell.exe\" and process.args:\"WindowsAudioDevice-Powershell-Cmdlet\"", - "risk_score": 50, + "risk_score": 21, "rule_id": "b27b9f47-0a20-4807-8377-7f899b4fbada", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Collection", + "reference": "https://attack.mitre.org/tactics/TA0009/" + }, + "technique": [ + { + "id": "T1123", + "name": "Audio Capture", + "reference": "https://attack.mitre.org/techniques/T1123/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_audio_capture_via_soundrecorder.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_audio_capture_via_soundrecorder.json index 89eec55d827d6d..87bdfc4980124f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_audio_capture_via_soundrecorder.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_audio_capture_via_soundrecorder.json @@ -1,17 +1,36 @@ { - "description": "EQL - Audio Capture via SoundRecorder", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "An adversary can leverage a computer's peripheral devices or applications to capture audio recordings for the purpose of listening into sensitive conversations to gather information.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Audio Capture via SoundRecorder", + "max_signals": 33, + "name": "Audio Capture via SoundRecorder", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"SoundRecorder.exe\" and process.args:\"/FILE\"", - "risk_score": 50, + "risk_score": 21, "rule_id": "f8e06892-ed10-4452-892e-2c5a38d552f1", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Collection", + "reference": "https://attack.mitre.org/tactics/TA0009/" + }, + "technique": [ + { + "id": "T1123", + "name": "Audio Capture", + "reference": "https://attack.mitre.org/techniques/T1123/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_event_viewer.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_event_viewer.json index 80f83991516a67..2fa63fa51f7c12 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_event_viewer.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_event_viewer.json @@ -1,17 +1,36 @@ { - "description": "EQL -Bypass UAC Event Viewer", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies User Account Control (UAC) bypass via eventvwr.exe. Attackers bypass UAC to stealthily execute code with elevated permissions.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL -Bypass UAC Event Viewer", + "max_signals": 33, + "name": "Bypass UAC via Event Viewer", "query": "process.parent.name:eventvwr.exe and event.action:\"Process Create (rule: ProcessCreate)\" and not process.executable:(\"C:\\Windows\\System32\\mmc.exe\" or \"C:\\Windows\\SysWOW64\\mmc.exe\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "59547add-a400-4baa-aa0c-66c72efdb77f", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1088", + "name": "Bypass User Account Control", + "reference": "https://attack.mitre.org/techniques/T1088/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_via_cmstp.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_via_cmstp.json index 0850632c95899d..fdc716dcb3ebeb 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_via_cmstp.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_via_cmstp.json @@ -1,17 +1,36 @@ { - "description": "EQL - Bypass UAC via CMSTP", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies User Account Control (UAC) bypass via cmstp.exe. Attackers bypass UAC to stealthily execute code with elevated permissions.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Bypass UAC via CMSTP", + "max_signals": 33, + "name": "Bypass UAC via Cmstp", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.parent.name:\"cmstp.exe\" and process.parent.args:(\"/s\" and \"/au\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "2f7403da-1a4c-46bb-8ecc-c1a596e10cd0", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1088", + "name": "Bypass User Account Control", + "reference": "https://attack.mitre.org/techniques/T1088/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_via_sdclt.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_via_sdclt.json index 85ba24fd572c37..484a01e0211abb 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_via_sdclt.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_bypass_uac_via_sdclt.json @@ -1,17 +1,36 @@ { - "description": "EQL -Bypass UAC Via sdclt", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies User Account Control (UAC) bypass via sdclt.exe. Attackers bypass UAC to stealthily execute code with elevated permissions.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL -Bypass UAC Via sdclt", + "max_signals": 33, + "name": "Bypass UAC via Sdclt", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"sdclt.exe\" and process.args:\"/kickoffelev\" and not process.executable:(\"C:\\Windows\\System32\\sdclt.exe\" or \"C:\\Windows\\System32\\control.exe\" or \"C:\\Windows\\SysWOW64\\sdclt.exe\" or \"C:\\Windows\\SysWOW64\\control.exe\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "f68d83a1-24cb-4b8d-825b-e8af400b9670", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1088", + "name": "Bypass User Account Control", + "reference": "https://attack.mitre.org/techniques/T1088/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json index 28f45b94049e78..e9729ff102619a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json @@ -1,17 +1,36 @@ { - "description": "EQL - Clearing Windows Event Logs", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies attempts to clear Windows event log stores. This is often done by attackers in an attempt evade detection or destroy forensic evidence on a system.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Clearing Windows Event Logs", + "max_signals": 33, + "name": "Clearing Windows Event Logs", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and (process.name:\"wevtutil.exe\" and process.args:\"cl\") or (process.name:\"powershell.exe\" and process.args:\"Clear-EventLog\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "d331bbe2-6db4-4941-80a5-8270db72eb61", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1070", + "name": "Indicator Removal on Host", + "reference": "https://attack.mitre.org/techniques/T1070/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json index 6f00427656af6f..479bb4a2a6d7c6 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json @@ -1,17 +1,36 @@ { - "description": "EQL - Delete Volume USN Journal with fsutil", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of the fsutil.exe to delete the volume USNJRNL. This technique is used by attackers to eliminate evidence of files created during post-exploitation activities.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Delete Volume USN Journal with fsutil", + "max_signals": 33, + "name": "Delete Volume USN Journal with Fsutil", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"fsutil.exe\" and process.args:(\"usn\" and \"deletejournal\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "f675872f-6d85-40a3-b502-c0d2ef101e92", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1107", + "name": "File Deletion", + "reference": "https://attack.mitre.org/techniques/T1107/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json index 8f5b21b74ee6a3..204925e4b677b4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json @@ -1,17 +1,36 @@ { - "description": "EQL - Deleting Backup Catalogs with wbadmin", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of the wbadmin.exe to delete the backup catalog. Ransomware and other malware may do this to prevent system recovery.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Deleting Backup Catalogs with wbadmin", + "max_signals": 33, + "name": "Deleting Backup Catalogs with Wbadmin", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"wbadmin.exe\" and process.args:(\"delete\" and \"catalog\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "581add16-df76-42bb-af8e-c979bfb39a59", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1107", + "name": "File Deletion", + "reference": "https://attack.mitre.org/techniques/T1107/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json index 56f0b2efec620c..b6398a9985e7e4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json @@ -1,17 +1,36 @@ { - "description": "EQL - Direct Outbound SMB Connection", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies unexpected processes making network connections over port 445. Windows File Sharing is typically implemented over Server Message Block (SMB), which communicates between hosts using port 445. When legitimate, these network connections are established by the kernel. Processes making 445/tcp connections may be port scanners, exploits, or suspicious user-level processes moving laterally.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Direct Outbound SMB Connection", + "max_signals": 33, + "name": "Direct Outbound SMB Connection", "query": " event.action:\"Network connection detected (rule: NetworkConnect)\" and destination.port:445 and not process.pid:4 and not destination.ip:(\"127.0.0.1\" or \"::1\")", - "risk_score": 50, + "risk_score": 47, "rule_id": "c82c7d8f-fb9e-4874-a4bd-fd9e3f9becf1", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1210", + "name": "Exploitation of Remote Services", + "reference": "https://attack.mitre.org/techniques/T1210/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json index 4d1e32eb298978..32b43cc24e91b2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json @@ -1,17 +1,36 @@ { - "description": "EQL - Disable Windows Firewall Rules with Netsh", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of the netsh.exe to disable or weaken the local firewall. Attackers will use this command line tool to disable the firewall during troubleshooting or to enable network mobility.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Disable Windows Firewall Rules with Netsh", + "max_signals": 33, + "name": "Disable Windows Firewall Rules via Netsh", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"netsh.exe\" and process.args:(\"firewall\" and \"set\" and \"disable\") or process.args:(\"advfirewall\" and \"state\" and \"off\")", - "risk_score": 50, + "risk_score": 47, "rule_id": "4b438734-3793-4fda-bd42-ceeada0be8f9", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1089", + "name": "Disabling Security Tools", + "reference": "https://attack.mitre.org/techniques/T1089/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_dll_search_order_hijack.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_dll_search_order_hijack.json index b9bf463a8e5f22..5740453b6ae6d8 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_dll_search_order_hijack.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_dll_search_order_hijack.json @@ -1,17 +1,51 @@ { - "description": "EQL - DLL Search Order Hijack", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Detects writing DLL files to known locations associated with Windows files vulnerable to DLL search order hijacking.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - DLL Search Order Hijack", + "max_signals": 33, + "name": "DLL Search Order Hijack", "query": " event.action:\"File created (rule: FileCreate)\" and not winlog.user.identifier:(\"S-1-5-18\" or \"S-1-5-19\" or \"S-1-5-20\") and file.path:(\"C\\Windows\\ehome\\cryptbase.dll\" or \"C\\Windows\\System32\\Sysprep\\cryptbase.dll\" or \"C\\Windows\\System32\\Sysprep\\cryptsp.dll\" or \"C\\Windows\\System32\\Sysprep\\rpcrtremote.dll\" or \"C\\Windows\\System32\\Sysprep\\uxtheme.dll\" or \"C\\Windows\\System32\\Sysprep\\dwmapi.dll\" or \"C\\Windows\\System32\\Sysprep\\shcore.dll\" or \"C\\Windows\\System32\\Sysprep\\oleacc.dll\" or \"C\\Windows\\System32\\ntwdblib.dll\") ", - "risk_score": 50, + "risk_score": 47, "rule_id": "73fbc44c-c3cd-48a8-a473-f4eb2065c716", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1088", + "name": "Bypass User Account Control", + "reference": "https://attack.mitre.org/techniques/T1088/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1088", + "name": "Bypass User Account Control", + "reference": "https://attack.mitre.org/techniques/T1088/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json index 6b4ffd9cb21e3b..37e1c26885a157 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json @@ -1,17 +1,36 @@ { - "description": "EQL - Encoding or Decoding Files via CertUtil", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies the use of certutil.exe to encode or decode data. CertUtil is a native Windows component which is part of Certificate Services. CertUtil is often abused by attackers to encode or decode base64 data for stealthier command and control or exfiltration.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Encoding or Decoding Files via CertUtil", + "max_signals": 33, + "name": "Encoding or Decoding Files via CertUtil", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"certutil.exe\" and process.args:(\"-encode\" or \"/encode\" or \"-decode\" or \"/decode\")", - "risk_score": 50, + "risk_score": 47, "rule_id": "fd70c98a-c410-42dc-a2e3-761c71848acf", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1140", + "name": "Deobfuscate/Decode Files or Information", + "reference": "https://attack.mitre.org/techniques/T1140/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json index f09983d26aff50..dc4991f86a0f54 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json @@ -1,17 +1,39 @@ { - "description": "EQL - Local Scheduled Task Commands", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "A scheduled task can be used by an adversary to establish persistence, move laterally, and/or escalate privileges.", + "false_positives": [ + "Legitimate scheduled tasks may be created during installation of new software." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Local Scheduled Task Commands", + "max_signals": 33, + "name": "Local Scheduled Task Commands", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.name:schtasks.exe and process.args:(\"/create\" or \"-create\" or \"/S\" or \"-s\" or \"/run\" or \"-run\" or \"/change\" or \"-change\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "afcce5ad-65de-4ed2-8516-5e093d3ac99a", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1053", + "name": "Scheduled Task", + "reference": "https://attack.mitre.org/techniques/T1053/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json index d33a3dbe6de814..eb6f2377376f28 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json @@ -1,17 +1,36 @@ { - "description": "EQL - Local Service Commands", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of sc.exe to create, modify, or start services on remote hosts. This could be indicative of adversary lateral movement but will be noisy if commonly done by admins.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Local Service Commands", + "max_signals": 33, + "name": "Local Service Commands", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:sc.exe and process.args:(\"create\" or \"config\" or \"failure\" or \"start\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "e8571d5f-bea1-46c2-9f56-998de2d3ed95", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1021", + "name": "Remote Services", + "reference": "https://attack.mitre.org/techniques/T1021/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_modification_of_boot_configuration.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_modification_of_boot_configuration.json index 39dc2547520737..26bd65b897c63a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_modification_of_boot_configuration.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_modification_of_boot_configuration.json @@ -1,17 +1,36 @@ { - "description": "EQL - Modification of Boot Configuration", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of bcdedit.exe to delete boot configuration data. This tactic is sometimes used as by malware or an attacker as a destructive technique.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Modification of Boot Configuration", + "max_signals": 33, + "name": "Modification of Boot Configuration", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"bcdedit.exe\" and process.args:\"set\" and process.args:( (\"bootstatuspolicy\" and \"ignoreallfailures\") or (\"recoveryenabled\" and \"no\") ) ", - "risk_score": 50, + "risk_score": 73, "rule_id": "b9ab2f7f-f719-4417-9599-e0252fffe2d8", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1107", + "name": "File Deletion", + "reference": "https://attack.mitre.org/techniques/T1107/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json index dd8fab2d8ad706..d40ffed523c6a4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json @@ -1,17 +1,36 @@ { - "description": "EQL - MsBuild Making Network Connections", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies MsBuild.exe making outbound network connections. This may indicate adversarial activity as MsBuild is often leveraged by adversaries to execute code and evade detection.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - MsBuild Making Network Connections", + "max_signals": 33, + "name": "MsBuild Making Network Connections", "query": " event.action:\"Network connection detected (rule: NetworkConnect)\" and process.name:msbuild.exe and not destination.ip:(\"127.0.0.1\" or \"::1\")", - "risk_score": 50, + "risk_score": 47, "rule_id": "0e79980b-4250-4a50-a509-69294c14e84b", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1127", + "name": "Trusted Developer Utilities", + "reference": "https://attack.mitre.org/techniques/T1127/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json index 8037cc9bcba7f0..7905d80c6e8c29 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json @@ -1,17 +1,39 @@ { - "description": "EQL - Mshta Making Network Connections", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies mshta.exe making a network connection. This may indicate adversarial activity as mshta.exe is often leveraged by adversaries to execute malicious scripts and evade detection.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Mshta Making Network Connections", + "max_signals": 33, + "name": "Network Connection via Mshta", "query": "event.action:\"Network connection detected (rule: NetworkConnect)\" and process.name:\"mshta.exe\" and not process.name:\"mshta.exe\"", - "risk_score": 50, + "references": [ + "https://www.fireeye.com/blog/threat-research/2017/05/cyber-espionage-apt32.html" + ], + "risk_score": 47, "rule_id": "a4ec1382-4557-452b-89ba-e413b22ed4b8", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1170", + "name": "Mshta", + "reference": "https://attack.mitre.org/techniques/T1170/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msxsl_making_network_connections.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msxsl_making_network_connections.json index 5dd6d5d3042c6d..16ef15589f48f7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msxsl_making_network_connections.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msxsl_making_network_connections.json @@ -1,17 +1,36 @@ { - "description": "EQL - MsXsl Making Network Connections", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies msxsl.exe making a network connection. This may indicate adversarial activity as msxsl.exe is often leveraged by adversaries to execute malicious scripts and evade detection.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - MsXsl Making Network Connections", + "max_signals": 33, + "name": "Network Connection via MsXsl", "query": "process.name:msxsl.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "risk_score": 47, "rule_id": "d7351b03-135d-43ba-8b36-cc9b07854525", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1220", + "name": "XSL Script Processing", + "reference": "https://attack.mitre.org/techniques/T1220/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json index d83f7796cd4d1a..fd210005118b84 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json @@ -1,17 +1,54 @@ { - "description": "EQL - PsExec Lateral Movement Command", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of the SysInternals tool PsExec.exe making a network connection. This could be an indication of lateral movement.", + "false_positives": [ + "PsExec is a dual-use tool that can be used for benign or malicious activity. It's important to baseline your environment to determine the amount of noise to expect from this tool." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - PsExec Lateral Movement Command", + "max_signals": 33, + "name": "PsExec Network Connection", "query": "process.name:psexec.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" ", - "risk_score": 50, + "risk_score": 21, "rule_id": "55d551c6-333b-4665-ab7e-5d14a59715ce", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1035", + "name": "Service Execution", + "reference": "https://attack.mitre.org/techniques/T1035/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1035", + "name": "Service Execution", + "reference": "https://attack.mitre.org/techniques/T1035/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_office_child_process.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_office_child_process.json index 5746541dd879cf..a5d71e23a1215a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_office_child_process.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_office_child_process.json @@ -1,17 +1,36 @@ { - "description": "EQL - Suspicious MS Office Child Process", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies suspicious child processes of frequently targeted Microsoft Office applications (Word, PowerPoint, Excel). These child processes are often launched during exploitation of Office applications or from documents with malicious macros.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Suspicious MS Office Child Process", + "max_signals": 33, + "name": "Suspicious MS Office Child Process", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.parent.name:(\"winword.exe\" or \"excel.exe\" or \"powerpnt.exe\" or \"eqnedt32.exe\" or \"fltldr.exe\" or \"mspub.exe\" or \"msaccess.exe\") and process.name:(\"arp.exe\" or \"dsquery.exe\" or \"dsget.exe\" or \"gpresult.exe\" or \"hostname.exe\" or \"ipconfig.exe\" or \"nbtstat.exe\" or \"net.exe\" or \"net1.exe\" or \"netsh.exe\" or \"netstat.exe\" or \"nltest.exe\" or \"ping.exe\" or \"qprocess.exe\" or \"quser.exe\" or \"qwinsta.exe\" or \"reg.exe\" or \"sc.exe\" or \"systeminfo.exe\" or \"tasklist.exe\" or \"tracert.exe\" or \"whoami.exe\" or \"bginfo.exe\" or \"cdb.exe\" or \"cmstp.exe\" or \"csi.exe\" or \"dnx.exe\" or \"fsi.exe\" or \"ieexec.exe\" or \"iexpress.exe\" or \"installutil.exe\" or \"Microsoft.Workflow.Compiler.exe\" or \"msbuild.exe\" or \"mshta.exe\" or \"msxsl.exe\" or \"odbcconf.exe\" or \"rcsi.exe\" or \"regsvr32.exe\" or \"xwizard.exe\" or \"atbroker.exe\" or \"forfiles.exe\" or \"schtasks.exe\" or \"regasm.exe\" or \"regsvcs.exe\" or \"cmd.exe\" or \"cscript.exe\" or \"powershell.exe\" or \"pwsh.exe\" or \"wmic.exe\" or \"wscript.exe\" or \"bitsadmin.exe\" or \"certutil.exe\" or \"ftp.exe\") ", - "risk_score": 50, + "risk_score": 21, "rule_id": "a624863f-a70d-417f-a7d2-7a404638d47f", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1193", + "name": "Spearphishing Attachment", + "reference": "https://attack.mitre.org/techniques/T1193/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_outlook_child_process.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_outlook_child_process.json index 88ce75eeef34e8..86716d66080492 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_outlook_child_process.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_outlook_child_process.json @@ -1,17 +1,36 @@ { - "description": "EQL - Suspicious MS Outlook Child Process", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies suspicious child processes of Microsoft Outlook. These child processes are often associated with spear phishing activity.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Suspicious MS Outlook Child Process", + "max_signals": 33, + "name": "Suspicious MS Outlook Child Process", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.parent.name:\"outlook.exe\" and process.name:(\"arp.exe\" or \"dsquery.exe\" or \"dsget.exe\" or \"gpresult.exe\" or \"hostname.exe\" or \"ipconfig.exe\" or \"nbtstat.exe\" or \"net.exe\" or \"net1.exe\" or \"netsh.exe\" or \"netstat.exe\" or \"nltest.exe\" or \"ping.exe\" or \"qprocess.exe\" or \"quser.exe\" or \"qwinsta.exe\" or \"reg.exe\" or \"sc.exe\" or \"systeminfo.exe\" or \"tasklist.exe\" or \"tracert.exe\" or \"whoami.exe\" or \"bginfo.exe\" or \"cdb.exe\" or \"cmstp.exe\" or \"csi.exe\" or \"dnx.exe\" or \"fsi.exe\" or \"ieexec.exe\" or \"iexpress.exe\" or \"installutil.exe\" or \"Microsoft.Workflow.Compiler.exe\" or \"msbuild.exe\" or \"mshta.exe\" or \"msxsl.exe\" or \"odbcconf.exe\" or \"rcsi.exe\" or \"regsvr32.exe\" or \"xwizard.exe\" or \"atbroker.exe\" or \"forfiles.exe\" or \"schtasks.exe\" or \"regasm.exe\" or \"regsvcs.exe\" or \"cmd.exe\" or \"cscript.exe\" or \"powershell.exe\" or \"pwsh.exe\" or \"wmic.exe\" or \"wscript.exe\" or \"bitsadmin.exe\" or \"certutil.exe\" or \"ftp.exe\") ", - "risk_score": 50, + "risk_score": 21, "rule_id": "32f4675e-6c49-4ace-80f9-97c9259dca2e", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1193", + "name": "Spearphishing Attachment", + "reference": "https://attack.mitre.org/techniques/T1193/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_pdf_reader_child_process.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_pdf_reader_child_process.json index 2e3a654127b53e..b0fbccf1b67a70 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_pdf_reader_child_process.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_pdf_reader_child_process.json @@ -1,17 +1,36 @@ { - "description": "EQL - Suspicious PDF Reader Child Process", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies suspicious child processes of PDF reader applications. These child processes are often launched via exploitation of PDF applications or social engineering.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Suspicious PDF Reader Child Process", + "max_signals": 33, + "name": "Suspicious PDF Reader Child Process", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.parent.name:(\"acrord32.exe\" or \"rdrcef.exe\" or \"foxitphantomPDF.exe\" or \"foxitreader.exe\") and process.name:(\"arp.exe\" or \"dsquery.exe\" or \"dsget.exe\" or \"gpresult.exe\" or \"hostname.exe\" or \"ipconfig.exe\" or \"nbtstat.exe\" or \"net.exe\" or \"net1.exe\" or \"netsh.exe\" or \"netstat.exe\" or \"nltest.exe\" or \"ping.exe\" or \"qprocess.exe\" or \"quser.exe\" or \"qwinsta.exe\" or \"reg.exe\" or \"sc.exe\" or \"systeminfo.exe\" or \"tasklist.exe\" or \"tracert.exe\" or \"whoami.exe\" or \"bginfo.exe\" or \"cdb.exe\" or \"cmstp.exe\" or \"csi.exe\" or \"dnx.exe\" or \"fsi.exe\" or \"ieexec.exe\" or \"iexpress.exe\" or \"installutil.exe\" or \"Microsoft.Workflow.Compiler.exe\" or \"msbuild.exe\" or \"mshta.exe\" or \"msxsl.exe\" or \"odbcconf.exe\" or \"rcsi.exe\" or \"regsvr32.exe\" or \"xwizard.exe\" or \"atbroker.exe\" or \"forfiles.exe\" or \"schtasks.exe\" or \"regasm.exe\" or \"regsvcs.exe\" or \"cmd.exe\" or \"cscript.exe\" or \"powershell.exe\" or \"pwsh.exe\" or \"wmic.exe\" or \"wscript.exe\" or \"bitsadmin.exe\" or \"certutil.exe\" or \"ftp.exe\") ", - "risk_score": 50, + "risk_score": 73, "rule_id": "afcac7b1-d092-43ff-a136-aa7accbda38f", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1193", + "name": "Spearphishing Attachment", + "reference": "https://attack.mitre.org/techniques/T1193/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json index 20080719f3ed3b..984b522596c1e0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json @@ -1,17 +1,36 @@ { - "description": "EQL - System Shells via Services", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Windows services typically run as SYSTEM and can be used as a privilege escalation opportunity. Malware or penetration testers may run a shell as a service to gain SYSTEM permissions.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - System Shells via Services", + "max_signals": 33, + "name": "System Shells via Services", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.parent.name:\"services.exe\" and process.name:(\"cmd.exe\" or \"powershell.exe\")", - "risk_score": 50, + "risk_score": 47, "rule_id": "0022d47d-39c7-4f69-a232-4fe9dc7a3acd", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1050", + "name": "New Service", + "reference": "https://attack.mitre.org/techniques/T1050/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json index 79f8f8e1f606c8..03b9bebb655c3a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json @@ -1,17 +1,36 @@ { - "description": "EQL - Unusual Network Connection via RunDLL32", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies unusual instances of rundll32.exe making outbound network connections. This may indicate adversarial activity and may identify malicious DLLs.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Unusual Network Connection via RunDLL32", + "max_signals": 33, + "name": "Unusual Network Connection via RunDLL32", "query": "process.name:rundll32.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "risk_score": 21, "rule_id": "52aaab7b-b51c-441a-89ce-4387b3aea886", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1085", + "name": "Rundll32", + "reference": "https://attack.mitre.org/techniques/T1085/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json index 28cce6ed89f8b0..72eb17863e0d3b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json @@ -1,17 +1,36 @@ { - "description": "EQL - Unusual Parent-Child Relationship ", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies Windows programs run from unexpected parent processes. This could indicate masquerading or other strange activity on a system.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Unusual Parent-Child Relationship ", + "max_signals": 33, + "name": "Unusual Parent-Child Relationship ", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.parent.executable:* and ( (process.name:\"smss.exe\" and not process.parent.name:(\"System\" or \"smss.exe\")) or (process.name:\"csrss.exe\" and not process.parent.name:(\"smss.exe\" or \"svchost.exe\")) or (process.name:\"wininit.exe\" and not process.parent.name:\"smss.exe\") or (process.name:\"winlogon.exe\" and not process.parent.name:\"smss.exe\") or (process.name:\"lsass.exe\" and not process.parent.name:\"wininit.exe\") or (process.name:\"LogonUI.exe\" and not process.parent.name:(\"winlogon.exe\" or \"wininit.exe\")) or (process.name:\"services.exe\" and not process.parent.name:\"wininit.exe\") or (process.name:\"svchost.exe\" and not process.parent.name:(\"services.exe\" or \"MsMpEng.exe\")) or (process.name:\"spoolsv.exe\" and not process.parent.name:\"services.exe\") or (process.name:\"taskhost.exe\" and not process.parent.name:(\"services.exe\" or \"svchost.exe\")) or (process.name:\"taskhostw.exe\" and not process.parent.name:(\"services.exe\" or \"svchost.exe\")) or (process.name:\"userinit.exe\" and not process.parent.name:(\"dwm.exe\" or \"winlogon.exe\")) )", - "risk_score": 50, + "risk_score": 47, "rule_id": "35df0dd8-092d-4a83-88c1-5151a804f31b", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1093", + "name": "Process Hollowing", + "reference": "https://attack.mitre.org/techniques/T1093/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json index 8b84ec4ff34f48..8ca16198ff1752 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json @@ -1,17 +1,36 @@ { - "description": "EQL - Unusual Process Network Connection", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies network activity from unexpected system applications. This may indicate adversarial activity as these applications are often leveraged by adversaries to execute code and evade detection.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Unusual Process Network Connection", + "max_signals": 33, + "name": "Unusual Process Network Connection", "query": " event.action:\"Network connection detected (rule: NetworkConnect)\" and process.name:(bginfo.exe or cdb.exe or cmstp.exe or csi.exe or dnx.exe or fsi.exe or ieexec.exe or iexpress.exe or Microsoft.Workflow.Compiler.exe or odbcconf.exe or rcsi.exe or xwizard.exe)", - "risk_score": 50, + "risk_score": 21, "rule_id": "610949a1-312f-4e04-bb55-3a79b8c95267", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1127", + "name": "Trusted Developer Utilities", + "reference": "https://attack.mitre.org/techniques/T1127/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json index 3af9d9c4277511..dee3d18bd5eda5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json @@ -1,17 +1,36 @@ { - "description": "EQL - User Account Creation", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies attempts to create new local users. This is sometimes done by attackers to increase access to a system or domain.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - User Account Creation", + "max_signals": 33, + "name": "User Account Creation", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.name:(\"net.exe\" or \"net1.exe\") and not process.parent.name:\"net.exe\" and process.args:(\"user\" and (\"/add\" or \"/ad\")) ", - "risk_score": 50, + "risk_score": 21, "rule_id": "1aa9181a-492b-4c01-8b16-fa0735786b2b", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1136", + "name": "Create Account", + "reference": "https://attack.mitre.org/techniques/T1136/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_added_to_administrator_group.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_added_to_administrator_group.json index 226f2dd1e39342..4ed6a06b18d3b0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_added_to_administrator_group.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_added_to_administrator_group.json @@ -1,17 +1,36 @@ { - "description": "EQL - User Added to Administrator Group", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies attempts to add a user to an administrative group with the \"net.exe\" command. This is sometimes done by attackers to increase access of a compromised account or create new account.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - User Added to Administrator Group", + "max_signals": 33, + "name": "User Added to Administrator Group", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.name:(\"net.exe\" or \"net1.exe\") and not process.parent.name:\"net.exe\" and process.args:(\"group\" and \"admin\" and \"/add\") ", - "risk_score": 50, + "risk_score": 47, "rule_id": "4426de6f-6103-44aa-a77e-49d672836c27", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1098", + "name": "Account Manipulation", + "reference": "https://attack.mitre.org/techniques/T1098/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json index 2b27bce457aff8..cdeeb1563dfde5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json @@ -1,17 +1,36 @@ { - "description": "EQL - Volume Shadow Copy Deletion via VssAdmin", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of vssadmin.exe for shadow copy deletion on endpoints. This commonly occurs in tandem with ransomware or other destructive attacks.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Volume Shadow Copy Deletion via VssAdmin", + "max_signals": 33, + "name": "Volume Shadow Copy Deletion via VssAdmin", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"vssadmin.exe\" and process.args:(\"delete\" and \"shadows\") ", - "risk_score": 50, + "risk_score": 73, "rule_id": "b5ea4bfe-a1b2-421f-9d47-22a75a6f2921", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1490", + "name": "Inhibit System Recovery", + "reference": "https://attack.mitre.org/techniques/T1490/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json index 4ec4530cc967f7..9465cf84d73f4b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json @@ -1,17 +1,36 @@ { - "description": "EQL - Volume Shadow Copy Deletion via WMIC", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of wmic.exe for shadow copy deletion on endpoints. This commonly occurs in tandem with ransomware or other destructive attacks.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Volume Shadow Copy Deletion via WMIC", + "max_signals": 33, + "name": "Volume Shadow Copy Deletion via WMIC", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"wmic.exe\" and process.args:(\"shadowcopy\" and \"delete\")", - "risk_score": 50, + "risk_score": 73, "rule_id": "dc9c1f74-dac3-48e3-b47f-eb79db358f57", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1107", + "name": "File Deletion", + "reference": "https://attack.mitre.org/techniques/T1107/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json index da96eb39e4d96a..f3df1276de53d5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json @@ -1,17 +1,36 @@ { - "description": "EQL - Windows Script Executing PowerShell", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies a PowerShell process launched by either cscript.exe or wscript.exe. Observing Windows scripting processes executing a PowerShell script, may be indicative of malicious activity.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - Windows Script Executing PowerShell", + "max_signals": 33, + "name": "Windows Script Executing PowerShell", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.parent.name:(\"wscript.exe\" or \"cscript.exe\") and process.name:\"powershell.exe\"", - "risk_score": 50, + "risk_score": 21, "rule_id": "f545ff26-3c94-4fd0-bd33-3c7f95a3a0fc", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1193", + "name": "Spearphishing Attachment", + "reference": "https://attack.mitre.org/techniques/T1193/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_wmic_command_lateral_movement.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_wmic_command_lateral_movement.json index 3f1c22e2a55d99..a50d9e64f2e2b5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_wmic_command_lateral_movement.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_wmic_command_lateral_movement.json @@ -1,17 +1,39 @@ { - "description": "EQL - WMIC Command Lateral Movement", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of wmic.exe to run commands on remote hosts. This could be indicative of adversary lateral movement but will be noisy if commonly done by admins.", + "false_positives": [ + "The WMIC utility provides a command-line interface for WMI, which can be used for an array of administrative capabilities. It's important to baseline your environment to determine any abnormal use of this tool." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "EQL - WMIC Command Lateral Movement", + "max_signals": 33, + "name": "WMIC Command Lateral Movement", "query": " event.action:\"Process Create (rule: ProcessCreate)\" and process.name:\"wmic.exe\" and process.args:(\"/node\" or \"-node\") and process.args:(\"call\" or \"set\")", - "risk_score": 50, + "risk_score": 21, "rule_id": "9616587f-6396-42d0-bd31-ef8dbd806210", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1047", + "name": "Windows Management Instrumentation", + "reference": "https://attack.mitre.org/techniques/T1047/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/index.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/index.ts index 6ef81addd846ec..cd6d899133bff1 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/index.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/index.ts @@ -9,307 +9,117 @@ import rule1 from './403_response_to_a_post.json'; import rule2 from './405_response_method_not_allowed.json'; -import rule3 from './500_response_on_admin_page.json'; -import rule4 from './eql_adding_the_hidden_file_attribute_with_via_attribexe.json'; -import rule5 from './eql_adobe_hijack_persistence.json'; -import rule6 from './eql_audio_capture_via_powershell.json'; -import rule7 from './eql_audio_capture_via_soundrecorder.json'; -import rule8 from './eql_bypass_uac_event_viewer.json'; -import rule9 from './eql_bypass_uac_via_cmstp.json'; -import rule10 from './eql_bypass_uac_via_sdclt.json'; -import rule11 from './eql_clearing_windows_event_logs.json'; -import rule12 from './eql_delete_volume_usn_journal_with_fsutil.json'; -import rule13 from './eql_deleting_backup_catalogs_with_wbadmin.json'; -import rule14 from './eql_direct_outbound_smb_connection.json'; -import rule15 from './eql_disable_windows_firewall_rules_with_netsh.json'; -import rule16 from './eql_dll_search_order_hijack.json'; -import rule17 from './eql_encoding_or_decoding_files_via_certutil.json'; -import rule18 from './eql_local_scheduled_task_commands.json'; -import rule19 from './eql_local_service_commands.json'; -import rule20 from './eql_modification_of_boot_configuration.json'; -import rule21 from './eql_msbuild_making_network_connections.json'; -import rule22 from './eql_mshta_making_network_connections.json'; -import rule23 from './eql_msxsl_making_network_connections.json'; -import rule24 from './eql_psexec_lateral_movement_command.json'; -import rule25 from './eql_suspicious_ms_office_child_process.json'; -import rule26 from './eql_suspicious_ms_outlook_child_process.json'; -import rule27 from './eql_suspicious_pdf_reader_child_process.json'; -import rule28 from './eql_system_shells_via_services.json'; -import rule29 from './eql_unusual_network_connection_via_rundll32.json'; -import rule30 from './eql_unusual_parentchild_relationship.json'; -import rule31 from './eql_unusual_process_network_connection.json'; -import rule32 from './eql_user_account_creation.json'; -import rule33 from './eql_user_added_to_administrator_group.json'; -import rule34 from './eql_volume_shadow_copy_deletion_via_vssadmin.json'; -import rule35 from './eql_volume_shadow_copy_deletion_via_wmic.json'; -import rule36 from './eql_windows_script_executing_powershell.json'; -import rule37 from './eql_wmic_command_lateral_movement.json'; -import rule38 from './linux_hping_activity.json'; -import rule39 from './linux_iodine_activity.json'; -import rule40 from './linux_kernel_module_activity.json'; -import rule41 from './linux_ldso_process_activity.json'; -import rule42 from './linux_lzop_activity.json'; -import rule43 from './linux_mknod_activity.json'; -import rule44 from './linux_netcat_network_connection.json'; -import rule45 from './linux_network_anomalous_process_using_https_ports.json'; -import rule46 from './linux_nmap_activity.json'; -import rule47 from './linux_nping_activity.json'; -import rule48 from './linux_process_started_in_temp_directory.json'; -import rule49 from './linux_ptrace_activity.json'; -import rule50 from './linux_rawshark_activity.json'; -import rule51 from './linux_shell_activity_by_web_server.json'; -import rule52 from './linux_socat_activity.json'; -import rule53 from './linux_ssh_forwarding.json'; -import rule54 from './linux_strace_activity.json'; -import rule55 from './linux_tcpdump_activity.json'; -import rule56 from './linux_web_download.json'; -import rule57 from './linux_whoami_commmand.json'; -import rule58 from './network_dns_directly_to_the_internet.json'; -import rule59 from './network_ftp_file_transfer_protocol_activity_to_the_internet.json'; -import rule60 from './network_irc_internet_relay_chat_protocol_activity_to_the_internet.json'; -import rule61 from './network_nat_traversal_port_activity.json'; -import rule62 from './network_port_26_activity.json'; -import rule63 from './network_port_8000_activity.json'; -import rule64 from './network_port_8000_activity_to_the_internet.json'; -import rule65 from './network_pptp_point_to_point_tunneling_protocol_activity.json'; -import rule66 from './network_proxy_port_activity_to_the_internet.json'; -import rule67 from './network_rdp_remote_desktop_protocol_from_the_internet.json'; -import rule68 from './network_rdp_remote_desktop_protocol_to_the_internet.json'; -import rule69 from './network_rpc_remote_procedure_call_from_the_internet.json'; -import rule70 from './network_rpc_remote_procedure_call_to_the_internet.json'; -import rule71 from './network_smb_windows_file_sharing_activity_to_the_internet.json'; -import rule72 from './network_smtp_to_the_internet.json'; -import rule73 from './network_sql_server_port_activity_to_the_internet.json'; -import rule74 from './network_ssh_secure_shell_from_the_internet.json'; -import rule75 from './network_ssh_secure_shell_to_the_internet.json'; -import rule76 from './network_telnet_port_activity.json'; -import rule77 from './network_tor_activity_to_the_internet.json'; -import rule78 from './network_vnc_virtual_network_computing_from_the_internet.json'; -import rule79 from './network_vnc_virtual_network_computing_to_the_internet.json'; -import rule80 from './null_user_agent.json'; -import rule81 from './sqlmap_user_agent.json'; -import rule82 from './suricata_base64_encoded_invokecommand_powershell_execution.json'; -import rule83 from './suricata_base64_encoded_newobject_powershell_execution.json'; -import rule84 from './suricata_base64_encoded_startprocess_powershell_execution.json'; -import rule85 from './suricata_category_a_suspicious_string_was_detected.json'; -import rule86 from './suricata_category_attempted_administrator_privilege_gain.json'; -import rule87 from './suricata_category_attempted_denial_of_service.json'; -import rule88 from './suricata_category_attempted_information_leak.json'; -import rule89 from './suricata_category_attempted_login_with_suspicious_username.json'; -import rule90 from './suricata_category_attempted_user_privilege_gain.json'; -import rule91 from './suricata_category_client_using_unusual_port.json'; -import rule92 from './suricata_category_crypto_currency_mining_activity.json'; -import rule93 from './suricata_category_decode_of_an_rpc_query.json'; -import rule94 from './suricata_category_default_username_and_password_login_attempt.json'; -import rule95 from './suricata_category_denial_of_service.json'; -import rule96 from './suricata_category_denial_of_service_attack.json'; -import rule97 from './suricata_category_executable_code_was_detected.json'; -import rule98 from './suricata_category_exploit_kit_activity.json'; -import rule99 from './suricata_category_external_ip_address_retrieval.json'; -import rule100 from './suricata_category_generic_icmp_event.json'; -import rule101 from './suricata_category_generic_protocol_command_decode.json'; -import rule102 from './suricata_category_information_leak.json'; -import rule103 from './suricata_category_large_scale_information_leak.json'; -import rule104 from './suricata_category_malware_command_and_control_activity.json'; -import rule105 from './suricata_category_misc_activity.json'; -import rule106 from './suricata_category_misc_attack.json'; -import rule107 from './suricata_category_network_scan_detected.json'; -import rule108 from './suricata_category_network_trojan_detected.json'; -import rule109 from './suricata_category_nonstandard_protocol_or_event.json'; -import rule110 from './suricata_category_not_suspicious_traffic.json'; -import rule111 from './suricata_category_observed_c2_domain.json'; -import rule112 from './suricata_category_possible_social_engineering_attempted.json'; -import rule113 from './suricata_category_possibly_unwanted_program.json'; -import rule114 from './suricata_category_potential_corporate_privacy_violation.json'; -import rule115 from './suricata_category_potentially_bad_traffic.json'; -import rule116 from './suricata_category_potentially_vulnerable_web_application_access.json'; -import rule117 from './suricata_category_successful_administrator_privilege_gain.json'; -import rule118 from './suricata_category_successful_credential_theft.json'; -import rule119 from './suricata_category_successful_user_privilege_gain.json'; -import rule120 from './suricata_category_suspicious_filename_detected.json'; -import rule121 from './suricata_category_system_call_detected.json'; -import rule122 from './suricata_category_targeted_malicious_activity.json'; -import rule123 from './suricata_category_tcp_connection_detected.json'; -import rule124 from './suricata_category_unknown_traffic.json'; -import rule125 from './suricata_category_unsuccessful_user_privilege_gain.json'; -import rule126 from './suricata_category_web_application_attack.json'; -import rule127 from './suricata_cobaltstrike_artifact_in_an_dns_request.json'; -import rule128 from './suricata_commonly_abused_dns_domain_detected.json'; -import rule129 from './suricata_directory_reversal_characters_in_an_http_request.json'; -import rule130 from './suricata_directory_traversal_characters_in_an_http_request.json'; -import rule131 from './suricata_directory_traversal_characters_in_http_response.json'; -import rule132 from './suricata_directory_traversal_in_downloaded_zip_file.json'; -import rule133 from './suricata_dns_traffic_on_unusual_tcp_port.json'; -import rule134 from './suricata_dns_traffic_on_unusual_udp_port.json'; -import rule135 from './suricata_double_encoded_characters_in_a_uri.json'; -import rule136 from './suricata_double_encoded_characters_in_an_http_post.json'; -import rule137 from './suricata_double_encoded_characters_in_http_request.json'; -import rule138 from './suricata_eval_php_function_in_an_http_request.json'; -import rule139 from './suricata_exploit_cve_2018_1000861.json'; -import rule140 from './suricata_exploit_cve_2019_0227.json'; -import rule141 from './suricata_exploit_cve_2019_0232.json'; -import rule142 from './suricata_exploit_cve_2019_0604.json'; -import rule143 from './suricata_exploit_cve_2019_0708.json'; -import rule144 from './suricata_exploit_cve_2019_0752.json'; -import rule145 from './suricata_exploit_cve_2019_1003000.json'; -import rule146 from './suricata_exploit_cve_2019_10149.json'; -import rule147 from './suricata_exploit_cve_2019_11043.json'; -import rule148 from './suricata_exploit_cve_2019_11510.json'; -import rule149 from './suricata_exploit_cve_2019_11580.json'; -import rule150 from './suricata_exploit_cve_2019_11581.json'; -import rule151 from './suricata_exploit_cve_2019_13450.json'; -import rule152 from './suricata_exploit_cve_2019_13505.json'; -import rule153 from './suricata_exploit_cve_2019_15107.json'; -import rule154 from './suricata_exploit_cve_2019_15846.json'; -import rule155 from './suricata_exploit_cve_2019_16072.json'; -import rule156 from './suricata_exploit_cve_2019_1652.json'; -import rule157 from './suricata_exploit_cve_2019_16662.json'; -import rule158 from './suricata_exploit_cve_2019_16759.json'; -import rule159 from './suricata_exploit_cve_2019_16928.json'; -import rule160 from './suricata_exploit_cve_2019_17270.json'; -import rule161 from './suricata_exploit_cve_2019_1821.json'; -import rule162 from './suricata_exploit_cve_2019_19781.json'; -import rule163 from './suricata_exploit_cve_2019_2618.json'; -import rule164 from './suricata_exploit_cve_2019_2725.json'; -import rule165 from './suricata_exploit_cve_2019_3396.json'; -import rule166 from './suricata_exploit_cve_2019_3929.json'; -import rule167 from './suricata_exploit_cve_2019_5533.json'; -import rule168 from './suricata_exploit_cve_2019_6340.json'; -import rule169 from './suricata_exploit_cve_2019_7256.json'; -import rule170 from './suricata_exploit_cve_2019_9978.json'; -import rule171 from './suricata_ftp_traffic_on_unusual_port_internet_destination.json'; -import rule172 from './suricata_http_traffic_on_unusual_port_internet_destination.json'; -import rule173 from './suricata_imap_traffic_on_unusual_port_internet_destination.json'; -import rule174 from './suricata_lazagne_artifact_in_an_http_post.json'; -import rule175 from './suricata_mimikatz_artifacts_in_an_http_post.json'; -import rule176 from './suricata_mimikatz_string_detected_in_http_response.json'; -import rule177 from './suricata_nondns_traffic_on_tcp_port_53.json'; -import rule178 from './suricata_nondns_traffic_on_udp_port_53.json'; -import rule179 from './suricata_nonftp_traffic_on_port_21.json'; -import rule180 from './suricata_nonhttp_traffic_on_tcp_port_80.json'; -import rule181 from './suricata_nonimap_traffic_on_port_1443_imap.json'; -import rule182 from './suricata_nonsmb_traffic_on_tcp_port_139_smb.json'; -import rule183 from './suricata_nonssh_traffic_on_port_22.json'; -import rule184 from './suricata_nontls_on_tls_port.json'; -import rule185 from './suricata_possible_cobalt_strike_malleable_c2_null_response.json'; -import rule186 from './suricata_possible_sql_injection_sql_commands_in_http_transactions.json'; -import rule187 from './suricata_rpc_traffic_on_http_ports.json'; -import rule188 from './suricata_serialized_php_detected.json'; -import rule189 from './suricata_shell_exec_php_function_in_an_http_post.json'; -import rule190 from './suricata_ssh_traffic_not_on_port_22_internet_destination.json'; -import rule191 from './suricata_tls_traffic_on_unusual_port_internet_destination.json'; -import rule192 from './suricata_windows_executable_served_by_jpeg_web_content.json'; -import rule193 from './windows_background_intelligent_transfer_service_bits_connecting_to_the_internet.json'; -import rule194 from './windows_burp_ce_activity.json'; -import rule195 from './windows_certutil_connecting_to_the_internet.json'; -import rule196 from './windows_command_prompt_connecting_to_the_internet.json'; -import rule197 from './windows_command_shell_started_by_internet_explorer.json'; -import rule198 from './windows_command_shell_started_by_powershell.json'; -import rule199 from './windows_command_shell_started_by_svchost.json'; -import rule200 from './windows_credential_dumping_commands.json'; -import rule201 from './windows_credential_dumping_via_imageload.json'; -import rule202 from './windows_credential_dumping_via_registry_save.json'; -import rule203 from './windows_data_compression_using_powershell.json'; -import rule204 from './windows_defense_evasion_decoding_using_certutil.json'; -import rule205 from './windows_defense_evasion_or_persistence_via_hidden_files.json'; -import rule206 from './windows_defense_evasion_via_filter_manager.json'; -import rule207 from './windows_defense_evasion_via_windows_event_log_tools.json'; -import rule208 from './windows_execution_via_compiled_html_file.json'; -import rule209 from './windows_execution_via_connection_manager.json'; -import rule210 from './windows_execution_via_microsoft_html_application_hta.json'; -import rule211 from './windows_execution_via_net_com_assemblies.json'; -import rule212 from './windows_execution_via_regsvr32.json'; -import rule213 from './windows_execution_via_trusted_developer_utilities.json'; -import rule214 from './windows_html_help_executable_program_connecting_to_the_internet.json'; -import rule215 from './windows_image_load_from_a_temp_directory.json'; -import rule216 from './windows_indirect_command_execution.json'; -import rule217 from './windows_iodine_activity.json'; -import rule218 from './windows_management_instrumentation_wmi_execution.json'; -import rule219 from './windows_microsoft_html_application_hta_connecting_to_the_internet.json'; -import rule220 from './windows_mimikatz_activity.json'; -import rule221 from './windows_misc_lolbin_connecting_to_the_internet.json'; -import rule222 from './windows_net_command_activity_by_the_system_account.json'; -import rule223 from './windows_net_user_command_activity.json'; -import rule224 from './windows_netcat_activity.json'; -import rule225 from './windows_netcat_network_activity.json'; -import rule226 from './windows_network_anomalous_windows_process_using_https_ports.json'; -import rule227 from './windows_nmap_activity.json'; -import rule228 from './windows_nmap_scan_activity.json'; -import rule229 from './windows_payload_obfuscation_via_certutil.json'; -import rule230 from './windows_persistence_or_priv_escalation_via_hooking.json'; -import rule231 from './windows_persistence_via_application_shimming.json'; -import rule232 from './windows_persistence_via_bits_jobs.json'; -import rule233 from './windows_persistence_via_modification_of_existing_service.json'; -import rule234 from './windows_persistence_via_netshell_helper_dll.json'; -import rule235 from './windows_powershell_connecting_to_the_internet.json'; -import rule236 from './windows_priv_escalation_via_accessibility_features.json'; -import rule237 from './windows_process_discovery_via_tasklist_command.json'; -import rule238 from './windows_process_execution_via_wmi.json'; -import rule239 from './windows_process_started_by_acrobat_reader_possible_payload.json'; -import rule240 from './windows_process_started_by_ms_office_program_possible_payload.json'; -import rule241 from './windows_process_started_by_the_java_runtime.json'; -import rule242 from './windows_psexec_activity.json'; -import rule243 from './windows_register_server_program_connecting_to_the_internet.json'; -import rule244 from './windows_registry_query_local.json'; -import rule245 from './windows_registry_query_network.json'; -import rule246 from './windows_remote_management_execution.json'; -import rule247 from './windows_scheduled_task_activity.json'; -import rule248 from './windows_script_interpreter_connecting_to_the_internet.json'; -import rule249 from './windows_signed_binary_proxy_execution.json'; -import rule250 from './windows_signed_binary_proxy_execution_download.json'; -import rule251 from './windows_suspicious_process_started_by_a_script.json'; -import rule252 from './windows_whoami_command_activity.json'; -import rule253 from './windows_windump_activity.json'; -import rule254 from './windows_wireshark_activity.json'; -import rule255 from './zeek_notice_capturelosstoo_much_loss.json'; -import rule256 from './zeek_notice_conncontent_gap.json'; -import rule257 from './zeek_notice_connretransmission_inconsistency.json'; -import rule258 from './zeek_notice_dnsexternal_name.json'; -import rule259 from './zeek_notice_ftpbruteforcing.json'; -import rule260 from './zeek_notice_ftpsite_exec_success.json'; -import rule261 from './zeek_notice_heartbleedssl_heartbeat_attack.json'; -import rule262 from './zeek_notice_heartbleedssl_heartbeat_attack_success.json'; -import rule263 from './zeek_notice_heartbleedssl_heartbeat_many_requests.json'; -import rule264 from './zeek_notice_heartbleedssl_heartbeat_odd_length.json'; -import rule265 from './zeek_notice_httpsql_injection_attacker.json'; -import rule266 from './zeek_notice_httpsql_injection_victim.json'; -import rule267 from './zeek_notice_intelnotice.json'; -import rule268 from './zeek_notice_noticetally.json'; -import rule269 from './zeek_notice_packetfiltercannot_bpf_shunt_conn.json'; -import rule270 from './zeek_notice_packetfiltercompile_failure.json'; -import rule271 from './zeek_notice_packetfilterdropped_packets.json'; -import rule272 from './zeek_notice_packetfilterinstall_failure.json'; -import rule273 from './zeek_notice_packetfilterno_more_conn_shunts_available.json'; -import rule274 from './zeek_notice_packetfiltertoo_long_to_compile_filter.json'; -import rule275 from './zeek_notice_protocoldetectorprotocol_found.json'; -import rule276 from './zeek_notice_protocoldetectorserver_found.json'; -import rule277 from './zeek_notice_scanaddress_scan.json'; -import rule278 from './zeek_notice_scanport_scan.json'; -import rule279 from './zeek_notice_signaturescount_signature.json'; -import rule280 from './zeek_notice_signaturesmultiple_sig_responders.json'; -import rule281 from './zeek_notice_signaturesmultiple_signatures.json'; -import rule282 from './zeek_notice_signaturessensitive_signature.json'; -import rule283 from './zeek_notice_signaturessignature_summary.json'; -import rule284 from './zeek_notice_smtpblocklist_blocked_host.json'; -import rule285 from './zeek_notice_smtpblocklist_error_message.json'; -import rule286 from './zeek_notice_smtpsuspicious_origination.json'; -import rule287 from './zeek_notice_softwaresoftware_version_change.json'; -import rule288 from './zeek_notice_softwarevulnerable_version.json'; -import rule289 from './zeek_notice_sshinteresting_hostname_login.json'; -import rule290 from './zeek_notice_sshlogin_by_password_guesser.json'; -import rule291 from './zeek_notice_sshpassword_guessing.json'; -import rule292 from './zeek_notice_sshwatched_country_login.json'; -import rule293 from './zeek_notice_sslcertificate_expired.json'; -import rule294 from './zeek_notice_sslcertificate_expires_soon.json'; -import rule295 from './zeek_notice_sslcertificate_not_valid_yet.json'; -import rule296 from './zeek_notice_sslinvalid_ocsp_response.json'; -import rule297 from './zeek_notice_sslinvalid_server_cert.json'; -import rule298 from './zeek_notice_sslold_version.json'; -import rule299 from './zeek_notice_sslweak_cipher.json'; -import rule300 from './zeek_notice_sslweak_key.json'; -import rule301 from './zeek_notice_teamcymrumalwarehashregistrymatch.json'; -import rule302 from './zeek_notice_traceroutedetected.json'; -import rule303 from './zeek_notice_weirdactivity.json'; +import rule3 from './elastic_endpoint_security_adversary_behavior_detected.json'; +import rule4 from './elastic_endpoint_security_cred_dumping_detected.json'; +import rule5 from './elastic_endpoint_security_cred_dumping_prevented.json'; +import rule6 from './elastic_endpoint_security_cred_manipulation_detected.json'; +import rule7 from './elastic_endpoint_security_cred_manipulation_prevented.json'; +import rule8 from './elastic_endpoint_security_exploit_detected.json'; +import rule9 from './elastic_endpoint_security_exploit_prevented.json'; +import rule10 from './elastic_endpoint_security_malware_detected.json'; +import rule11 from './elastic_endpoint_security_malware_prevented.json'; +import rule12 from './elastic_endpoint_security_permission_theft_detected.json'; +import rule13 from './elastic_endpoint_security_permission_theft_prevented.json'; +import rule14 from './elastic_endpoint_security_process_injection_detected.json'; +import rule15 from './elastic_endpoint_security_process_injection_prevented.json'; +import rule16 from './elastic_endpoint_security_ransomware_detected.json'; +import rule17 from './elastic_endpoint_security_ransomware_prevented.json'; +import rule18 from './eql_adding_the_hidden_file_attribute_with_via_attribexe.json'; +import rule19 from './eql_adobe_hijack_persistence.json'; +import rule20 from './eql_audio_capture_via_powershell.json'; +import rule21 from './eql_audio_capture_via_soundrecorder.json'; +import rule22 from './eql_bypass_uac_event_viewer.json'; +import rule23 from './eql_bypass_uac_via_cmstp.json'; +import rule24 from './eql_bypass_uac_via_sdclt.json'; +import rule25 from './eql_clearing_windows_event_logs.json'; +import rule26 from './eql_delete_volume_usn_journal_with_fsutil.json'; +import rule27 from './eql_deleting_backup_catalogs_with_wbadmin.json'; +import rule28 from './eql_direct_outbound_smb_connection.json'; +import rule29 from './eql_disable_windows_firewall_rules_with_netsh.json'; +import rule30 from './eql_dll_search_order_hijack.json'; +import rule31 from './eql_encoding_or_decoding_files_via_certutil.json'; +import rule32 from './eql_local_scheduled_task_commands.json'; +import rule33 from './eql_local_service_commands.json'; +import rule34 from './eql_modification_of_boot_configuration.json'; +import rule35 from './eql_msbuild_making_network_connections.json'; +import rule36 from './eql_mshta_making_network_connections.json'; +import rule37 from './eql_msxsl_making_network_connections.json'; +import rule38 from './eql_psexec_lateral_movement_command.json'; +import rule39 from './eql_suspicious_ms_office_child_process.json'; +import rule40 from './eql_suspicious_ms_outlook_child_process.json'; +import rule41 from './eql_suspicious_pdf_reader_child_process.json'; +import rule42 from './eql_system_shells_via_services.json'; +import rule43 from './eql_unusual_network_connection_via_rundll32.json'; +import rule44 from './eql_unusual_parentchild_relationship.json'; +import rule45 from './eql_unusual_process_network_connection.json'; +import rule46 from './eql_user_account_creation.json'; +import rule47 from './eql_user_added_to_administrator_group.json'; +import rule48 from './eql_volume_shadow_copy_deletion_via_vssadmin.json'; +import rule49 from './eql_volume_shadow_copy_deletion_via_wmic.json'; +import rule50 from './eql_windows_script_executing_powershell.json'; +import rule51 from './eql_wmic_command_lateral_movement.json'; +import rule52 from './linux_hping_activity.json'; +import rule53 from './linux_iodine_activity.json'; +import rule54 from './linux_kernel_module_activity.json'; +import rule55 from './linux_ldso_process_activity.json'; +import rule56 from './linux_mknod_activity.json'; +import rule57 from './linux_netcat_network_connection.json'; +import rule58 from './linux_nmap_activity.json'; +import rule59 from './linux_nping_activity.json'; +import rule60 from './linux_process_started_in_temp_directory.json'; +import rule61 from './linux_shell_activity_by_web_server.json'; +import rule62 from './linux_socat_activity.json'; +import rule63 from './linux_ssh_forwarding.json'; +import rule64 from './linux_strace_activity.json'; +import rule65 from './linux_tcpdump_activity.json'; +import rule66 from './linux_whoami_commmand.json'; +import rule67 from './network_dns_directly_to_the_internet.json'; +import rule68 from './network_ftp_file_transfer_protocol_activity_to_the_internet.json'; +import rule69 from './network_irc_internet_relay_chat_protocol_activity_to_the_internet.json'; +import rule70 from './network_nat_traversal_port_activity.json'; +import rule71 from './network_port_26_activity.json'; +import rule72 from './network_port_8000_activity_to_the_internet.json'; +import rule73 from './network_pptp_point_to_point_tunneling_protocol_activity.json'; +import rule74 from './network_proxy_port_activity_to_the_internet.json'; +import rule75 from './network_rdp_remote_desktop_protocol_from_the_internet.json'; +import rule76 from './network_rdp_remote_desktop_protocol_to_the_internet.json'; +import rule77 from './network_rpc_remote_procedure_call_from_the_internet.json'; +import rule78 from './network_rpc_remote_procedure_call_to_the_internet.json'; +import rule79 from './network_smb_windows_file_sharing_activity_to_the_internet.json'; +import rule80 from './network_smtp_to_the_internet.json'; +import rule81 from './network_sql_server_port_activity_to_the_internet.json'; +import rule82 from './network_ssh_secure_shell_from_the_internet.json'; +import rule83 from './network_ssh_secure_shell_to_the_internet.json'; +import rule84 from './network_telnet_port_activity.json'; +import rule85 from './network_tor_activity_to_the_internet.json'; +import rule86 from './network_vnc_virtual_network_computing_from_the_internet.json'; +import rule87 from './network_vnc_virtual_network_computing_to_the_internet.json'; +import rule88 from './null_user_agent.json'; +import rule89 from './sqlmap_user_agent.json'; +import rule90 from './windows_background_intelligent_transfer_service_bits_connecting_to_the_internet.json'; +import rule91 from './windows_certutil_connecting_to_the_internet.json'; +import rule92 from './windows_command_prompt_connecting_to_the_internet.json'; +import rule93 from './windows_command_shell_started_by_internet_explorer.json'; +import rule94 from './windows_command_shell_started_by_powershell.json'; +import rule95 from './windows_command_shell_started_by_svchost.json'; +import rule96 from './windows_defense_evasion_via_filter_manager.json'; +import rule97 from './windows_execution_via_compiled_html_file.json'; +import rule98 from './windows_execution_via_connection_manager.json'; +import rule99 from './windows_execution_via_net_com_assemblies.json'; +import rule100 from './windows_execution_via_regsvr32.json'; +import rule101 from './windows_execution_via_trusted_developer_utilities.json'; +import rule102 from './windows_html_help_executable_program_connecting_to_the_internet.json'; +import rule103 from './windows_misc_lolbin_connecting_to_the_internet.json'; +import rule104 from './windows_net_command_activity_by_the_system_account.json'; +import rule105 from './windows_persistence_via_application_shimming.json'; +import rule106 from './windows_priv_escalation_via_accessibility_features.json'; +import rule107 from './windows_process_discovery_via_tasklist_command.json'; +import rule108 from './windows_process_execution_via_wmi.json'; +import rule109 from './windows_register_server_program_connecting_to_the_internet.json'; +import rule110 from './windows_signed_binary_proxy_execution.json'; +import rule111 from './windows_signed_binary_proxy_execution_download.json'; +import rule112 from './windows_suspicious_process_started_by_a_script.json'; +import rule113 from './windows_whoami_command_activity.json'; export const rawRules = [ rule1, rule2, @@ -424,194 +234,4 @@ export const rawRules = [ rule111, rule112, rule113, - rule114, - rule115, - rule116, - rule117, - rule118, - rule119, - rule120, - rule121, - rule122, - rule123, - rule124, - rule125, - rule126, - rule127, - rule128, - rule129, - rule130, - rule131, - rule132, - rule133, - rule134, - rule135, - rule136, - rule137, - rule138, - rule139, - rule140, - rule141, - rule142, - rule143, - rule144, - rule145, - rule146, - rule147, - rule148, - rule149, - rule150, - rule151, - rule152, - rule153, - rule154, - rule155, - rule156, - rule157, - rule158, - rule159, - rule160, - rule161, - rule162, - rule163, - rule164, - rule165, - rule166, - rule167, - rule168, - rule169, - rule170, - rule171, - rule172, - rule173, - rule174, - rule175, - rule176, - rule177, - rule178, - rule179, - rule180, - rule181, - rule182, - rule183, - rule184, - rule185, - rule186, - rule187, - rule188, - rule189, - rule190, - rule191, - rule192, - rule193, - rule194, - rule195, - rule196, - rule197, - rule198, - rule199, - rule200, - rule201, - rule202, - rule203, - rule204, - rule205, - rule206, - rule207, - rule208, - rule209, - rule210, - rule211, - rule212, - rule213, - rule214, - rule215, - rule216, - rule217, - rule218, - rule219, - rule220, - rule221, - rule222, - rule223, - rule224, - rule225, - rule226, - rule227, - rule228, - rule229, - rule230, - rule231, - rule232, - rule233, - rule234, - rule235, - rule236, - rule237, - rule238, - rule239, - rule240, - rule241, - rule242, - rule243, - rule244, - rule245, - rule246, - rule247, - rule248, - rule249, - rule250, - rule251, - rule252, - rule253, - rule254, - rule255, - rule256, - rule257, - rule258, - rule259, - rule260, - rule261, - rule262, - rule263, - rule264, - rule265, - rule266, - rule267, - rule268, - rule269, - rule270, - rule271, - rule272, - rule273, - rule274, - rule275, - rule276, - rule277, - rule278, - rule279, - rule280, - rule281, - rule282, - rule283, - rule284, - rule285, - rule286, - rule287, - rule288, - rule289, - rule290, - rule291, - rule292, - rule293, - rule294, - rule295, - rule296, - rule297, - rule298, - rule299, - rule300, - rule301, - rule302, - rule303, ]; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json index b42e4130b688cf..517e16fb3d284b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json @@ -1,16 +1,25 @@ { - "description": "Linux: Hping Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Hping ran on a Linux host. Hping is FOSS command-line packet analyzer and has the ability to construct network packets for a wide variety of network security testing applications including scanning and firewall auditing.", + "false_positives": [ + "Normal use of hping is uncommon apart from security testing and research. Use by non-security engineers is very uncommon." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Hping Activity", + "max_signals": 33, + "name": "Hping Process Activity", "query": "process.name: hping and event.action:executed", - "risk_score": 50, + "references": [ + "https://en.wikipedia.org/wiki/Hping" + ], + "risk_score": 73, "rule_id": "90169566-2260-4824-b8e4-8615c3b4ed52", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json index 1eb66c39571d75..49f18ef9871a17 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json @@ -1,16 +1,25 @@ { - "description": "Linux: Iodine Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Iodine is a tool for tunneling Internet protocol version 4 (IPV4) traffic over the DNS protocol in order to circumvent firewalls, network security groups or network access lists while evading detection.", + "false_positives": [ + "Normal use of Iodine is uncommon apart from security testing and research. Use by non-security engineers is very uncommon." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Iodine Activity", + "max_signals": 33, + "name": "Potential DNS Tunneling via Iodine", "query": "process.name: (iodine or iodined) and event.action:executed", - "risk_score": 50, + "references": [ + "https://code.kryo.se/iodine/" + ], + "risk_score": 73, "rule_id": "041d4d41-9589-43e2-ba13-5680af75ebc2", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json index 90864f1ab8ab9f..8c94694ca4d040 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json @@ -1,16 +1,42 @@ { - "description": "Linux: Kernel Module Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies loadable kernel module errors, often indicative of potential persistence attempts.", + "false_positives": [ + "Security tools and device drivers may run these programs in order to load legitimate kernel modules. Use of these programs by ordinary users is uncommon." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Kernel Module Activity", + "max_signals": 33, + "name": "Persistence via Kernel Module Modification", "query": "process.name: (insmod or kmod or modprobe or rmod) and event.action:executed", - "risk_score": 50, + "references": [ + "https://www.hackers-arise.com/single-post/2017/11/03/Linux-for-Hackers-Part-10-Loadable-Kernel-Modules-LKM" + ], + "risk_score": 21, "rule_id": "81cc58f5-8062-49a2-ba84-5cc4b4d31c40", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/techniques/TA0003/" + }, + "technique": [ + { + "id": "T1215", + "name": "Kernel Modules and Extensions", + "reference": "https://attack.mitre.org/techniques/T1215/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ldso_process_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ldso_process_activity.json index 174e246fa70d98..82a2a16080160f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ldso_process_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ldso_process_activity.json @@ -1,17 +1,22 @@ { - "description": "Linux ld.so process activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "The dynamic linker, ld.so, runs in a privileged context and can be used to escape restrictive environments by spawning a shell in order to elevate privileges or move laterally.", + "false_positives": [ + "ld.so is a dual-use tool that can be used for benign or malicious activity. Some normal use of this command may originate from developers or administrators. Use of ld.so by non-engineers or ordinary users is uncommon." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux ld.so process activity", + "max_signals": 33, + "name": "Ld.so Process Activity", "query": "process.name:ld.so and event.action:executed", - "risk_score": 50, + "risk_score": 21, "rule_id": "3f31a31c-f7cf-4268-a0df-ec1a98099e7f", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_lzop_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_lzop_activity.json deleted file mode 100644 index 77953240c21859..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_lzop_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Linux lzop activity - possible @JulianRunnels", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Linux lzop activity", - "query": "process.name:lzop and event.action:executed", - "risk_score": 50, - "rule_id": "d7359214-54a4-4572-9e51-ebf79cda9b04", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json index 08940115207413..8f4e1f40fad122 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json @@ -1,16 +1,25 @@ { - "description": "Linux: Mknod Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "The Linux mknod program is sometimes used in the command payload of remote command injection (RCI) and other exploits to export a command shell when the traditional version of netcat is not available to the payload.", + "false_positives": [ + "Mknod is a Linux system program. Some normal use of this program, at varying levels of frequency, may originate from scripts, automation tools and frameworks. Usage by web servers is more likely to be suspicious." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Mknod Activity", + "max_signals": 33, + "name": "Mknod Process Activity", "query": "process.name: mknod and event.action:executed", - "risk_score": 50, + "references": [ + "https://pen-testing.sans.org/blog/2013/05/06/netcat-without-e-no-problem" + ], + "risk_score": 21, "rule_id": "61c31c14-507f-4627-8c31-072556b89a9c", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json index d324a4f64cbbad..b06a342d249774 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json @@ -1,16 +1,27 @@ { - "description": "Linux: Netcat Network Connection", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "A netcat process is engaging in network activity on a Linux host. Netcat is often used as a persistence mechanism by exporting a reverse shell or by serving a shell on a listening port. Netcat is also sometimes used for data exfiltration. ", + "false_positives": [ + "Netcat is a dual-use tool that can be used for benign or malicious activity. Netcat is included in some Linux distributions so its presence is not necessarily suspicious. Some normal use of this program, while uncommon, may originate from scripts, automation tools and frameworks." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Netcat Network Activity", + "max_signals": 33, + "name": "Netcat Network Activity", "query": "process.name: (nc or ncat or netcat or netcat.openbsd or netcat.traditional) and event.action: (connected-to or bound-socket or socket_opened)", - "risk_score": 50, + "references": [ + "http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet", + "https://www.sans.org/security-resources/sec560/netcat_cheat_sheet_v1.pdf", + "https://en.wikipedia.org/wiki/Netcat" + ], + "risk_score": 47, "rule_id": "adb961e0-cb74-42a0-af9e-29fc41f88f5f", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_network_anomalous_process_using_https_ports.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_network_anomalous_process_using_https_ports.json deleted file mode 100644 index d04f6610f450d4..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_network_anomalous_process_using_https_ports.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Linux Network - Anomalous Process Using HTTP/S Ports", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Linux Network - Anomalous Process Using HTTP/S Ports", - "query": "(destination.port:443 or destination.port:80) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16 and not process.name:curl and not process.name:http and not process.name:https and not process.name:nginx and not process.name:packetbeat and not process.name:python2 and not process.name:snapd and not process.name:wget", - "risk_score": 50, - "rule_id": "be40c674-1799-4a00-934d-0b2d54495913", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json index cb89fdc6ebbff5..406cd8e026e7a2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json @@ -1,16 +1,25 @@ { - "description": "Linux: Nmap Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Nmap was executed on a Linux host. Nmap is a FOSS tool for network scanning and security testing. It can map and discover networks, identify listening services and operating systems. It is sometimes used to gather information in support of exploitation, execution or lateral movement.", + "false_positives": [ + "Security testing tools and frameworks may run nmap in the course of security auditing. Some normal use of this command may originate from security engineers and network or server administrators. Use of nmap by ordinary users is uncommon." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Nmap Activity", + "max_signals": 33, + "name": "Nmap Process Activity", "query": "process.name: nmap", - "risk_score": 50, + "references": [ + "https://en.wikipedia.org/wiki/Nmap" + ], + "risk_score": 21, "rule_id": "c87fca17-b3a9-4e83-b545-f30746c53920", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json index b5508c388059cc..de53e05e70fa39 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json @@ -1,16 +1,25 @@ { - "description": "Linux: Nping Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Nping ran on a Linux host. Nping is part of the Nmap tool suite and has the ability to construct raw packets for a wide variety of security testing applications including denial of service testing.", + "false_positives": [ + "Some normal use of this command may originate from security engineers and network or server administrators but this is usually not routine or unannounced. Use of nping by non-engineers or ordinary users is uncommon." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Nping Activity", + "max_signals": 33, + "name": "Nping Process Activity", "query": "process.name: nping and event.action:executed", - "risk_score": 50, + "references": [ + "https://en.wikipedia.org/wiki/Nmap" + ], + "risk_score": 47, "rule_id": "0d69150b-96f8-467c-a86d-a67a3378ce77", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json index d9d409feae4735..4ed021a4c864df 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json @@ -1,16 +1,22 @@ { - "description": "Linux: Process Started in Temp Directory", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies processes running in a temporary folder. This is sometimes done by adversaries to hide malware.", + "false_positives": [ + "Build systems like Jenkins may start processes in the /tmp directory. These can be exempted by name or by username." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Process Started in Temp Directory", + "max_signals": 33, + "name": "Unusual Process Execution - Temp", "query": "process.working_directory: /tmp and event.action:executed", - "risk_score": 50, + "risk_score": 47, "rule_id": "df959768-b0c9-4d45-988c-5606a2be8e5a", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ptrace_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ptrace_activity.json deleted file mode 100644 index 47ae28cf8ea4c0..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ptrace_activity.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Linux: Ptrace Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Linux: Ptrace Activity", - "query": "process.name: ptrace and event.action:executed", - "risk_score": 50, - "rule_id": "1bff9259-e160-4920-bf72-4c96b6dbb7af", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_rawshark_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_rawshark_activity.json deleted file mode 100644 index d4924cab7048fc..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_rawshark_activity.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Linux: Rawshark Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Linux: Rawshark Activity", - "query": "process.name: rawshark and event.action:executed", - "risk_score": 50, - "rule_id": "30eb2b9d-b53b-4ba5-bfab-7119a8b84029", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json index d533f5d4ec3f64..c7d856cbe61f35 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json @@ -1,17 +1,42 @@ { - "description": "Linux: Shell Activity By Web Server", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies suspicious commands executed via a web server, which may suggest a vulnerability and remote shell access.", + "false_positives": [ + "Network monitoring or management products may have a web server component that runs shell commands as part of normal behavior." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Shell Activity By Web Server", + "max_signals": 33, + "name": "Potential Shell via Web Server", "query": "process.name: bash and (user.name: apache or www) and event.action:executed", - "risk_score": 50, + "references": [ + "https://pentestlab.blog/tag/web-shell/" + ], + "risk_score": 47, "rule_id": "231876e7-4d1f-4d63-a47c-47dd1acdc1cb", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/techniques/TA0003/" + }, + "technique": [ + { + "id": "T1100", + "name": "Web Shell", + "reference": "https://attack.mitre.org/techniques/T1215/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json index 2ea860e0619587..481a99518d4ed3 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json @@ -1,16 +1,25 @@ { - "description": "Linux: socat activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "A Socat process is running on a Linux host. Socat is often used as a persistence mechanism by exporting a reverse shell or by serving a shell on a listening port. Socat is also sometimes used for lateral movement. ", + "false_positives": [ + "Socat is a dual-use tool that can be used for benign or malicious activity. Some normal use of this program, at varying levels of frequency, may originate from scripts, automation tools and frameworks. Usage by web servers is more likely to be suspicious." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Whoami Commmand", + "max_signals": 33, + "name": "Socat Process Activity", "query": "process.name:socat and not process.args:\"-V\" and event.action:executed", - "risk_score": 50, + "references": [ + "https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys/#method-2-using-socat" + ], + "risk_score": 47, "rule_id": "cd4d5754-07e1-41d4-b9a5-ef4ea6a0a126", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ssh_forwarding.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ssh_forwarding.json index 38562320921b4d..3b61814ab66fd7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ssh_forwarding.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_ssh_forwarding.json @@ -1,19 +1,43 @@ { - "description": "Detect ssh processes with the `-R` flag which can be used to forward a port on a local system to the local system so that someone on the remote system can connect to the local system. This is often used by attackers to create encrypted tunnels through firewalls for pivoting and persistence.", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "An SSH processes ran with the `-R` flag which can be used to forward a port to a remote destination for purposes of pivoting and persistence. This technique often used to create encrypted tunnels and circumvent firewalls, security groups or network access lists.", + "false_positives": [ + "Some normal use of this command may originate from usage by engineers as an alternative or ad-hoc remote access solution. Use of this command by non-administrative users is uncommon." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: SSH Port Forwarding", + "max_signals": 33, + "name": "Potential Lateral Movement via SSH Port Forwarding", "query": "process.name:ssh and process.args:\"-R\" and event.action:executed", "references": [ - " - https://www.ssh.com/ssh/tunneling,https://www.ssh.com/ssh/tunneling/example,https://attack.mitre.org/techniques/T1184/" + "https://www.ssh.com/ssh/tunneling", + "https://www.ssh.com/ssh/tunneling/example" ], - "risk_score": 50, + "risk_score": 47, "rule_id": "45d256ab-e665-445b-8306-2f83a8db59f8", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1184", + "name": "SSH Hijacking", + "reference": "https://attack.mitre.org/techniques/T1184/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json index dc0eae38d20c65..6f8bc112fd0114 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json @@ -1,16 +1,25 @@ { - "description": "Linux: Strace Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Strace runs in a privileged context and can be used to escape restrictive environments by instantiating a shell in order to elevate privlieges or move laterally.", + "false_positives": [ + "Strace is a dual-use tool that can be used for benign or malicious activity. Some normal use of this command may originate from developers or SREs engaged in debugging or system call tracing." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Strace Activity", + "max_signals": 33, + "name": "Strace Process Activity", "query": "process.name: strace and event.action:executed", - "risk_score": 50, + "references": [ + "https://en.wikipedia.org/wiki/Strace" + ], + "risk_score": 21, "rule_id": "d6450d4e-81c6-46a3-bd94-079886318ed5", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Linux" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json index f7b543fef75f5e..b6dc7f1689770c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json @@ -1,16 +1,54 @@ { - "description": "Linux: Tcpdump Activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "The Tcpdump program ran on a Linux host. Tcpdump is a network monitoring or packet 'sniffing' tool that can be used to capture insecure credentials or data in motion. Sniffing can also be used to discover details of network services as a prelude to lateral movement or defense evasion.", + "false_positives": [ + "Some normal use of this command may originate from server or network administrators engaged in network troubleshooting." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Tcpdump Activity", + "max_signals": 33, + "name": "Network Sniffing via Tcpdump", "query": "process.name: tcpdump and event.action:executed", - "risk_score": 50, + "risk_score": 21, "rule_id": "7a137d76-ce3d-48e2-947d-2747796a78c0", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1040", + "name": "Network Sniffing", + "reference": "https://attack.mitre.org/techniques/T1040/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0007", + "name": "Discovery", + "reference": "https://attack.mitre.org/tactics/TA0007/" + }, + "technique": [ + { + "id": "T1040", + "name": "Network Sniffing", + "reference": "https://attack.mitre.org/techniques/T1040/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_web_download.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_web_download.json deleted file mode 100644 index 876a3fef7aa091..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_web_download.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Linux: Web Download", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Linux: Web Download", - "query": "process.name: (curl or wget) and event.action:executed", - "risk_score": 50, - "rule_id": "e8ec93a6-49d2-4467-8c12-81c435fcc519", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json index 56a2782eb0cca0..91c6d2bcc9f954 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json @@ -1,16 +1,39 @@ { - "description": "Linux: Whoami Commmand", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "The whoami application was executed on a Linux host. This is often used by tools and persistence mechanisms to test for privileged access.", + "false_positives": [ + "Security testing tools and frameworks may run this command. Some normal use of this command may originate from automation tools and frameworks." + ], + "index": [ + "auditbeat-*" + ], "language": "kuery", - "name": "Linux: Whoami Commmand", + "max_signals": 33, + "name": "User Discovery via Whoami", "query": "process.name: whoami and event.action:executed", - "risk_score": 50, + "risk_score": 21, "rule_id": "120559c6-5e24-49f4-9e30-8ffe697df6b9", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0007", + "name": "Discovery", + "reference": "https://attack.mitre.org/tactics/TA0007/" + }, + "technique": [ + { + "id": "T1033", + "name": "System Owner/User Discovery", + "reference": "https://attack.mitre.org/techniques/T1033/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_dns_directly_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_dns_directly_to_the_internet.json index 1a3c3c003b532c..3d1b07a267eca1 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_dns_directly_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_dns_directly_to_the_internet.json @@ -1,17 +1,46 @@ { - "description": "Network - DNS Directly to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects internal network client sending DNS traffic directly to the Internet.\nThis is atypical behavior for a managed network and can be indicative of malware,\nexfiltration, command and control or simply misconfiguration. This also impacts your\norganization's ability to provide enterprise monitoring and logging of DNS and opens\nyour network to a variety of abuses or malicious communications.\n", + "false_positives": [ + "DNS servers should be excluded from this rule as this is expected behavior for them. Endpoints usually query local DNS servers defined in their DHCP scopes but this may be overridden if a user configures their endpoint to use a remote DNS server. This is uncommon in managed enterprise networks because it would tend to break intra-net name resolution when split horizon DNS is utilized. Some consumer VPN services and browser plug-ins may send DNS traffic to remote Internet destinations; in that case, such devices or networks can be excluded from this rule if this is expected behavior." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - DNS Directly to the Internet\t", - "query": "destination.port:53 and not destination.ip: 169.254.169.254/32 and not destination.ip:127.0.0.53/32 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "DNS Activity to the Internet", + "query": "destination.port:53 and (\n network.direction: outbound or (\n source.ip:(10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip:( 169.254.169.254/32 or 127.0.0.53/32 or 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 or 224.0.0.251 or ff02\\:\\:fb or 255.255.255.255 )\n )\n)\n", + "references": [ + "https://www.us-cert.gov/ncas/alerts/TA15-240A", + "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-81-2.pdf" + ], + "risk_score": 47, "rule_id": "6ea71ff0-9e95-475b-9506-2580d1ce6154", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ftp_file_transfer_protocol_activity_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ftp_file_transfer_protocol_activity_to_the_internet.json index 99a126f0613ec0..ef7b39412c808c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ftp_file_transfer_protocol_activity_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ftp_file_transfer_protocol_activity_to_the_internet.json @@ -1,17 +1,57 @@ { - "description": "Network - FTP (File Transfer Protocol) Activity to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects events that may indicate the use of FTP network connections to the Internet.\nThe File Transfer Protocol (FTP) has been around in its current form since the\n1980's. It can be an efficient and normal procedure on your network to send and\nreceive files. Because it is common and efficient, adversaries will also often\nuse this protocol to ex-filtrate data from your network or download new tools.\nAdditionally, FTP is a plain-text protocol which may expose your user name and\npassword, if intercepted. FTP activity involving servers subject to regulations or compliance standards may be unauthorized.\n", + "false_positives": [ + "FTP servers should be excluded from this rule as this is expected behavior for them. Some business work-flows may use FTP for data exchange. These work-flows often have expected characteristics such as users, sources and destinations. FTP activity involving an unusual source or destination may be more suspicious. FTP activity involving a production server that has no known associated FTP work-flow or business requirement is often suspicious. NEW NEW" + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - FTP (File Transfer Protocol) Activity to the Internet\t", - "query": "(destination.port:20 or destination.port:21) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "FTP (File Transfer Protocol) Activity to the Internet", + "query": "network.transport: tcp and destination.port: (20 or 21) and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 21, "rule_id": "87ec6396-9ac4-4706-bcf0-2ebb22002f43", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0010", + "name": "Exfiltration", + "reference": "https://attack.mitre.org/tactics/TA0010/" + }, + "technique": [ + { + "id": "T1048", + "name": "Exfiltration Over Alternative Protocol", + "reference": "https://attack.mitre.org/techniques/T1048/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_irc_internet_relay_chat_protocol_activity_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_irc_internet_relay_chat_protocol_activity_to_the_internet.json index 79814eb552d5ba..2700eae9774820 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_irc_internet_relay_chat_protocol_activity_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_irc_internet_relay_chat_protocol_activity_to_the_internet.json @@ -1,17 +1,57 @@ { - "description": "Network - IRC (Internet Relay Chat) Protocol Activity to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects events that use common ports for IRC to the Internet. IRC (Internet Relay Chat)\nis a common protocol that can be used chat and file transfer. This protocol\nalso makes a good candidate for remote control of malware and data transfer in\nand out of a network.\n", + "false_positives": [ + "IRC activity may be normal behavior for developers and engineers but is unusual for non-engineering end users. IRC activity involving an unusual source or destination may be more suspicious. IRC activity involving a production server is often suspicious. Because these ports are in the ephemeral range, this rule may false under certain conditions such as when a NATted web server replies to a client which has used a port in the range by coincidence. In this case, such servers can be excluded if desired. Some legacy applications may use these ports but this is very uncommon and usually appears only in local traffic using private IPs which this rule does not match." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - IRC (Internet Relay Chat) Protocol Activity to the Internet\t", - "query": "(destination.port:20 or destination.port:21) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "IRC (Internet Relay Chat) Protocol Activity to the Internet", + "query": "network.transport: tcp and destination.port:(6667 or 6697) and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 47, "rule_id": "c6474c34-4953-447a-903e-9fcb7b6661aa", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0010", + "name": "Exfiltration", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1048", + "name": "Exfiltration Over Alternative Protocol", + "reference": "https://attack.mitre.org/techniques/T1048/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_nat_traversal_port_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_nat_traversal_port_activity.json index d370773e3879f8..e87e296017a36e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_nat_traversal_port_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_nat_traversal_port_activity.json @@ -1,17 +1,42 @@ { - "description": "Network - NAT Traversal Port Activity\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects events that could be describing IPSEC NAT Traversal traffic.\nIPSEC is a VPN technology that allows one system to talk to another using\nencrypted tunnels. NAT Traversal enables these tunnels to communicate over\nthe Internet where one of the sides is behind a NAT router gateway. This may\nbe common on your network, but this technique is also used by threat actors\nto avoid detection.\n", + "false_positives": [ + "Some networks may utilize these protocols but usage that is unfamiliar to local network administrators can be unexpected and suspicious. Because this port is in the ephemeral range, this rule may false under certain conditions such as when a application server with a public IP address replies to a client which has used a UDP port in the range by coincidence. This is uncommon but such servers can be excluded if desired." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - NAT Traversal Port Activity\t", - "query": "destination.port:4500", - "risk_score": 50, + "name": "IPSEC NAT Traversal Port Activity", + "query": "network.transport: udp and destination.port: 4500", + "risk_score": 21, "rule_id": "a9cb3641-ff4b-4cdc-a063-b4b8d02a67c7", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_26_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_26_activity.json index cfdb5e6584ee37..59db16c7b7d3dd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_26_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_26_activity.json @@ -1,17 +1,61 @@ { - "description": "Network - Port 26 Activity\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects events that may indicate use of SMTP on TCP port 26. This\nport is commonly used by several popular mail transfer agents to deconflict\nwith the default SMTP port 25. This port has also been used by a malware family\ncalled BadPatch for command and control of Windows systems.\n", + "false_positives": [ + "Servers that process email traffic may cause false positives and should be excluded from this rule as this is expected behavior for them." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - Port 26 Activity\t", - "query": "destination.port:26", - "risk_score": 50, + "name": "SMTP on Port 26/TCP", + "query": "network.transport: tcp and destination.port: 26", + "references": [ + "https://unit42.paloaltonetworks.com/unit42-badpatch/", + "https://isc.sans.edu/forums/diary/Next+up+whats+up+with+TCP+port+26/25564/" + ], + "risk_score": 21, "rule_id": "d7e62693-aab9-4f66-a21a-3d79ecdd603d", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0010", + "name": "Exfiltration", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Exfiltration Over Alternative Protocol", + "reference": "https://attack.mitre.org/techniques/T1048/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity.json deleted file mode 100644 index 218109b73221d6..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Network - Port 8000 Activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Network - Port 8000 Activity", - "query": "destination.port:8000", - "risk_score": 50, - "rule_id": "9c5f8092-e3f7-4eda-b9d3-56eed28fb157", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity_to_the_internet.json index 5eeda8e094bb97..2b3d08a7c80d98 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity_to_the_internet.json @@ -1,17 +1,42 @@ { - "description": "Network - Port 8000 Activity to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "TCP Port 8000 is commonly used for development environments of web server\nsoftware. It generally should not be exposed directly to the Internet. If you are\nrunning software like this on the Internet, you should consider placing it behind\na reverse proxy.\n", + "false_positives": [ + "Because this port is in the ephemeral range, this rule may false under certain conditions such as when a NATed web server replies to a client which has used a port in the range by coincidence. In this case, such servers can be excluded if desired. Some applications may use this port but this is very uncommon and usually appears in local traffic using private IPs which this rule does not match. Some cloud environments, particularly development environments, may use this port when VPNs or direct connects are not in use and cloud instances are accessed across the Internet." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - Port 8000 Activity to the Internet\t", - "query": "destination.port:8000 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "TCP Port 8000 Activity to the Internet", + "query": "network.transport: tcp and destination.port: 8000 and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 21, "rule_id": "08d5d7e2-740f-44d8-aeda-e41f4263efaf", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_pptp_point_to_point_tunneling_protocol_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_pptp_point_to_point_tunneling_protocol_activity.json index 7b83966e18e704..b008ca2c2bee6c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_pptp_point_to_point_tunneling_protocol_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_pptp_point_to_point_tunneling_protocol_activity.json @@ -1,17 +1,42 @@ { - "description": "Network - PPTP (Point to Point Tunneling Protocol) Activity\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects events that may indicate use of a PPTP VPN connection. Some threat actors use these types of connections to tunnel their traffic while avoiding detection.", + "false_positives": [ + "Some networks may utilize PPTP protocols but this is uncommon as more modern VPN technologies are available. Usage that is unfamiliar to local network administrators can be unexpected and suspicious. Torrenting applications may use this port. Because this port is in the ephemeral range, this rule may false under certain conditions such as when an application server with replies to a client which has used this port by coincidence. This is uncommon but such servers can be excluded if desired." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - PPTP (Point to Point Tunneling Protocol) Activity\t", - "query": "destination.port:1723", - "risk_score": 50, + "name": "PPTP (Point to Point Tunneling Protocol) Activity", + "query": "network.transport: tcp and destination.port: 1723", + "risk_score": 21, "rule_id": "d2053495-8fe7-4168-b3df-dad844046be3", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_proxy_port_activity_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_proxy_port_activity_to_the_internet.json index 3a55db40504592..f7c6ffddcaf9ee 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_proxy_port_activity_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_proxy_port_activity_to_the_internet.json @@ -1,17 +1,42 @@ { - "description": "Network - Proxy Port Activity to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects events that may describe network events of proxy use to the\nInternet. It includes popular HTTP proxy ports and SOCKS proxy ports. Typically\nenvironments will use an internal IP address for a proxy server. It can also\nbe used to circumvent network controls and detection mechanisms.\n", + "false_positives": [ + "Some proxied applications may use these ports but this usually occurs in local traffic using private IPs which this rule does not match. Proxies are widely used as a security technology but in enterprise environments this is usually local traffic which this rule does not match. Internet proxy services using these ports can be white-listed if desired. Some screen recording applications may use these ports. Proxy port activity involving an unusual source or destination may be more suspicious. Some cloud environments may use this port when VPNs or direct connects are not in use and cloud instances are accessed across the Internet. Because these ports are in the ephemeral range, this rule may false under certain conditions such as when a NATed web server replies to a client which has used a port in the range by coincidence. In this case, such servers can be excluded if desired." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - Proxy Port Activity to the Internet\t", - "query": "(destination.port:8080 or destination.port:3128) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "Proxy Port Activity to the Internet", + "query": "network.transport: tcp and destination.port: (3128 or 8080 or 1080) and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 47, "rule_id": "ad0e5e75-dd89-4875-8d0a-dfdc1828b5f3", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_from_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_from_the_internet.json index e5c1e33470fa47..76528da19a57c3 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_from_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_from_the_internet.json @@ -1,17 +1,72 @@ { - "description": "Network - RDP (Remote Desktop Protocol) from the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of RDP traffic\nfrom the Internet. RDP is commonly used by system administrators to remotely\ncontrol a system for maintenance or to use shared resources. It should almost\nnever be directly exposed to the Internet, as it is frequently targeted and\nexploited by threat actors as an initial access or back-door vector.\n", + "false_positives": [ + "Some network security policies allow RDP directly from the Internet but usage that is unfamiliar to server or network owners can be unexpected and suspicious. RDP services may be exposed directly to the Internet in some networks such as cloud environments. In such cases, only RDP gateways, bastions or jump servers may be expected expose RDP directly to the Internet and can be exempted from this rule. RDP may be required by some work-flows such as remote access and support for specialized software products and servers. Such work-flows are usually known and not unexpected." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - RDP (Remote Desktop Protocol) from the Internet\t", - "query": "(destination.port:8080 or destination.port:3128) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "RDP (Remote Desktop Protocol) from the Internet", + "query": "network.transport: tcp and destination.port: 3389 and (\n network.direction: inbound or (\n not source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n and destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 47, "rule_id": "8c1bdde8-4204-45c0-9e0c-c85ca3902488", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1190", + "name": "Remote Services", + "reference": "https://attack.mitre.org/techniques/T1021/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0001", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0001/" + }, + "technique": [ + { + "id": "T1190", + "name": "Exploit Public-Facing Application", + "reference": "https://attack.mitre.org/techniques/T1190/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_to_the_internet.json index 92316f2bb05daf..55b9716af9346d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_to_the_internet.json @@ -1,17 +1,57 @@ { - "description": "Network - RDP (Remote Desktop Protocol) to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of RDP traffic\nto the Internet. RDP is commonly used by system administrators to remotely\ncontrol a system for maintenance or to use shared resources. It should almost\nnever be directly exposed to the Internet, as it is frequently targeted and\nexploited by threat actors as an initial access or back-door vector.\n", + "false_positives": [ + "RDP connections may be made directly to Internet destinations in order to access Windows cloud server instances but such connections are usually made only by engineers. In such cases, only RDP gateways, bastions or jump servers may be expected Internet destinations and can be exempted from this rule. RDP may be required by some work-flows such as remote access and support for specialized software products and servers. Such work-flows are usually known and not unexpected. Usage that is unfamiliar to server or network owners can be unexpected and suspicious." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - RDP (Remote Desktop Protocol) to the Internet\t", - "query": "destination.port:3389 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "RDP (Remote Desktop Protocol) to the Internet", + "query": "network.transport: tcp and destination.port: 3389 and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 21, "rule_id": "e56993d2-759c-4120-984c-9ec9bb940fd5", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Exploit Public-Facing Application", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0010", + "name": "Exfiltration", + "reference": "https://attack.mitre.org/tactics/TA0010/" + }, + "technique": [ + { + "id": "T1048", + "name": "Exfiltration Over Alternative Protocol", + "reference": "https://attack.mitre.org/techniques/T1048/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_from_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_from_the_internet.json index 69d6d18ced8b9d..ca6715ac487859 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_from_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_from_the_internet.json @@ -1,17 +1,39 @@ { - "description": "Network - RPC (Remote Procedure Call) from the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of RPC traffic\nfrom the Internet. RPC is commonly used by system administrators to remotely\ncontrol a system for maintenance or to use shared resources. It should almost\nnever be directly exposed to the Internet, as it is frequently targeted and\nexploited by threat actors as an initial access or back-door vector.\n", + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - RPC (Remote Procedure Call) from the Internet\t", - "query": "destination.port:3389 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "RPC (Remote Procedure Call) from the Internet", + "query": "network.transport: tcp and destination.port: 135 and (\n network.direction: inbound or (\n not source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 73, "rule_id": "143cb236-0956-4f42-a706-814bcaa0cf5a", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1190", + "name": "Exploit Public-Facing Application", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_to_the_internet.json index 1f9a71bab92442..91db97dabdd46f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_to_the_internet.json @@ -1,17 +1,39 @@ { - "description": "Network - RPC (Remote Procedure Call) to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of RPC traffic\nto the Internet. RPC is commonly used by system administrators to remotely\ncontrol a system for maintenance or to use shared resources. It should almost\nnever be directly exposed to the Internet, as it is frequently targeted and\nexploited by threat actors as an initial access or back-door vector.\n", + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - RPC (Remote Procedure Call) to the Internet\t", - "query": "destination.port:135 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "RPC (Remote Procedure Call) to the Internet", + "query": "network.transport: tcp and destination.port: 135 and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 73, "rule_id": "32923416-763a-4531-bb35-f33b9232ecdb", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1190", + "name": "Exploit Public-Facing Application", + "reference": "https://attack.mitre.org/techniques/T1190/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smb_windows_file_sharing_activity_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smb_windows_file_sharing_activity_to_the_internet.json index 627a89609cc21f..ee47dff73db40f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smb_windows_file_sharing_activity_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smb_windows_file_sharing_activity_to_the_internet.json @@ -1,17 +1,54 @@ { - "description": "Network - SMB (Windows File Sharing) Activity to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of Windows\nfile sharing (also called SMB or CIFS) traffic to the Internet. SMB is commonly\nused within networks to share files, printers, and other system resources amongst\ntrusted systems. It should almost never be directly exposed to the Internet, as\nit is frequently targeted and exploited by threat actors as an initial access\nor back-door vector or for data exfiltration.\n", + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - SMB (Windows File Sharing) Activity to the Internet\t", - "query": "(destination.port:139 or destination.port:445) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "SMB (Windows File Sharing) Activity to the Internet", + "query": "network.transport: tcp and destination.port: (139 or 445) and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 73, "rule_id": "c82b2bd8-d701-420c-ba43-f11a155b681a", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1190", + "name": "Exploit Public-Facing Application", + "reference": "https://attack.mitre.org/techniques/T1190/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0010", + "name": "Exfiltration", + "reference": "https://attack.mitre.org/tactics/TA0010/" + }, + "technique": [ + { + "id": "T1043", + "name": "Exfiltration Over Alternative Protocol", + "reference": "https://attack.mitre.org/techniques/T1048/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smtp_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smtp_to_the_internet.json index ff5a61cbe00e67..68daf71d9992a4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smtp_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smtp_to_the_internet.json @@ -1,17 +1,57 @@ { - "description": "Network - SMTP to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects events that may describe SMTP traffic from internal\nhosts to a host across the Internet. In an enterprise network, there is typically\na dedicate host that is internal that could perform this function. It is also\nfrequently abused by threat actors for command and control or data exfiltration.\n", + "false_positives": [ + "NATed servers that process email traffic may false and should be excluded from this rule as this is expected behavior for them. Consumer and / or personal devices may send email traffic to remote Internet destinations; in that case, such devices or networks can be excluded from this rule if this is expected behavior." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - SMTP to the Internet\t", - "query": "destination.port:25 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "SMTP to the Internet", + "query": "network.transport: tcp and destination.port: (25 or 465 or 587) and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 21, "rule_id": "67a9beba-830d-4035-bfe8-40b7e28f8ac4", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0010", + "name": "Exfiltration", + "reference": "https://attack.mitre.org/tactics/TA0010/" + }, + "technique": [ + { + "id": "T1048", + "name": "Exfiltration Over Alternative Protocol", + "reference": "https://attack.mitre.org/techniques/T1048/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_sql_server_port_activity_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_sql_server_port_activity_to_the_internet.json index eeeb93e12938f0..df779d47246a5d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_sql_server_port_activity_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_sql_server_port_activity_to_the_internet.json @@ -1,17 +1,42 @@ { - "description": "Network - SQL Server Port Activity to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects events that may describe database traffic\n(MS SQL, Oracle, MySQL, and Postgresql) across the Internet. Databases\nshould almost never be directly exposed to the Internet, as they are\nfrequently targeted by threat actors to gain initial access to network resources.\n", + "false_positives": [ + "Because these ports are in the ephemeral range, this rule may false under certain conditions such as when a NATed web server replies to a client which has used a port in the range by coincidence. In this case, such servers can be excluded if desired. Some cloud environments may use this port when VPNs or direct connects are not in use and database instances are accessed directly across the Internet." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - SQL Server Port Activity to the Internet\t", - "query": "destination.port:1433 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "SQL Traffic to the Internet", + "query": "network.transport: tcp and destination.port: (1433 or 1521 or 3336 or 5432) and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 47, "rule_id": "139c7458-566a-410c-a5cd-f80238d6a5cd", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_from_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_from_the_internet.json index 11f24626fa0c19..6c278700450b19 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_from_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_from_the_internet.json @@ -1,17 +1,72 @@ { - "description": "Network - SSH (Secure Shell) from the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of SSH traffic\nfrom the Internet. SSH is commonly used by system administrators to remotely\ncontrol a system using the command line shell. If it is exposed to the Internet,\nit should be done with strong security controls as it is frequently targeted and\nexploited by threat actors as an initial access or back-door vector.\n", + "false_positives": [ + "Some network security policies allow SSH directly from the Internet but usage that is unfamiliar to server or network owners can be unexpected and suspicious. SSH services may be exposed directly to the Internet in some networks such as cloud environments. In such cases, only SSH gateways, bastions or jump servers may be expected expose SSH directly to the Internet and can be exempted from this rule. SSH may be required by some work-flows such as remote access and support for specialized software products and servers. Such work-flows are usually known and not unexpected." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - SSH (Secure Shell) from the Internet\t", - "query": "destination.port:22 and not source.ip:10.0.0.0/8 and not source.ip:172.16.0.0/12 and not source.ip:192.168.0.0/16", - "risk_score": 50, + "name": "SSH (Secure Shell) from the Internet", + "query": "network.transport: tcp and destination.port:22 and (\n network.direction: inbound or (\n not source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 47, "rule_id": "ea0784f0-a4d7-4fea-ae86-4baaf27a6f17", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1021", + "name": "Remote Services", + "reference": "https://attack.mitre.org/techniques/T1021/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0001", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0001/" + }, + "technique": [ + { + "id": "T1190", + "name": "Exploit Public-Facing Application", + "reference": "https://attack.mitre.org/techniques/T1190/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_to_the_internet.json index ded8c005c4462e..63f2dbc8a34f12 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_to_the_internet.json @@ -1,17 +1,42 @@ { - "description": "Network - SSH (Secure Shell) to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of SSH traffic\nfrom the Internet. SSH is commonly used by system administrators to remotely\ncontrol a system using the command line shell. If it is exposed to the Internet,\nit should be done with strong security controls as it is frequently targeted and\nexploited by threat actors as an initial access or back-door vector.\n", + "false_positives": [ + "SSH connections may be made directly to Internet destinations in order to access Linux cloud server instances but such connections are usually made only by engineers. In such cases, only SSH gateways, bastions or jump servers may be expected Internet destinations and can be exempted from this rule. SSH may be required by some work-flows such as remote access and support for specialized software products and servers. Such work-flows are usually known and not unexpected. Usage that is unfamiliar to server or network owners can be unexpected and suspicious." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - SSH (Secure Shell) to the Internet\t", - "query": "destination.port:22 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "SSH (Secure Shell) to the Internet", + "query": "network.transport: tcp and destination.port:22 and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 21, "rule_id": "6f1500bc-62d7-4eb9-8601-7485e87da2f4", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_telnet_port_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_telnet_port_activity.json index a48f311163c2da..0d28f0ea53d9a3 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_telnet_port_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_telnet_port_activity.json @@ -1,17 +1,72 @@ { - "description": "Network - Telnet Port Activity\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of Telnet traffic.\nTelnet is commonly used by system administrators to remotely control older or embed ed\nsystems using the command line shell. It should almost never be directly exposed to\nthe Internet, as it is frequently targeted and exploited by threat actors as an\ninitial access or back-door vector. As a plain-text protocol, it may also expose\n", + "false_positives": [ + "IoT (Internet of Things) devices and networks may use telnet and can be excluded if desired. Some business work-flows may use Telnet for administration of older devices. These often have a predictable behavior. Telnet activity involving an unusual source or destination may be more suspicious. Telnet activity involving a production server that has no known associated Telnet work-flow or business requirement is often suspicious." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - Telnet Port Activity\t", - "query": "destination.port:23", - "risk_score": 50, + "name": "Telnet Port Activity", + "query": "network.transport: tcp and destination.port: 23", + "risk_score": 47, "rule_id": "34fde489-94b0-4500-a76f-b8a157cf9269", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1021", + "name": "Remote Services", + "reference": "https://attack.mitre.org/techniques/T1021/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1190", + "name": "Exploit Public-Facing Application", + "reference": "https://attack.mitre.org/techniques/T1190/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_tor_activity_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_tor_activity_to_the_internet.json index 713cc7da72e571..80893e9404f021 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_tor_activity_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_tor_activity_to_the_internet.json @@ -1,17 +1,57 @@ { - "description": "Network - Tor Activity to the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of Tor traffic\nto the Internet. Tor is a network protocol that sends traffic through a\nseries of encrypted tunnels used to conceal a user's location and usage.\nTor may be used by threat actors as an alternate communication pathway to\nconceal the actor's identity and avoid detection.\n", + "false_positives": [ + "Tor client activity is uncommon in managed enterprise networks but may be common in unmanaged or public networks where few security policies apply. Because these ports are in the ephemeral range, this rule may false under certain conditions such as when a NATed web server replies to a client which has used one of these ports by coincidence. In this case, such servers can be excluded if desired." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - Tor Activity to the Internet\t", - "query": "(destination.port:9001 or destination.port:9030) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "Tor Activity to the Internet", + "query": "network.transport: tcp and destination.port: (9001 or 9030) and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 47, "rule_id": "7d2c38d7-ede7-4bdf-b140-445906e6c540", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1043", + "name": "Commonly Used Port", + "reference": "https://attack.mitre.org/techniques/T1043/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1188", + "name": "Multi-hop Proxy", + "reference": "https://attack.mitre.org/techniques/T1188/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_from_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_from_the_internet.json index 4f1dba808600e4..e64138dd053fa6 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_from_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_from_the_internet.json @@ -1,17 +1,57 @@ { - "description": "Network - VNC (Virtual Network Computing) From the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of VNC traffic\nfrom the Internet. VNC is commonly used by system administrators to remotely\ncontrol a system for maintenance or to use shared resources. It should almost\nnever be directly exposed to the Internet, as it is frequently targeted and\nexploited by threat actors as an initial access or back-door vector.\n", + "false_positives": [ + "VNC connections may be received directly to Linux cloud server instances but such connections are usually made only by engineers. VNC is less common than SSH or RDP but may be required by some work-flows such as remote access and support for specialized software products or servers. Such work-flows are usually known and not unexpected. Usage that is unfamiliar to server or network owners can be unexpected and suspicious." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - VNC (Virtual Network Computing) From the Internet\t", - "query": "destination.port:5800 and not source.ip:10.0.0.0/8 and not source.ip:172.16.0.0/12 and not source.ip:192.168.0.0/16", - "risk_score": 50, + "name": "VNC (Virtual Network Computing) from the Internet", + "query": "network.transport: tcp and (destination.port >= 5800 and destination.port <= 5810) and (\n network.direction: inbound or (\n not source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 73, "rule_id": "5700cb81-df44-46aa-a5d7-337798f53eb8", - "severity": "low", - "to": "now", + "severity": "high", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1219", + "name": "Remote Access Tools", + "reference": "https://attack.mitre.org/techniques/T1219/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0001", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0001/" + }, + "technique": [ + { + "id": "T1190", + "name": "Exploit Public-Facing Application", + "reference": "https://attack.mitre.org/techniques/T1190/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_to_the_internet.json index fd04ae3ae7dee1..8c43419c3ead55 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_to_the_internet.json @@ -1,17 +1,42 @@ { - "description": "Network - VNC (Virtual Network Computing) To the Internet\t", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This signal detects network events that may indicate the use of VNC traffic\nto the Internet. VNC is commonly used by system administrators to remotely\ncontrol a system for maintenance or to use shared resources. It should almost\nnever be directly exposed to the Internet, as it is frequently targeted and\nexploited by threat actors as an initial access or back-door vector.\n", + "false_positives": [ + "VNC connections may be made directly to Linux cloud server instances but such connections are usually made only by engineers. VNC is less common than SSH or RDP but may be required by some work flows such as remote access and support for specialized software products or servers. Such work-flows are usually known and not unexpected. Usage that is unfamiliar to server or network owners can be unexpected and suspicious." + ], + "index": [ + "auditbeat-*", + "endgame-*", + "filebeat-*", + "packetbeat-*", + "winlogbeat-*" + ], "language": "kuery", - "name": "Network - VNC (Virtual Network Computing) To the Internet\t", - "query": "destination.port:5800 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "name": "VNC (Virtual Network Computing) to the Internet", + "query": "network.transport: tcp and (destination.port >= 5800 and destination.port <= 5810) and (\n network.direction: outbound or (\n source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16) and\n not destination.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)\n )\n)\n", + "risk_score": 47, "rule_id": "3ad49c61-7adc-42c1-b788-732eda2f5abf", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "network" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1219", + "name": "Remote Access Tools", + "reference": "https://attack.mitre.org/techniques/T1219/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json index d563944171b7ac..87a3119ac780d3 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json @@ -1,35 +1,43 @@ { - "description": "Null user agent", - "enabled": false, + "description": "A request to a web application server contained no identifying user agent string.", + "false_positives": [ + "Some normal applications and scripts may contain no user agent. Most legitmate web requests from the Internet contain a user agent string. Requests from web browsers almost always contain a user agent string. If the source is unexpected, or the user is unauthorized, or the request is unusual, these may be suspicious or malicious activity." + ], "filters": [ { - "meta": { - "alias": null, - "negate": true, - "disabled": false, - "type": "exists", - "key": "user_agent.original", - "value": "exists", - "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index" + "$state": { + "store": "appState" }, "exists": { "field": "user_agent.original" }, - "$state": { - "store": "appState" + "meta": { + "disabled": false, + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "key": "user_agent.original", + "negate": true, + "type": "exists", + "value": "exists" } } ], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "index": [ + "apm-*-transaction*" + ], "language": "kuery", - "name": "Null user agent", + "max_signals": 33, + "name": "Web Application Suspicious Activity: No User Agent", "query": "url.path: *", - "risk_score": 50, + "references": [ + "https://en.wikipedia.org/wiki/User_agent" + ], + "risk_score": 47, "rule_id": "43303fd4-4839-4e48-b2b2-803ab060758d", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "APM" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json index 48cf20bcbacf7e..72d85dcbffc062 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json @@ -1,17 +1,24 @@ { - "description": "SQLmap user agent", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "This is an example of how to detect an unwanted web client user agent. This search matches the user agent for sqlmap 1.3.11 which is a popular FOSS tool for testing web applications for SQL injection vulnerabilities. ", + "false_positives": [ + "This signal does not indicate that a SQL injection attack occured, only that the sqlmap tool was used. Security scans and tests may result in these errors. If the source is not an authorized security tester, this is generally suspicious or malicious activity." + ], + "index": [ + "apm-*-transaction*" + ], "language": "kuery", - "name": "SQLmap user agent", + "name": "Web Application Suspicious Activity: sqlmap User Agent", "query": "user_agent.original:\"sqlmap/1.3.11#stable (http://sqlmap.org)\"", - "risk_score": 50, + "references": [ + "http://sqlmap.org/" + ], + "risk_score": 47, "rule_id": "d49cc73f-7a16-4def-89ce-9fc7127d7820", - "severity": "low", - "to": "now", + "severity": "medium", + "tags": [ + "Elastic", + "APM" + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_invokecommand_powershell_execution.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_invokecommand_powershell_execution.json deleted file mode 100644 index 05d54f6bdb4c63..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_invokecommand_powershell_execution.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "description": "Suricata Base64 Encoded Invoke-Command Powershell Execution", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Base64 Encoded Invoke-Command Powershell Execution", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2610182 or 2610183 or 2610184 or 2610185 or 2610186 or 2610187) or rule.id: (2610182 or 2610183 or 2610184 or 2610185 or 2610186 or 2610187))", - "references": [ - "https://github.com/travisbgreen/hunting-rules/blob/master/hunting.rules#L179-L184", - "This group of signatures detect base-64 encoded variations of the 'Invoke-Command' Powershell cmdlet. This is not something you should see on a typical network and could indicate a possible command and control channel." - ], - "risk_score": 50, - "rule_id": "6ff01a30-95dd-471c-b61d-0fd9ee2d0a20", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0011", - "name": "command and control", - "reference": "https://attack.mitre.org/tactics/TA0011/" - }, - "techniques": [ - { - "id": "T1001", - "name": "data obfuscation", - "reference": "https://attack.mitre.org/techniques/T1001/" - }, - { - "id": "T1132", - "name": "data encoding", - "reference": "https://attack.mitre.org/techniques/T1132/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_newobject_powershell_execution.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_newobject_powershell_execution.json deleted file mode 100644 index ac47a6877c5250..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_newobject_powershell_execution.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "description": "Suricata Base64 Encoded New-Object Powershell Execution", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Base64 Encoded New-Object Powershell Execution", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2610188 or 2610189 or 2610190 or 2610191 or 2610192 or 2610193) or rule.id: (2610188 or 2610189 or 2610190 or 2610191 or 2610192 or 2610193))", - "references": [ - "https://github.com/travisbgreen/hunting-rules/blob/master/hunting.rules#L191-L196", - "This group of signatures detect base-64 encoded variations of the 'New-Object' Powershell cmdlet. This is not something you should see on a typical network and could indicate a possible command and control channel." - ], - "risk_score": 50, - "rule_id": "d14d5401-0f7a-4933-b816-1b8f823e3d84", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0011", - "name": "command and control", - "reference": "https://attack.mitre.org/tactics/TA0011/" - }, - "techniques": [ - { - "id": "T1001", - "name": "data obfuscation", - "reference": "https://attack.mitre.org/techniques/T1001/" - }, - { - "id": "T1132", - "name": "data encoding", - "reference": "https://attack.mitre.org/techniques/T1132/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_startprocess_powershell_execution.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_startprocess_powershell_execution.json deleted file mode 100644 index 972299bbd74b04..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_base64_encoded_startprocess_powershell_execution.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "description": "Suricata Base64 Encoded Start-Process Powershell Execution", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Base64 Encoded Start-Process Powershell Execution", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2610194 or 2610195 or 2610196 or 2610197 or 2610198 or 2610199) or rule.id: (2610194 or 2610195 or 2610196 or 2610197 or 2610198 or 2610199))", - "references": [ - "https://github.com/travisbgreen/hunting-rules/blob/master/hunting.rules#L191-L196", - "This group of signatures detect base-64 encoded variations of the 'Start-Process' Powershell cmdlet. This is not something you should see on a typical network and could indicate a possible command and control channel." - ], - "risk_score": 50, - "rule_id": "372dce88-003d-4bcf-8c95-34ea8be180a1", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0011", - "name": "command and control", - "reference": "https://attack.mitre.org/tactics/TA0011/" - }, - "techniques": [ - { - "id": "T1001", - "name": "data obfuscation", - "reference": "https://attack.mitre.org/techniques/T1001/" - }, - { - "id": "T1132", - "name": "data encoding", - "reference": "https://attack.mitre.org/techniques/T1132/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_a_suspicious_string_was_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_a_suspicious_string_was_detected.json deleted file mode 100644 index bb6a57f905bf7d..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_a_suspicious_string_was_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - A suspicious string was detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - A suspicious string was detected", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"A suspicious string was detected\" or rule.category: \"A suspicious string was detected\")", - "risk_score": 50, - "rule_id": "2a3d91c1-5065-46ab-bed0-93f80835b1d5", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_administrator_privilege_gain.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_administrator_privilege_gain.json deleted file mode 100644 index 9de1f5ad33712e..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_administrator_privilege_gain.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Attempted Administrator Privilege Gain", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Attempted Administrator Privilege Gain", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Attempted Administrator Privilege Gain\" or rule.category: \"Attempted Administrator Privilege Gain\")", - "risk_score": 50, - "rule_id": "f840129e-9089-4f46-8af1-0745e8f54713", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_denial_of_service.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_denial_of_service.json deleted file mode 100644 index d0c3eb9ba2331c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_denial_of_service.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Attempted Denial of Service", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Attempted Denial of Service", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Attempted Denial of Service\" or rule.category: \"Attempted Denial of Service\")", - "risk_score": 50, - "rule_id": "a62927f4-2488-4679-b56f-cda1a7f4c9e1", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_information_leak.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_information_leak.json deleted file mode 100644 index 75995d657b4640..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_information_leak.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Attempted Information Leak", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Attempted Information Leak", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Attempted Information Leak\" or rule.category: \"Attempted Information Leak\")", - "risk_score": 50, - "rule_id": "88d69362-f496-41d6-8e6b-a2dbaed3513f", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_login_with_suspicious_username.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_login_with_suspicious_username.json deleted file mode 100644 index 31d14a3b687089..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_login_with_suspicious_username.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Attempted Login with Suspicious Username", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Attempted Login with Suspicious Username", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"An attempted login using a suspicious username was detected\" or rule.category: \"An attempted login using a suspicious username was detected\")", - "risk_score": 50, - "rule_id": "a84cd36c-dd5a-4e86-a2ce-44556c21cef0", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_user_privilege_gain.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_user_privilege_gain.json deleted file mode 100644 index 13300e8a17694d..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_attempted_user_privilege_gain.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Attempted User Privilege Gain", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Attempted User Privilege Gain", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Attempted User Privilege Gain\" or rule.category: \"Attempted User Privilege Gain\")", - "risk_score": 50, - "rule_id": "eabce895-4602-4d20-8bf9-11c903bb3e08", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_client_using_unusual_port.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_client_using_unusual_port.json deleted file mode 100644 index 9c1e3ef1b39f8e..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_client_using_unusual_port.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Client Using Unusual Port", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Client Using Unusual Port", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"A client was using an unusual port\" or rule.category: \"A client was using an unusual port\")", - "risk_score": 50, - "rule_id": "00503a3c-304c-421c-bfea-e5d8fdfd9726", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_crypto_currency_mining_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_crypto_currency_mining_activity.json deleted file mode 100644 index a4ef732c2e1bd5..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_crypto_currency_mining_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Crypto Currency Mining Activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Crypto Currency Mining Activity", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Crypto Currency Mining Activity Detected\" or rule.category: \"Crypto Currency Mining Activity Detected\")", - "risk_score": 50, - "rule_id": "74cd4920-a441-41d2-8a23-5bee70626e60", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_decode_of_an_rpc_query.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_decode_of_an_rpc_query.json deleted file mode 100644 index 43f767f14b7e6c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_decode_of_an_rpc_query.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Decode of an RPC Query", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Decode of an RPC Query", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Decode of an RPC Query\" or rule.category: \"Decode of an RPC Query\")", - "risk_score": 50, - "rule_id": "e9fc5bd3-c8a1-442c-be6d-032da07c508b", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_default_username_and_password_login_attempt.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_default_username_and_password_login_attempt.json deleted file mode 100644 index 74a566563f15a3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_default_username_and_password_login_attempt.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Default Username and Password Login Attempt", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Default Username and Password Login Attempt", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Attempt to login by a default username and password\" or rule.category: \"Attempt to login by a default username and password\")", - "risk_score": 50, - "rule_id": "190bd112-f831-4813-98b2-e45a934277c2", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_denial_of_service.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_denial_of_service.json deleted file mode 100644 index d7a615807593e6..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_denial_of_service.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Denial of Service", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Denial of Service", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Denial of Service\" or rule.category: \"Denial of Service\")", - "risk_score": 75, - "rule_id": "0e97e390-84db-4725-965a-a8b0b600f7be", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_denial_of_service_attack.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_denial_of_service_attack.json deleted file mode 100644 index e0bf4220d4467f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_denial_of_service_attack.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Denial of Service Attack", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Denial of Service Attack", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Detection of a Denial of Service Attack\" or rule.category: \"Detection of a Denial of Service Attack\")", - "risk_score": 100, - "rule_id": "42a60eaa-fd20-479b-b6ca-bdb88d47b34b", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_executable_code_was_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_executable_code_was_detected.json deleted file mode 100644 index 09a72e761cb409..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_executable_code_was_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Executable code was detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Executable code was detected", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Executable code was detected\" or rule.category: \"Executable code was detected\")", - "risk_score": 50, - "rule_id": "4699296b-5127-475a-9d83-8434fcd18136", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_exploit_kit_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_exploit_kit_activity.json deleted file mode 100644 index 8c8f5565da4e64..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_exploit_kit_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Exploit Kit Activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Exploit Kit Activity", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Exploit Kit Activity Detected\" or rule.category: \"Exploit Kit Activity Detected\")", - "risk_score": 50, - "rule_id": "b3111af8-79bf-4ec3-97ae-28d9ed9fbd38", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_external_ip_address_retrieval.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_external_ip_address_retrieval.json deleted file mode 100644 index 39c42d81ee59d5..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_external_ip_address_retrieval.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - External IP Address Retrieval", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - External IP Address Retrieval", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Device Retrieving External IP Address Detected\" or rule.category: \"Device Retrieving External IP Address Detected\")", - "risk_score": 50, - "rule_id": "c7df9ecf-d6be-4ef8-9871-cb317dfff0b4", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_generic_icmp_event.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_generic_icmp_event.json deleted file mode 100644 index e4d15f667371f9..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_generic_icmp_event.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Generic ICMP event", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Generic ICMP event", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Generic ICMP event\" or rule.category: \"Generic ICMP event\")", - "risk_score": 25, - "rule_id": "3309bffa-7c43-409a-acea-6631c1b077e5", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_generic_protocol_command_decode.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_generic_protocol_command_decode.json deleted file mode 100644 index faaccc5eee9926..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_generic_protocol_command_decode.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Generic Protocol Command Decode", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Generic Protocol Command Decode", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Generic Protocol Command Decode\" or rule.category: \"Generic Protocol Command Decode\")", - "risk_score": 25, - "rule_id": "6fd2deb4-a7a9-4221-8b7b-8d26836a8c30", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_information_leak.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_information_leak.json deleted file mode 100644 index c58b4a5f4b13a3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_information_leak.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Information Leak", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Information Leak", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Information Leak\" or rule.category: \"Information Leak\")", - "risk_score": 25, - "rule_id": "95df8ff4-7169-4c84-ae50-3561b1d1bc91", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_large_scale_information_leak.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_large_scale_information_leak.json deleted file mode 100644 index b1916165c6e903..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_large_scale_information_leak.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Large Scale Information Leak", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Large Scale Information Leak", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Large Scale Information Leak\" or rule.category: \"Large Scale Information Leak\")", - "risk_score": 75, - "rule_id": "ca98de30-c703-4170-97ae-ab2b340f6080", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_malware_command_and_control_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_malware_command_and_control_activity.json deleted file mode 100644 index 4682f973bdfc93..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_malware_command_and_control_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Malware Command and Control Activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Malware Command and Control Activity", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Malware Command and Control Activity Detected\" or rule.category: \"Malware Command and Control Activity Detected\")", - "risk_score": 100, - "rule_id": "56656341-2940-4a69-b8fe-acf3c734f540", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_misc_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_misc_activity.json deleted file mode 100644 index 49928bd4caaa53..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_misc_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Misc Activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Misc Activity", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Misc activity\" or rule.category: \"Misc activity\")", - "risk_score": 25, - "rule_id": "403ddbde-a486-4dd7-b932-cee4ebef88b6", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_misc_attack.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_misc_attack.json deleted file mode 100644 index 34c9059d264981..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_misc_attack.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Misc Attack", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Misc Attack", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Misc Attack\" or rule.category: \"Misc Attack\")", - "risk_score": 50, - "rule_id": "83277123-749f-49da-ad3d-d59f35490db1", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_network_scan_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_network_scan_detected.json deleted file mode 100644 index 9bc0572e257795..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_network_scan_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Network Scan Detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Network Scan Detected", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Detection of a Network Scan\" or rule.category: \"Detection of a Network Scan\")", - "risk_score": 25, - "rule_id": "7e969b45-d005-4173-aee7-a7aaa79bc372", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_network_trojan_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_network_trojan_detected.json deleted file mode 100644 index b319d5d2be079b..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_network_trojan_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Network Trojan Detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Network Trojan Detected", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"A Network Trojan was detected\" or rule.category: \"A Network Trojan was detected\")", - "risk_score": 100, - "rule_id": "76ffa464-ec03-42e1-87ee-87760c331061", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_nonstandard_protocol_or_event.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_nonstandard_protocol_or_event.json deleted file mode 100644 index c104b1d2acc450..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_nonstandard_protocol_or_event.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Non-Standard Protocol or Event", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Non-Standard Protocol or Event", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Detection of a non-standard protocol or event\" or rule.category: \"Detection of a non-standard protocol or event\")", - "risk_score": 50, - "rule_id": "82f9f485-873b-4eeb-b231-052ab81e05b8", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_not_suspicious_traffic.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_not_suspicious_traffic.json deleted file mode 100644 index 4ff46e429c4c3a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_not_suspicious_traffic.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Not Suspicious Traffic", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Not Suspicious Traffic", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Not Suspicious Traffic\" or rule.category: \"Not Suspicious Traffic\")", - "risk_score": 25, - "rule_id": "c0f684ff-4f15-44e7-912d-aa8b8f08a910", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_observed_c2_domain.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_observed_c2_domain.json deleted file mode 100644 index 6b06e23648cbdb..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_observed_c2_domain.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Observed C2 Domain", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Observed C2 Domain", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Domain Observed Used for C2 Detected\" or rule.category: \"Domain Observed Used for C2 Detected\")", - "risk_score": 75, - "rule_id": "8adfa89f-aa90-4d26-9d7a-7da652cae902", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_possible_social_engineering_attempted.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_possible_social_engineering_attempted.json deleted file mode 100644 index 7c4f096280ed47..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_possible_social_engineering_attempted.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Possible Social Engineering Attempted", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Possible Social Engineering Attempted", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Possible Social Engineering Attempted\" or rule.category: \"Possible Social Engineering Attempted\")", - "risk_score": 50, - "rule_id": "7d2d5a5f-f590-407d-933a-42adb1a7bcef", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_possibly_unwanted_program.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_possibly_unwanted_program.json deleted file mode 100644 index 7e5f92c15e4141..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_possibly_unwanted_program.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Possibly Unwanted Program", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Possibly Unwanted Program", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Possibly Unwanted Program Detected\" or rule.category: \"Possibly Unwanted Program Detected\")", - "risk_score": 25, - "rule_id": "1b9a31e8-fdfa-400e-aa4e-79a7f1a1da18", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potential_corporate_privacy_violation.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potential_corporate_privacy_violation.json deleted file mode 100644 index 221cfaab48e004..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potential_corporate_privacy_violation.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Potential Corporate Privacy Violation", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Potential Corporate Privacy Violation", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Potential Corporate Privacy Violation\" or rule.category: \"Potential Corporate Privacy Violation\")", - "risk_score": 25, - "rule_id": "1c70f5d5-eae0-4d00-b35a-d34ca607094e", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potentially_bad_traffic.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potentially_bad_traffic.json deleted file mode 100644 index fc1baf20147577..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potentially_bad_traffic.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Potentially Bad Traffic", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Potentially Bad Traffic", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Potentially Bad Traffic\" or rule.category: \"Potentially Bad Traffic\")", - "risk_score": 25, - "rule_id": "197cdd5a-9880-4780-a87c-594d0ed2b7b4", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potentially_vulnerable_web_application_access.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potentially_vulnerable_web_application_access.json deleted file mode 100644 index cfcb246d44f4d1..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_potentially_vulnerable_web_application_access.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Potentially Vulnerable Web Application Access", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Potentially Vulnerable Web Application Access", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"access to a potentially vulnerable web application\" or rule.category: \"access to a potentially vulnerable web application\")", - "risk_score": 75, - "rule_id": "0993e926-1a01-4c28-918a-cdd5741a19a8", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_administrator_privilege_gain.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_administrator_privilege_gain.json deleted file mode 100644 index 919083650682c9..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_administrator_privilege_gain.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Successful Administrator Privilege Gain", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Successful Administrator Privilege Gain", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Successful Administrator Privilege Gain\" or rule.category: \"Successful Administrator Privilege Gain\")", - "risk_score": 75, - "rule_id": "f068e655-1f52-4d81-839a-9c08c6543ceb", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_credential_theft.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_credential_theft.json deleted file mode 100644 index feb708316fbd8a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_credential_theft.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Successful Credential Theft", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Successful Credential Theft", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Successful Credential Theft Detected\" or rule.category: \"Successful Credential Theft Detected\")", - "risk_score": 75, - "rule_id": "90f3e735-2187-4e8e-8d28-6e3249964851", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_user_privilege_gain.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_user_privilege_gain.json deleted file mode 100644 index 8a7e366d25e585..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_successful_user_privilege_gain.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Successful User Privilege Gain", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Successful User Privilege Gain", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Successful User Privilege Gain\" or rule.category: \"Successful User Privilege Gain\")", - "risk_score": 50, - "rule_id": "f8ebd022-6e92-4b80-ac49-7ee011ba2ce0", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_suspicious_filename_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_suspicious_filename_detected.json deleted file mode 100644 index 356c0d23dd4e9c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_suspicious_filename_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Suspicious Filename Detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Suspicious Filename Detected", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"A suspicious filename was detected\" or rule.category: \"A suspicious filename was detected\")", - "risk_score": 25, - "rule_id": "d0489b07-8140-4e3d-a2b7-52f2c06fdc7c", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_system_call_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_system_call_detected.json deleted file mode 100644 index f41692fb218412..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_system_call_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - System Call Detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - System Call Detected", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"A system call was detected\" or rule.category: \"A system call was detected\")", - "risk_score": 50, - "rule_id": "44a5c55a-a34f-43c3-8f21-df502862aa9b", - "severity": "medium", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_targeted_malicious_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_targeted_malicious_activity.json deleted file mode 100644 index 9c13b53f43263d..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_targeted_malicious_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Targeted Malicious Activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Targeted Malicious Activity", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Targeted Malicious Activity was Detected\" or rule.category: \"Targeted Malicious Activity was Detected\")", - "risk_score": 75, - "rule_id": "d299379d-41de-4640-96b6-77aaa9adfa6f", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_tcp_connection_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_tcp_connection_detected.json deleted file mode 100644 index eb41269d58ffa1..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_tcp_connection_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - TCP Connection Detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - TCP Connection Detected", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"A TCP connection was detected\" or rule.category: \"A TCP connection was detected\")", - "risk_score": 0, - "rule_id": "ddf402cf-307d-4f46-a25d-dce3aee1ad13", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_unknown_traffic.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_unknown_traffic.json deleted file mode 100644 index a260d049633b98..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_unknown_traffic.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Unknown Traffic", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Unknown Traffic", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Unknown Traffic\" or rule.category: \"Unknown Traffic\")", - "risk_score": 25, - "rule_id": "827ea90c-00c2-45f7-b873-dd060297b2d2", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_unsuccessful_user_privilege_gain.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_unsuccessful_user_privilege_gain.json deleted file mode 100644 index c57cc857cef676..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_unsuccessful_user_privilege_gain.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Unsuccessful User Privilege Gain", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Unsuccessful User Privilege Gain", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Unsuccessful User Privilege Gain\" or rule.category: \"Unsuccessful User Privilege Gain\")", - "risk_score": 50, - "rule_id": "85471d30-78c9-48f6-b2db-ab5b2547e450", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_web_application_attack.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_web_application_attack.json deleted file mode 100644 index 4014473971b8ef..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_category_web_application_attack.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Category - Web Application Attack", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Category - Web Application Attack", - "query": "event.module: suricata and event.kind: alert and (suricata.eve.alert.category: \"Web Application Attack\" or rule.category: \"Web Application Attack\")", - "risk_score": 75, - "rule_id": "e856918b-f26e-4893-84b9-3deb65046fb7", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_cobaltstrike_artifact_in_an_dns_request.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_cobaltstrike_artifact_in_an_dns_request.json deleted file mode 100644 index e77e977d780d5e..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_cobaltstrike_artifact_in_an_dns_request.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata CobaltStrike Artifact in an DNS Request", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata CobaltStrike Artifact in an DNS Request", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2610166 or 2610167 or 2610168) or rule.id: (2610166 or 2610167 or 2610168))", - "risk_score": 100, - "rule_id": "481ef0f5-beda-4fa2-8bfb-039c95500deb", - "severity": "high", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_commonly_abused_dns_domain_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_commonly_abused_dns_domain_detected.json deleted file mode 100644 index a866c79a858224..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_commonly_abused_dns_domain_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Commonly Abused DNS Domain Detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Commonly Abused DNS Domain Detected", - "query": " event.module:suricata and event.kind:alert and (suricata.eve.alert.signature:(TGI* and *HUNT* and *Abused* and *TLD*) or rule.description:(TGI* and *HUNT* and *Abused* and *TLD*))", - "risk_score": 25, - "rule_id": "1844dfe1-b05e-4ca6-b367-6b9e3a1fe227", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_reversal_characters_in_an_http_request.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_reversal_characters_in_an_http_request.json deleted file mode 100644 index 862d5417fadcc4..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_reversal_characters_in_an_http_request.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Directory Reversal Characters in an HTTP Request", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Directory Reversal Characters in an HTTP Request", - "query": "(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610161 or 2610162)", - "risk_score": 50, - "rule_id": "c0ca8090-60f8-4458-befe-c43687b648a3", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_characters_in_an_http_request.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_characters_in_an_http_request.json deleted file mode 100644 index 73cb913e271a16..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_characters_in_an_http_request.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "description": "Suricata Directory Traversal Characters in an HTTP Request Header", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Directory Traversal Characters in an HTTP Request Header", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2610161 or 2610162) or rule.id: (2610161 or 2610162))", - "references": [ - "https://github.com/travisbgreen/hunting-rules/blob/master/hunting.rules#L179-L184", - "This group of signatures detects directory traversal characters in a header of an HTTP request. This is not something you should see on a typical network and could indicate an attempt to exploit the web application." - ], - "risk_score": 50, - "rule_id": "7c663c8d-cdfd-4605-9dd6-d682fa4ade8c", - "severity": "medium", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_characters_in_http_response.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_characters_in_http_response.json deleted file mode 100644 index c9d0db8ed300ee..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_characters_in_http_response.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "description": "Suricata Directory Traversal Characters in HTTP Response", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Directory Traversal Characters in HTTP Response", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id:2610086 or rule.id:2610086)", - "references": [ - "https://github.com/travisbgreen/hunting-rules/blob/master/hunting.rules#L89", - "This group of signatures detects directory traversal characters in a header of an HTTP response. This is not something you should see on a typical network and could indicate an attempt to exploit the web application." - ], - "risk_score": 75, - "rule_id": "a6406974-ea70-45b5-b5d8-ca17695adbde", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_in_downloaded_zip_file.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_in_downloaded_zip_file.json deleted file mode 100644 index 65f8195751fc52..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_directory_traversal_in_downloaded_zip_file.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "description": "Suricata Directory Traversal in Downloaded Zip File", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Directory Traversal in Downloaded Zip File", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id:2610085 or rule.id:2610085)", - "references": [ - "https://github.com/travisbgreen/hunting-rules/blob/master/hunting.rules#L88", - "This group of signatures detects directory traversal characters in a zip archive downloaded over the network. This is not something you should see on a typical network and could indicate an attempt to trick a user to overwrite system files." - ], - "risk_score": 75, - "rule_id": "d5d990bc-303c-4241-8138-6ba3cf2ee93e", - "severity": "medium", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0002", - "name": "execution", - "reference": "https://attack.mitre.org/tactics/TA0002/" - }, - "techniques": [ - { - "id": "T1204", - "name": "user execution", - "reference": "https://attack.mitre.org/techniques/T1204/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_dns_traffic_on_unusual_tcp_port.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_dns_traffic_on_unusual_tcp_port.json deleted file mode 100644 index bd73b822f9f495..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_dns_traffic_on_unusual_tcp_port.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "description": "Suricata DNS Traffic on Unusual Port (TCP or UDP)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata DNS Traffic on Unusual Port", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2610015 or 2610013) or rule.id: (2610015 or 2610013))", - "references": [ - "https://github.com/travisbgreen/hunting-rules/blob/master/hunting.rules#L14-L16", - "This detects DNS traffic running on an unusual port. This could indicate an application that is misconfigured or attempting to bypass security controls." - ], - "risk_score": 50, - "rule_id": "deeae336-4ff7-4cf8-ae5b-18bce05da02e", - "severity": "low", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0011", - "name": "command and control", - "reference": "https://attack.mitre.org/tactics/TA0011/" - }, - "techniques": [ - { - "id": "T1065", - "name": "uncommonly used port", - "reference": "https://attack.mitre.org/techniques/T1065/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_dns_traffic_on_unusual_udp_port.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_dns_traffic_on_unusual_udp_port.json deleted file mode 100644 index eb9b06f3cab145..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_dns_traffic_on_unusual_udp_port.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata DNS Traffic on Unusual UDP Port", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata DNS Traffic on Unusual UDP Port", - "query": "suricata.eve.alert.signature_id:2610015 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "2343d9a4-365b-45b2-acb0-76934d43c75b", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_a_uri.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_a_uri.json deleted file mode 100644 index eaed3aabed8f24..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_a_uri.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Double Encoded Characters in a URI", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Double Encoded Characters in a URI", - "query": "(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610092 or 2610093 or 2610094 or 2610095)", - "risk_score": 50, - "rule_id": "1ed4d2d1-330c-4c7d-b32d-2d8805437946", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_an_http_post.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_an_http_post.json deleted file mode 100644 index 136ea957be766e..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_an_http_post.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Double Encoded Characters in an HTTP POST", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Double Encoded Characters in an HTTP POST", - "query": "suricata.eve.alert.signature_id:2610090 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "a839a360-94ae-4219-b1cc-458d836333a7", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_http_request.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_http_request.json deleted file mode 100644 index 3cbdb6da3c141f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_double_encoded_characters_in_http_request.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "description": "Suricata Double Encoded Characters in a URI", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Double Encoded Characters in a URI", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2610090 or 2610092 or 2610093 or 2610094 or 2610095) or rule.id: (2610090 or 2610092 or 2610093 or 2610094 or 2610095))", - "references": [ - "https://github.com/travisbgreen/hunting-rules/blob/master/hunting.rules", - "This group of signatures detects double encoding of characters in an HTTP request. This is not something you should see on a typical network and could indicate an attempt to exploit the web application or bypass detections." - ], - "risk_score": 25, - "rule_id": "8aedfe6f-9219-463b-808b-91e7ea8ea5e8", - "severity": "low", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_eval_php_function_in_an_http_request.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_eval_php_function_in_an_http_request.json deleted file mode 100644 index 986ac161d70df1..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_eval_php_function_in_an_http_request.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata eval PHP Function in an HTTP Request", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata eval PHP Function in an HTTP Request", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id:2610088 or rule.id: 2610088)", - "risk_score": 50, - "rule_id": "8c77b4ed-4e98-438b-adb0-d645d4a4ea26", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2018_1000861.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2018_1000861.json deleted file mode 100644 index 54b881428aa34c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2018_1000861.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SPECIFIC_APPS Jenkins Chained Exploits CVE-2018-1000861 and CVE-2019-1003000", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SPECIFIC_APPS Jenkins Chained Exploits CVE-2018-1000861 and CVE-2019-1003000", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027349 or 2027350) or rule.id: (2027349 or 2027350))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2018-1000861"], - "risk_score": 100, - "rule_id": "ada41f8a-92b1-49d0-80ac-c4bc28824ab5", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0227.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0227.json deleted file mode 100644 index c050b73114bf52..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0227.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ATTACK [PTsecurity] Possible Apache Axis RCE via SSRF (CVE-2019-0227)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ATTACK [PTsecurity] Possible Apache Axis RCE via SSRF (CVE-2019-0227)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (10004698) or rule.id: (10004698))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-0227"], - "risk_score": 100, - "rule_id": "2c8f321c-ba84-4c16-80dd-f20ea06e0c6d", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0232.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0232.json deleted file mode 100644 index 9522a286f7898c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0232.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ATTACK [PTsecurity] Apache Tomcat RCE on Windows (CVE-2019-0232)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ATTACK [PTsecurity] Apache Tomcat RCE on Windows (CVE-2019-0232)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (10004953) or rule.id: (10004953))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-0232"], - "risk_score": 100, - "rule_id": "fd7ef9a2-f010-49c1-8e08-31d84a9607dd", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0604.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0604.json deleted file mode 100644 index 95940a5396b943..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0604.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SPECIFIC_APPS Rails Arbitrary File Disclosure Attempt", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SPECIFIC_APPS Rails Arbitrary File Disclosure Attempt", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027096) or rule.id: (2027096))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-0604"], - "risk_score": 100, - "rule_id": "ec50104d-26b1-45a6-b80e-768bd13cc34c", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0708.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0708.json deleted file mode 100644 index 401e1e815ea521..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0708.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT [NCC GROUP] Possible Bluekeep Inbound RDP Exploitation Attempt (CVE-2019-0708)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Possible Bluekeep Inbound RDP Exploitation Attempt (CVE-2019-0708)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (10004867 or 2027369) or rule.id: (10004867 or 2027369))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-0708"], - "risk_score": 100, - "rule_id": "1589bff6-ec82-4acf-8f67-68ef0f3676d0", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0752.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0752.json deleted file mode 100644 index 5f256681aedd9f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_0752.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT IE Scripting Engine Memory Corruption Vulnerability (CVE-2019-0752)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT IE Scripting Engine Memory Corruption Vulnerability (CVE-2019-0752)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027721) or rule.id: (2027721))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-0752"], - "risk_score": 100, - "rule_id": "5aa5f6db-2cc7-43de-ac8b-c7daa52ba9c3", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1003000.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1003000.json deleted file mode 100644 index c470783b0266d3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1003000.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SPECIFIC_APPS Jenkins RCE CVE-2019-1003000", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SPECIFIC_APPS Jenkins RCE CVE-2019-1003000", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027349 or 2027350 or 2027346) or rule.id: (2027349 or 2027350 or 2027346))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-1003000"], - "risk_score": 100, - "rule_id": "6deba829-00ac-4298-bc80-976e4ef215d2", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_10149.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_10149.json deleted file mode 100644 index 2c18ecc3104fd2..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_10149.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Possible Exim 4.87-4.91 RCE Attempt Inbound (CVE-2019-10149", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Possible Exim 4.87-4.91 RCE Attempt Inbound (CVE-2019-10149", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027442) or rule.id: (2027442))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-10149"], - "risk_score": 100, - "rule_id": "e52d833a-0642-4076-89e9-6b7263361cee", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11043.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11043.json deleted file mode 100644 index 0e2c8cfa7339d2..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11043.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SERVER Possible PHP Remote Code Execution CVE-2019-11043 PoC (Inbound)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SERVER Possible PHP Remote Code Execution CVE-2019-11043 PoC (Inbound)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2028895) or rule.id: (2028895))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-11043"], - "risk_score": 100, - "rule_id": "7955c692-1259-4f77-aa9e-95a98b69d4aa", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11510.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11510.json deleted file mode 100644 index 65a6874f09932a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11510.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Pulse Secure SSL VPN - Arbitrary File Read (CVE-2019-11510)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Pulse Secure SSL VPN - Arbitrary File Read (CVE-2019-11510)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027904) or rule.id: (2027904))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-11510"], - "risk_score": 100, - "rule_id": "d2dbbfee-2104-4d20-b562-d466b0b2c5ef", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11580.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11580.json deleted file mode 100644 index 6e3e8bc8cdbb72..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11580.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SPECIFIC_APPS Atlassian Crowd Plugin Upload Attempt (CVE-2019-11580)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SPECIFIC_APPS Atlassian Crowd Plugin Upload Attempt (CVE-2019-11580)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027712) or rule.id: (2027712))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-11580"], - "risk_score": 100, - "rule_id": "f6e6c803-b44c-44b1-acbb-cd3e5bca10f8", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11581.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11581.json deleted file mode 100644 index 34b93871fa10b6..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_11581.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SPECIFIC_APPS Atlassian JIRA Template Injection RCE (CVE-2019-11581", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SPECIFIC_APPS Atlassian JIRA Template Injection RCE (CVE-2019-11581", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027711) or rule.id: (2027711))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-11581"], - "risk_score": 100, - "rule_id": "720663fb-23da-43a5-bf4f-907265e5426d", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_13450.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_13450.json deleted file mode 100644 index ae014db82194eb..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_13450.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Possible Zoom Client Auto-Join (CVE-2019-13450", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Possible Zoom Client Auto-Join (CVE-2019-13450", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027696) or rule.id: (2027696))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-13450"], - "risk_score": 100, - "rule_id": "04a9d926-51bb-4981-8116-04ee63f1ad75", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_13505.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_13505.json deleted file mode 100644 index 5a70886a844699..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_13505.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SPECIFIC_APPS Appointment Hour Booking - WordPress Plugin - Stored XSS (CVE-2019-13505)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SPECIFIC_APPS Appointment Hour Booking - WordPress Plugin - Stored XSS (CVE-2019-13505)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027706) or rule.id: (2027706))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-13505"], - "risk_score": 100, - "rule_id": "7b47f6a7-ae2a-46a1-a718-641649dfbfd6", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_15107.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_15107.json deleted file mode 100644 index cbede3be1782bf..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_15107.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SERVER Webmin RCE CVE-2019-15107", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SERVER Webmin RCE CVE-2019-15107", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027896) or rule.id: (2027896))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-15107"], - "risk_score": 100, - "rule_id": "37f923c4-048d-4a17-b804-b4f895477962", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_15846.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_15846.json deleted file mode 100644 index 99ac06aa715aab..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_15846.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Possible EXIM RCE Inbound (CVE-2019-15846)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Possible EXIM RCE Inbound (CVE-2019-15846)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027959 or 2027960) or rule.id: (2027959 or 2027960))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-15846"], - "risk_score": 100, - "rule_id": "1d625e03-a21b-40c8-82c0-edb497a48254", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16072.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16072.json deleted file mode 100644 index 0fe9cde7307e8c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16072.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Enigma Network Management Systems v65.0.0 CVE-2019-16072 (Outbound)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Enigma Network Management Systems v65.0.0 CVE-2019-16072 (Outbound)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2029159 or 2029158) or rule.id: (2029159 or 2029158))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-16072"], - "risk_score": 100, - "rule_id": "5cf97dad-2327-4010-8498-64e5d53fd317", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1652.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1652.json deleted file mode 100644 index 254c6019a039d3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1652.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Possible Cisco RV320 RCE Attempt (CVE-2019-1652)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Possible Cisco RV320 RCE Attempt (CVE-2019-1652)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2026860) or rule.id: (2026860))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-1652"], - "risk_score": 100, - "rule_id": "ed220bf3-6617-41c3-8a03-8726d17e3dfc", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16662.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16662.json deleted file mode 100644 index d804e7dc181739..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16662.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Possible rConfig 3.9.2 Remote Code Execution PoC (CVE-2019-16662)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Possible rConfig 3.9.2 Remote Code Execution PoC (CVE-2019-16662)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2028933) or rule.id: (2028933))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-16662"], - "risk_score": 100, - "rule_id": "777097d9-059e-409f-9509-67d7f90aea8c", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16759.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16759.json deleted file mode 100644 index 7ceebbe31c0ea2..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16759.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT vBulletin 5.x Unauthenticated Remote Code Execution (CVE-2019-16759)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT vBulletin 5.x Unauthenticated Remote Code Execution (CVE-2019-16759)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2028621 or 2028625 or 2028826) or rule.id: (2028621 or 2028625 or 2028826))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-16759"], - "risk_score": 100, - "rule_id": "145634a6-6d3d-4e78-bd51-ffe6f69f6bbb", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16928.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16928.json deleted file mode 100644 index 2c970e3248a642..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_16928.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Possible EXIM DoS (CVE-2019-16928)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Possible EXIM DoS (CVE-2019-16928)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2028636) or rule.id: (2028636))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-16928"], - "risk_score": 100, - "rule_id": "39bb4ff1-ec7c-4379-9a07-ad24b83060bf", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_17270.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_17270.json deleted file mode 100644 index 2ed70492f52cad..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_17270.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Yachtcontrol Webservers RCE CVE-2019-17270", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Yachtcontrol Webservers RCE CVE-2019-17270", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2029153 or 2029152) or rule.id: (2029153 or 2029152))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-17270"], - "risk_score": 100, - "rule_id": "e6f42ad9-c024-46de-99d8-492d780cdd5e", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1821.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1821.json deleted file mode 100644 index 9c84f3042e86ce..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_1821.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_SPECIFIC_APPS Cisco Prime Infrastruture RCE - CVE-2019-1821", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_SPECIFIC_APPS Cisco Prime Infrastruture RCE - CVE-2019-1821", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027368) or rule.id: (2027368))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-1821"], - "risk_score": 100, - "rule_id": "5aed0105-a86a-4502-9a8b-169ee24b0c7f", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_19781.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_19781.json deleted file mode 100644 index 2ee5d4bff1cbe5..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_19781.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Possible Citrix Application Delivery Controller Arbitrary Code Execution Attempt (CVE-2019-19781) M2", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Possible Citrix Application Delivery Controller Arbitrary Code Execution Attempt (CVE-2019-19781) M2", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2029206 or 2029255) or rule.id: (2029206 or 2029255))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-19781"], - "risk_score": 100, - "rule_id": "6fde4e79-bf78-4173-b395-73377e289a73", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_2618.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_2618.json deleted file mode 100644 index 7ca97786945ff1..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_2618.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ATTACK [PTsecurity] Oracle Weblogic file upload RCE (CVE-2019-2618)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ATTACK [PTsecurity] Oracle Weblogic file upload RCE (CVE-2019-2618)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (10004781) or rule.id: (10004781))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-2618"], - "risk_score": 100, - "rule_id": "7ba6a778-647c-4506-8314-8206cf31f513", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_2725.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_2725.json deleted file mode 100644 index 66a7c63c9b3735..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_2725.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ATTACK [PTsecurity] Oracle Weblogic _async deserialization RCE Attempt (CVE-2019-2725)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ATTACK [PTsecurity] Oracle Weblogic _async deserialization RCE Attempt (CVE-2019-2725)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (10004779 or 10004927) or rule.id: (10004779 or 10004927))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-2725"], - "risk_score": 100, - "rule_id": "f7879284-38e9-40d4-a471-6e1b38fd5a9f", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_3396.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_3396.json deleted file mode 100644 index b4a0f0284665dd..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_3396.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_CLIENT Possible Confluence SSTI Exploitation Attempt - Leads to RCE/LFI (CVE-2019-3396)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_CLIENT Possible Confluence SSTI Exploitation Attempt - Leads to RCE/LFI (CVE-2019-3396)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (10004699 or 2027333) or rule.id: (10004699 or 2027333))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-3396"], - "risk_score": 100, - "rule_id": "d51ce0e4-31fa-4ffb-a1a6-7f9fa386ea52", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_3929.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_3929.json deleted file mode 100644 index ae6e48baa0fa6a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_3929.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Attempted Remote Command Injection Outbound (CVE-2019-3929)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Attempted Remote Command Injection Outbound (CVE-2019-3929)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027451 or 2027450) or rule.id: (2027451 or 2027450))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-3929"], - "risk_score": 100, - "rule_id": "0a6fefd6-22dd-4c78-aba8-e949b04360b4", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_5533.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_5533.json deleted file mode 100644 index 42d9793336ae36..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_5533.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT VMware VeloCloud Authorization Bypass (CVE-2019-5533)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT VMware VeloCloud Authorization Bypass (CVE-2019-5533)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2028928) or rule.id: (2028928))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-5533"], - "risk_score": 100, - "rule_id": "65012760-1f26-47a3-b2d3-a685d638483f", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_6340.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_6340.json deleted file mode 100644 index cd55b6be262dcb..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_6340.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ATTACK [PTsecurity] Arbitrary PHP RCE in Drupal 8 < 8.5.11,8.6.10 (CVE-2019-6340)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ATTACK [PTsecurity] Arbitrary PHP RCE in Drupal 8 < 8.5.11,8.6.10 (CVE-2019-6340)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (10004555) or rule.id: (10004555))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-6340"], - "risk_score": 100, - "rule_id": "4b2b4879-45c6-4721-b058-143f07aa474f", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_7256.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_7256.json deleted file mode 100644 index e8cfcb0cfc7916..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_7256.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET EXPLOIT Linear eMerge E3 Unauthenticated Command Injection Inbound (CVE-2019-7256)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET EXPLOIT Linear eMerge E3 Unauthenticated Command Injection Inbound (CVE-2019-7256)", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2029207) or rule.id: (2029207))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-7256"], - "risk_score": 100, - "rule_id": "8ef47e09-39f5-494a-82b7-3aca4310ea96", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_9978.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_9978.json deleted file mode 100644 index 0537004ae4b2d5..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_exploit_cve_2019_9978.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "description": "ET WEB_CLIENT Attempted RCE in Wordpress Social Warfare Plugin Inbound (CVE-2019-9978", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata ET WEB_CLIENT Attempted RCE in Wordpress Social Warfare Plugin Inbound (CVE-2019-9978", - "query": "event.module:suricata and event.kind:alert and (suricata.eve.alert.signature_id: (2027315) or rule.id: (2027315))", - "references": ["https://nvd.nist.gov/vuln/detail/CVE-2019-9978"], - "risk_score": 100, - "rule_id": "6b185518-b84a-44b7-843c-01c95b5a2a83", - "severity": "high", - "threats": [ - { - "framework": "MITRE ATT&CK", - "tactic": { - "id": "TA0001", - "name": "initial access", - "reference": "https://attack.mitre.org/tactics/TA0001/" - }, - "techniques": [ - { - "id": "T1190", - "name": "exploit public-facing application", - "reference": "https://attack.mitre.org/techniques/T1190/" - } - ] - } - ], - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_ftp_traffic_on_unusual_port_internet_destination.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_ftp_traffic_on_unusual_port_internet_destination.json deleted file mode 100644 index 8c36a7052a720a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_ftp_traffic_on_unusual_port_internet_destination.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata FTP Traffic on Unusual Port, Internet Destination", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata FTP Traffic on Unusual Port, Internet Destination", - "query": "suricata.eve.alert.signature_id:2610005 and (event.module:suricata and event.kind:alert) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "b1adc850-0fe3-4dac-94d3-6f240071f83a", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_http_traffic_on_unusual_port_internet_destination.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_http_traffic_on_unusual_port_internet_destination.json deleted file mode 100644 index 72228ce1215755..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_http_traffic_on_unusual_port_internet_destination.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata HTTP Traffic On Unusual Port, Internet Destination", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata HTTP Traffic On Unusual Port, Internet Destination", - "query": " suricata.eve.alert.signature_id:2610001 and (event.module:suricata and event.kind:alert) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "43795909-913c-419d-8355-7f2880694bec", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_imap_traffic_on_unusual_port_internet_destination.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_imap_traffic_on_unusual_port_internet_destination.json deleted file mode 100644 index 1f06fbb0a337db..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_imap_traffic_on_unusual_port_internet_destination.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata IMAP Traffic on Unusual Port, internet Destination", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata IMAP Traffic on Unusual Port, internet Destination", - "query": "suricata.eve.alert.signature_id:2610009 and (event.module:suricata and event.kind:alert) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "738ee70b-7d0f-438f-98ac-a393df58c58f", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_lazagne_artifact_in_an_http_post.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_lazagne_artifact_in_an_http_post.json deleted file mode 100644 index 9c2d818b88c5d3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_lazagne_artifact_in_an_http_post.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata LaZagne Artifact in an HTTP POST", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata LaZagne Artifact in an HTTP POST", - "query": "(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610149 or 2610150)", - "risk_score": 50, - "rule_id": "c6e6f16f-66de-43d5-8ab7-599af536dedf", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_mimikatz_artifacts_in_an_http_post.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_mimikatz_artifacts_in_an_http_post.json deleted file mode 100644 index 0cbf4092bfa31d..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_mimikatz_artifacts_in_an_http_post.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Mimikatz Artifacts in an HTTP POST", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Mimikatz Artifacts in an HTTP POST", - "query": "suricata.eve.alert.signature_id:2610155 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "1b62e8af-c10d-4708-9a74-118cb1c9ed8a", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_mimikatz_string_detected_in_http_response.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_mimikatz_string_detected_in_http_response.json deleted file mode 100644 index 730aaa63ab07db..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_mimikatz_string_detected_in_http_response.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Mimikatz String Detected in HTTP Response", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Mimikatz String Detected in HTTP Response", - "query": "(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610144 or 2610145 or 2610146 or 2610147 or 2610148)", - "risk_score": 50, - "rule_id": "2b365d3a-11a3-4bec-9698-b36c908f46ff", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nondns_traffic_on_tcp_port_53.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nondns_traffic_on_tcp_port_53.json deleted file mode 100644 index 96f180fee09902..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nondns_traffic_on_tcp_port_53.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata non-DNS Traffic on TCP Port 53", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata non-DNS Traffic on TCP Port 53", - "query": "suricata.eve.alert.signature_id:2610014 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "67c7d28e-8be4-49ae-9c89-5c328ea245dc", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nondns_traffic_on_udp_port_53.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nondns_traffic_on_udp_port_53.json deleted file mode 100644 index 95458f14b0b2c6..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nondns_traffic_on_udp_port_53.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata non-DNS Traffic on UDP Port 53", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata non-DNS Traffic on UDP Port 53", - "query": "suricata.eve.alert.signature_id:2610016 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "ba6dea7f-ba98-4a86-b570-d05d85472e79", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonftp_traffic_on_port_21.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonftp_traffic_on_port_21.json deleted file mode 100644 index 42bcc2fa1bca19..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonftp_traffic_on_port_21.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata non-FTP Traffic on Port 21", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata non-FTP Traffic on Port 21", - "query": "suricata.eve.alert.signature_id:2610006 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "ee2b07ec-94dd-48b2-b46b-7bef47cc43fc", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonhttp_traffic_on_tcp_port_80.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonhttp_traffic_on_tcp_port_80.json deleted file mode 100644 index af681646e8224f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonhttp_traffic_on_tcp_port_80.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata non-HTTP Traffic on TCP Port 80", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata non-HTTP Traffic on TCP Port 80", - "query": "suricata.eve.alert.signature_id:2610002 and (event.module:suricata and event.kind:alert) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "70f9bd9f-accc-4da8-8674-38992096ddba", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonimap_traffic_on_port_1443_imap.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonimap_traffic_on_port_1443_imap.json deleted file mode 100644 index 548b35165028c3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonimap_traffic_on_port_1443_imap.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata non-IMAP Traffic on Port 1443 (IMAP)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata non-IMAP Traffic on Port 1443 (IMAP)", - "query": "suricata.eve.alert.signature_id:2610010 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "241b6a1d-4f73-4b68-bd98-22e909681930", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonsmb_traffic_on_tcp_port_139_smb.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonsmb_traffic_on_tcp_port_139_smb.json deleted file mode 100644 index a7e57103c633d9..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonsmb_traffic_on_tcp_port_139_smb.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata non-SMB Traffic on TCP Port 139 (SMB)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata non-SMB Traffic on TCP Port 139 (SMB)", - "query": "suricata.eve.alert.signature_id:2610011 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "c259ab53-4b1a-42f6-b204-fe057c521515", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonssh_traffic_on_port_22.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonssh_traffic_on_port_22.json deleted file mode 100644 index 3e07bd7a97cb85..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nonssh_traffic_on_port_22.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata non-SSH Traffic on Port 22", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata non-SSH Traffic on Port 22", - "query": "suricata.eve.alert.signature_id:2610008 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "256e9e8b-8366-4f23-8cbe-c9eb5ba25633", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nontls_on_tls_port.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nontls_on_tls_port.json deleted file mode 100644 index 16dc9f46f0e32e..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_nontls_on_tls_port.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata non-TLS on TLS Port", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata non-TLS on TLS Port", - "query": "suricata.eve.alert.signature_id:2610004 and (event.module:suricata and event.kind:alert) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "b060c87f-af49-40eb-acee-561a1f1331aa", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_possible_cobalt_strike_malleable_c2_null_response.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_possible_cobalt_strike_malleable_c2_null_response.json deleted file mode 100644 index e8bc59f1b5268a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_possible_cobalt_strike_malleable_c2_null_response.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Possible Cobalt Strike Malleable C2 Null Response", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Possible Cobalt Strike Malleable C2 Null Response", - "query": "(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610202 or 2610203)", - "risk_score": 50, - "rule_id": "6099a760-7293-4e26-8aa8-b984abb32ac6", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_possible_sql_injection_sql_commands_in_http_transactions.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_possible_sql_injection_sql_commands_in_http_transactions.json deleted file mode 100644 index 8b208e5586726a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_possible_sql_injection_sql_commands_in_http_transactions.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Possible SQL Injection - SQL Commands in HTTP Transactions", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Possible SQL Injection - SQL Commands in HTTP Transactions", - "query": "(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610117 or 2610118 or 2610118 or 2610119 or 2610121 or 2610122 or 2610123)", - "risk_score": 50, - "rule_id": "cdfbcd5e-1d8e-47e6-b3f2-b09bce780640", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_rpc_traffic_on_http_ports.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_rpc_traffic_on_http_ports.json deleted file mode 100644 index fe3d500b42d3e9..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_rpc_traffic_on_http_ports.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata RPC Traffic on HTTP Ports", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata RPC Traffic on HTTP Ports", - "query": "suricata.eve.alert.signature_id:2610012 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "87e77fb6-b555-43be-adc5-f57c6aaf7cd0", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_serialized_php_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_serialized_php_detected.json deleted file mode 100644 index a59cc42fa4557f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_serialized_php_detected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Serialized PHP Detected", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Serialized PHP Detected", - "query": "suricata.eve.alert.signature_id:2610091 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "3baa5b65-d11e-40fb-a9b4-6b2a6a062d48", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_shell_exec_php_function_in_an_http_post.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_shell_exec_php_function_in_an_http_post.json deleted file mode 100644 index e4fd0e866e7cf9..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_shell_exec_php_function_in_an_http_post.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata shell_exec PHP Function in an HTTP POST", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata shell_exec PHP Function in an HTTP POST", - "query": "suricata.eve.alert.signature_id:2610087 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "082fca48-4707-485a-aedb-340ee77e0687", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_ssh_traffic_not_on_port_22_internet_destination.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_ssh_traffic_not_on_port_22_internet_destination.json deleted file mode 100644 index a22c3a4fdfdd40..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_ssh_traffic_not_on_port_22_internet_destination.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata SSH Traffic Not on Port 22, Internet Destination", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata SSH Traffic Not on Port 22, Internet Destination", - "query": "suricata.eve.alert.signature_id:2610007 and (event.module:suricata and event.kind:alert) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "82265eef-1212-4c4f-af04-f977a3060592", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_tls_traffic_on_unusual_port_internet_destination.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_tls_traffic_on_unusual_port_internet_destination.json deleted file mode 100644 index 23f1f79bc42487..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_tls_traffic_on_unusual_port_internet_destination.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata TLS Traffic on Unusual Port, Internet Destination", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata TLS Traffic on Unusual Port, Internet Destination", - "query": "suricata.eve.alert.signature_id:2610003 and (event.module:suricata and event.kind:alert) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "6c1db8ba-db4b-4513-a0e3-b3c857ba8b05", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_windows_executable_served_by_jpeg_web_content.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_windows_executable_served_by_jpeg_web_content.json deleted file mode 100644 index 9717beac902e5f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suricata_windows_executable_served_by_jpeg_web_content.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Suricata Windows Executable Served by JPEG Web Content", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Suricata Windows Executable Served by JPEG Web Content", - "query": "suricata.eve.alert.signature_id:2610084 and (event.module:suricata and event.kind:alert)", - "risk_score": 50, - "rule_id": "f7f038f4-b97a-4d0c-b3b6-d5fa1ad15951", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_background_intelligent_transfer_service_bits_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_background_intelligent_transfer_service_bits_connecting_to_the_internet.json index 301954fc587452..9b3784345b013a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_background_intelligent_transfer_service_bits_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_background_intelligent_transfer_service_bits_connecting_to_the_internet.json @@ -1,17 +1,51 @@ { - "description": "Windows: Background Intelligent Transfer Service (BITS) Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Adversaries may abuse the Background Intelligent Transfer Service (BITS) to download, execute, or clean up after performing a malicious action.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows: Background Intelligent Transfer Service (BITS) Connecting to the Internet", + "max_signals": 33, + "name": "Background Intelligent Transfer Service (BITS) connecting to the Internet", "query": "process.name:bitsadmin.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "risk_score": 21, "rule_id": "7edadee3-98ae-472c-b1c4-8c0a2c4877cc", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1197", + "name": "BITS Jobs", + "reference": "https://attack.mitre.org/techniques/T1197/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1197", + "name": "BITS Jobs", + "reference": "https://attack.mitre.org/techniques/T1197/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_burp_ce_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_burp_ce_activity.json deleted file mode 100644 index 22429df353679c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_burp_ce_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Burp CE activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Burp CE activity", - "query": "process.name:BurpSuiteCommunity.exe", - "risk_score": 50, - "rule_id": "0f09845b-2ec8-4770-8155-7df3d4e402cc", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_connecting_to_the_internet.json index 6cf9a375586bae..0a960fc427d7b2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_connecting_to_the_internet.json @@ -1,17 +1,36 @@ { - "description": "Windows: Certutil Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies certutil.exe making a network connection. Adversaries could abuse certutil.exe to download a certificate, or malware, from a remote URL.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows: Certutil Connecting to the Internet", + "max_signals": 33, + "name": "Certutil Network Connection", "query": "process.name:certutil.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "risk_score": 21, "rule_id": "1a2cf526-6784-4c51-a2b9-f0adcc05d85c", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1105", + "name": "Remote File Copy", + "reference": "https://attack.mitre.org/techniques/T1105/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json index c404bf7a05c85e..87dbd4cd707770 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json @@ -1,17 +1,54 @@ { - "description": "Windows: Command Prompt Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies cmd.exe making a network connection. Adversaries could abuse cmd.exe to download or execute malware from a remote URL.", + "false_positives": [ + "Administrators may use the command prompt for regular administrative tasks. It's important to baseline your environment for network connections being made from the command prompt to determine any abnormal use of this tool." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows: Command Prompt Connecting to the Internet", + "max_signals": 33, + "name": "Command Prompt Network Connection", "query": "process.name:cmd.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "risk_score": 21, "rule_id": "89f9a4b0-9f8f-4ee0-8823-c4751a6d6696", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command-Line Interface", + "reference": "https://attack.mitre.org/techniques/T1059/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0011", + "name": "Command and Control", + "reference": "https://attack.mitre.org/tactics/TA0011/" + }, + "technique": [ + { + "id": "T1105", + "name": "Remote File Copy", + "reference": "https://attack.mitre.org/techniques/T1105/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_internet_explorer.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_internet_explorer.json index 1bcad8ae016ef8..a214ab4544b97e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_internet_explorer.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_internet_explorer.json @@ -1,16 +1,36 @@ { - "description": "Command shell started by Internet Explorer", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies a suspicious parent child process relationship with cmd.exe spawning form Internet Explorer.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Command shell started by Internet Explorer", + "max_signals": 33, + "name": "Internet Explorer spawning cmd.exe", "query": "process.parent.name:iexplore.exe and process.name:cmd.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "7a6e1e81-deae-4cf6-b807-9a768fff3c06", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command-Line Interface", + "reference": "https://attack.mitre.org/techniques/T1059/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json index faa9694f658ff0..187cc9d344902f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json @@ -1,16 +1,51 @@ { - "description": "Command shell started by Powershell", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies a suspicious parent child process relationship with cmd.exe descending from PowerShell.exe.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Command shell started by Powershell", + "max_signals": 33, + "name": "PowerShell spawning cmd.exe", "query": "process.parent.name:powershell.exe and process.name:cmd.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "0f616aee-8161-4120-857e-742366f5eeb3", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command-Line Interface", + "reference": "https://attack.mitre.org/techniques/T1059/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1086", + "name": "PowerShell", + "reference": "https://attack.mitre.org/techniques/T1086/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json index aa371fea3f01d2..81114bf8b87668 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json @@ -1,16 +1,36 @@ { - "description": "Command shell started by Svchost", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies a suspicious parent child process relationship with cmd.exe descending from svchost.exe", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Command shell started by Svchost", + "max_signals": 33, + "name": "Svchost spawning cmd.exe", "query": "process.parent.name:svchost.exe and process.name:cmd.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "fd7a6052-58fa-4397-93c3-4795249ccfa2", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command-Line Interface", + "reference": "https://attack.mitre.org/techniques/T1059/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_commands.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_commands.json deleted file mode 100644 index dec76deb3e8880..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_commands.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Credential Dumping Commands", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Credential Dumping Commands", - "query": "event.code: 1 and process.args:*Invoke-Mimikatz-DumpCreds* or process.args:*gsecdump* or process.args:*wce* or (process.args:*procdump* and process.args:*lsass*) or (process.args:*ntdsutil* and process.args:*ntds*ifm*create*)", - "risk_score": 50, - "rule_id": "66885745-ea38-432c-9edb-599b943948d4", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_via_imageload.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_via_imageload.json deleted file mode 100644 index de3fc49fefa374..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_via_imageload.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Credential Dumping via ImageLoad", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Credential Dumping via ImageLoad", - "query": "event.code:7 and not process.name:Sysmon.exe and not process.name:Sysmon64.exe and not process.name:svchost.exe and not process.name:logonui.exe and (file.path:*samlib.dll* or file.path:*WinSCard.dll* or file.path:*cryptdll.dll* or file.path:*hid.dll* or file.path:*vaultcli.dll*)", - "risk_score": 50, - "rule_id": "f872647c-d070-4b1c-afcc-055f081d9205", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_via_registry_save.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_via_registry_save.json deleted file mode 100644 index 016f49e22a8f8f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_via_registry_save.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Credential Dumping via Registry Save", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Credential Dumping via Registry Save", - "query": "event.code: 1 and process.name:reg.exe and process.args:*save* and (process.args:*sam* or process.args:*system*)", - "risk_score": 50, - "rule_id": "9f6fb56f-4bbd-404e-b955-49dfba7c0e68", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_data_compression_using_powershell.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_data_compression_using_powershell.json deleted file mode 100644 index cf1334eda67781..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_data_compression_using_powershell.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Data Compression Using Powershell", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Data Compression Using Powershell", - "query": "event.code: 1 and process.name:powershell.exe and (process.args:*Recurse* and process.args:*Compress-Archive*)", - "risk_score": 50, - "rule_id": "bc913943-e1f9-4bf5-a593-caca7c2eb0c3", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_decoding_using_certutil.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_decoding_using_certutil.json deleted file mode 100644 index f718e5effe8ae1..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_decoding_using_certutil.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Defense Evasion - Decoding Using Certutil", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Defense Evasion - Decoding Using Certutil", - "query": "event.code:1 and process.name:attrib.exe and (process.args:*+h* or process.args:*+s*)", - "risk_score": 50, - "rule_id": "d9642bf2-87d0-45c2-8781-2bd2017cdbb8", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_or_persistence_via_hidden_files.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_or_persistence_via_hidden_files.json deleted file mode 100644 index 844a3fc2ac9ec2..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_or_persistence_via_hidden_files.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Defense Evasion or Persistence via Hidden Files", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Defense Evasion or Persistence via Hidden Files", - "query": "event.code:1 and process.name:attrib.exe and (process.args:\"+h\" or process.args:\"+s\")", - "risk_score": 50, - "rule_id": "340a0063-baba-447b-8396-26a5cc1eb684", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json index b98b0e3f8d0aa1..7c999c1fc1e03a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json @@ -1,17 +1,37 @@ { - "description": "Windows Defense evasion via Filter Manager", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "The Filter Manager Control Program (fltMC.exe) binary may be abused by adversaries to unload a filter driver and evade defenses.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Defense evasion via Filter Manager", + "max_signals": 33, + "name": "Potential Evasion via Filter Manager", "query": "event.code:1 and process.name:fltmc.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "06dceabf-adca-48af-ac79-ffdf4c3b1e9a", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "D-SA", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1222", + "name": "File and Directory Permissions Modification", + "reference": "https://attack.mitre.org/techniques/T1222/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_windows_event_log_tools.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_windows_event_log_tools.json deleted file mode 100644 index 2d37fedd30480d..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_windows_event_log_tools.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Defense Evasion via Windows Event Log Tools", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Defense Evasion via Windows Event Log Tools", - "query": "event.code:1 and process.name:wevtutil.exe", - "risk_score": 50, - "rule_id": "07979a67-ab4d-460f-9ff3-bf1352de6762", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json index 027556b7f24569..62c8942dda9c3c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json @@ -1,17 +1,54 @@ { - "description": "Windows Execution via Compiled HTML File", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Compiled HTML files (.chm) are commonly distributed as part of the Microsoft HTML Help system. Adversaries may conceal malicious code in a CHM file and deliver it to a victim for execution. CHM content is loaded by the HTML Help executable program (hh.exe).", + "false_positives": [ + "The HTML Help executable program (hh.exe) runs whenever a user clicks a compiled help (.chm) file or menu item that opens the help file inside the Help Viewer. This is not always malicious, but adversaries may abuse this technology to conceal malicious code." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Execution via Compiled HTML File", + "max_signals": 33, + "name": "Process Activity via Compiled HTML File", "query": "event.code:1 and process.name:hh.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "e3343ab9-4245-4715-b344-e11c56b0a47f", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1223", + "name": "Compiled HTML File", + "reference": "https://attack.mitre.org/techniques/T1223/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1223", + "name": "Compiled HTML File", + "reference": "https://attack.mitre.org/techniques/T1223/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_connection_manager.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_connection_manager.json index 30d2f4e3c89360..657487232fe81c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_connection_manager.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_connection_manager.json @@ -1,17 +1,37 @@ { - "description": "Windows Execution via Connection Manager", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Various Windows utilities may be used to execute commands, possibly without invoking cmd.exe, including the Program Compatibility Assistant (pcalua.exe) or forfiles.exe.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Execution via Connection Manager", + "max_signals": 33, + "name": "Indirect Command Execution", "query": "event.code:1 and process.parent.name:pcalua.exe or (process.name:bash.exe or process.name:forfiles.exe or process.name:pcalua.exe)", - "risk_score": 50, + "risk_score": 21, "rule_id": "f2728299-167a-489c-913c-2e0955ac3c40", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "D-SA", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1202", + "name": "Indirect Command Execution", + "reference": "https://attack.mitre.org/techniques/T1202/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_microsoft_html_application_hta.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_microsoft_html_application_hta.json deleted file mode 100644 index aa67d2aebe64bb..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_microsoft_html_application_hta.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Execution via Microsoft HTML Application (HTA)", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Execution via Microsoft HTML Application (HTA)", - "query": "event.code:1 and (process.parent.args:*mshta* or process.args:*mshta*)", - "risk_score": 50, - "rule_id": "b007cc82-c522-48d1-b7a7-53f63c50c494", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json index 20e0eba610e957..80d91fa5153427 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json @@ -1,17 +1,40 @@ { - "description": "Windows Execution via .NET COM Assemblies", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Adversaries can use Regsvcs.exe and Regasm.exe to proxy execution of code through a trusted Windows utility.", + "false_positives": [ + "Administrators may use the command prompt for regular administrative tasks. It's important to baseline your environment for network connections being made from the command prompt to determine any abnormal use of this tool." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Execution via .NET COM Assemblies", + "max_signals": 33, + "name": "Execution via Regsvcs/Regasm", "query": "event.code:1 and (process.name:regasm.exe or process.name:regsvcs.exe)", - "risk_score": 50, + "risk_score": 21, "rule_id": "5c12412f-602c-4120-8c4f-69d723dbba04", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "D-SA", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1121", + "name": "Regsvcs/Regasm", + "reference": "https://attack.mitre.org/techniques/T1121/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_regsvr32.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_regsvr32.json index 9371ec67fcec5c..6b2c54d5279630 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_regsvr32.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_regsvr32.json @@ -1,17 +1,51 @@ { - "description": "Windows Execution via Regsvr32", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies scrobj.dll loaded into unusual Microsoft processes. This may indicate a malicious scriptlet is being executed in the target process.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Execution via Regsvr32", + "max_signals": 33, + "name": "Suspicious Script Object Execution", "query": "event.code: 1 and scrobj.dll and (process.name:certutil.exe or process.name:regsvr32.exe or process.name:rundll32.exe)", - "risk_score": 50, + "risk_score": 21, "rule_id": "b7333d08-be4b-4cb4-b81e-924ae37b3143", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1064", + "name": "Scripting", + "reference": "https://attack.mitre.org/techniques/T1064/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1064", + "name": "Scripting", + "reference": "https://attack.mitre.org/techniques/T1064/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json index 3153c0d38d2fd6..e722d311b86c7a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json @@ -1,17 +1,55 @@ { - "description": "Windows Execution via Trusted Developer Utilities", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies possibly suspicious activity using trusted Windows developer activity.", + "false_positives": [ + "These programs may be used by Windows developers but use by non-engineers is unusual." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Execution via Trusted Developer Utilities", + "max_signals": 33, + "name": "Trusted Developer Application Usage", "query": "event.code:1 and (process.name:MSBuild.exe or process.name:msxsl.exe)", - "risk_score": 50, + "risk_score": 21, "rule_id": "9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae1", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "D-SA", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1127", + "name": "Trusted Developer Utilities", + "reference": "https://attack.mitre.org/techniques/T1127/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1127", + "name": "Trusted Developer Utilities", + "reference": "https://attack.mitre.org/techniques/T1127/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json index 4e39ab96840dff..2b4d774281b847 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json @@ -1,17 +1,51 @@ { - "description": "Windows: HTML Help executable Program Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Compiled HTML files (.chm) are commonly distributed as part of the Microsoft HTML Help system. Adversaries may conceal malicious code in a CHM file and deliver it to a victim for execution. CHM content is loaded by the HTML Help executable program (hh.exe).", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows: HTML Help executable Program Connecting to the Internet", + "max_signals": 33, + "name": "Network Connection via Compiled HTML File", "query": "process.name:hh.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "risk_score": 21, "rule_id": "b29ee2be-bf99-446c-ab1a-2dc0183394b8", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1223", + "name": "Compiled HTML File", + "reference": "https://attack.mitre.org/techniques/T1223/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1223", + "name": "Compiled HTML File", + "reference": "https://attack.mitre.org/techniques/T1223/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_image_load_from_a_temp_directory.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_image_load_from_a_temp_directory.json deleted file mode 100644 index d00f671c7b606f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_image_load_from_a_temp_directory.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "description": "Windows image load from a temp directory", - "enabled": false, - "filters": [ - { - "$state": { - "store": "appState" - }, - "meta": { - "alias": null, - "disabled": false, - "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", - "key": "event.action", - "negate": false, - "params": { - "query": "Image loaded (rule: ImageLoad)" - }, - "type": "phrase", - "value": "Image loaded (rule: ImageLoad)" - }, - "query": { - "match": { - "event.action": { - "query": "Image loaded (rule: ImageLoad)", - "type": "phrase" - } - } - } - } - ], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows image load from a temp directory", - "query": "file.path:Temp", - "risk_score": 50, - "rule_id": "f23e4cc7-6825-4a28-b27a-e67437a9a806", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_indirect_command_execution.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_indirect_command_execution.json deleted file mode 100644 index cbde84a5fc8580..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_indirect_command_execution.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Indirect Command Execution", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Indirect Command Execution", - "query": "event.code:1 and process.parent.name:pcalua.exe or (process.name:bash.exe or process.name:forfiles.exe or process.name:pcalua.exe)", - "risk_score": 50, - "rule_id": "ff969842-c573-4e69-8e12-02fb303290f2", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_iodine_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_iodine_activity.json deleted file mode 100644 index e60c57ebc489a3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_iodine_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Iodine activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Iodine activity", - "query": "event.code: 1 and process.name:iodine.exe or process.name:iodined.exe", - "risk_score": 50, - "rule_id": "fcbbf0b2-99c5-4c7f-8411-dc9ee392e43f", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_management_instrumentation_wmi_execution.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_management_instrumentation_wmi_execution.json deleted file mode 100644 index 378b23825dc820..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_management_instrumentation_wmi_execution.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Management Instrumentation (WMI) Execution", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Management Instrumentation (WMI) Execution", - "query": "event.code:1 and (process.parent.args:*wmiprvse.exe* or process.name:wmic.exe or process.args:*wmic* )", - "risk_score": 50, - "rule_id": "cec5eb81-6e01-40e5-a1bf-bf175cce4eb4", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_microsoft_html_application_hta_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_microsoft_html_application_hta_connecting_to_the_internet.json deleted file mode 100644 index 8b5dffeec67af4..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_microsoft_html_application_hta_connecting_to_the_internet.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows: Microsoft HTML Application (HTA) Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows: Microsoft HTML Application (HTA) Connecting to the Internet", - "query": "process.name:mshta.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "b084514b-e8ba-4bc4-bc2b-50fe145a4215", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_mimikatz_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_mimikatz_activity.json deleted file mode 100644 index 1016d2c7af5f24..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_mimikatz_activity.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Windows Mimikatz activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Mimikatz activity", - "query": "event.code: 1 and process.name:mimikatz.exe", - "risk_score": 50, - "rule_id": "5346463d-062f-419d-88ff-7a5e97875210", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json index e6d606384d4548..8a4cb75588bff5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json @@ -1,17 +1,51 @@ { - "description": "Windows: Misc LOLBin Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Binaries signed with trusted digital certificates can execute on Windows systems protected by digital signature validation. Adversaries may use these binaries to 'live off the land' and execute malicious files that could bypass application whitelisting and signature validation.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows: Misc LOLBin Connecting to the Internet", + "max_signals": 33, + "name": "Network Connection via Signed Binary", "query": "(process.name:expand.exe or process.name:extrac.exe or process.name:ieexec.exe or process.name:makecab.exe) and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "risk_score": 21, "rule_id": "63e65ec3-43b1-45b0-8f2d-45b34291dc44", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1218", + "name": "Signed Binary Proxy Execution", + "reference": "https://attack.mitre.org/techniques/T1218/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1218", + "name": "Signed Binary Proxy Execution", + "reference": "https://attack.mitre.org/techniques/T1218/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_activity_by_the_system_account.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_activity_by_the_system_account.json index f8689bb314857e..5b3257daec8fbe 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_activity_by_the_system_account.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_activity_by_the_system_account.json @@ -1,16 +1,36 @@ { - "description": "Windows net command activity by the SYSTEM account", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies attempts to create new users via the SYSTEM account.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows net command activity by the SYSTEM account", + "max_signals": 33, + "name": "Net command via SYSTEM account", "query": "process.name: (net.exe or net1.exe) and user.name:SYSTEM", - "risk_score": 50, + "risk_score": 21, "rule_id": "c3f5dc81-a8b4-4144-95a7-d0a818d7355d", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1136", + "name": "Create Account", + "reference": "https://attack.mitre.org/techniques/T1136/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_user_command_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_user_command_activity.json deleted file mode 100644 index 6b895f30fd5c4e..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_user_command_activity.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Windows net user command activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows net user command activity", - "query": "process.name:net.exe and process.args:user and event.code:1", - "risk_score": 50, - "rule_id": "b039a69d-7fba-4c84-8029-57ac12548a15", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_netcat_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_netcat_activity.json deleted file mode 100644 index 8b105514ec798b..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_netcat_activity.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Windows Netcat activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Netcat activity", - "query": "process.name:ncat.exe and event.code:1", - "risk_score": 50, - "rule_id": "e2437364-0c89-4e65-a34b-782cfbb7690b", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_netcat_network_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_netcat_network_activity.json deleted file mode 100644 index c16c91d9637e56..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_netcat_network_activity.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Windows Netcat network activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Netcat network activity", - "query": "process.name:ncat.exe and event.action:\"Network connection detected (rule: NetworkConnect)\"", - "risk_score": 50, - "rule_id": "ebdc4b6f-7fdb-4c21-bbd6-59e1ed11024a", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_network_anomalous_windows_process_using_https_ports.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_network_anomalous_windows_process_using_https_ports.json deleted file mode 100644 index a22b12d242414a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_network_anomalous_windows_process_using_https_ports.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Network - Anomalous Windows Process Using HTTP/S Ports", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Network - Anomalous Windows Process Using HTTP/S Ports", - "query": "(destination.port:443 or destination.port:80) and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16 and not process.name:chrome.exe and not process.name:explorer.exe and not process.name:filebeat.exe and not process.name:firefox.exe and not process.name:iexplore.exe and not process.name:jusched.exe and not process.name:MpCmdRun.exe and not process.name:MpSigStub.exe and not process.name:msfeedssync.exe and not process.name:packetbeat.exe and not process.name:powershell.exe and not process.name:procexp64.exe and not process.name:svchost.exe and not process.name:taskhostw.exe and not process.name:winlogbeat.exe", - "risk_score": 50, - "rule_id": "b486fa9e-e6c7-44a1-b07d-7d5f07f21ce1", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_nmap_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_nmap_activity.json deleted file mode 100644 index a0c3b5be64d1c3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_nmap_activity.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Windows nmap activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows nmap activity", - "query": "process.name:nmap.exe and event.code:1", - "risk_score": 50, - "rule_id": "5a4b2a98-31a6-4852-b224-d63aeb9e172d", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_nmap_scan_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_nmap_scan_activity.json deleted file mode 100644 index 0195367b6f7125..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_nmap_scan_activity.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Windows nmap scan activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows nmap scan activity", - "query": "process.name:nmap.exe and event.action:\"Network connection detected (rule: NetworkConnect)\"", - "risk_score": 50, - "rule_id": "54413985-a3da-4f45-b238-75afb65a1bae", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_payload_obfuscation_via_certutil.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_payload_obfuscation_via_certutil.json deleted file mode 100644 index 421cadfa8a63d7..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_payload_obfuscation_via_certutil.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Payload Obfuscation via Certutil", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Payload Obfuscation via Certutil", - "query": "event.code:1 and process.name:certutil.exe and (process.args:*encode* or process.args:*ToBase64String*)", - "risk_score": 50, - "rule_id": "ce7c270c-c69b-47dd-8c21-60a35e92f372", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_or_priv_escalation_via_hooking.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_or_priv_escalation_via_hooking.json deleted file mode 100644 index 47de4ba9ff6e74..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_or_priv_escalation_via_hooking.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Persistence or Priv Escalation via Hooking", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Persistence or Priv Escalation via Hooking", - "query": "event.code:1 and process.name:mavinject.exe and processs.args:*INJECTRUNNING*", - "risk_score": 50, - "rule_id": "015f070d-cf70-437c-99d1-472e31d36b03", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json index c6e558a3be2607..2c10382cdbc7c0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json @@ -1,17 +1,52 @@ { - "description": "Windows Persistence via Application Shimming", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "The Application Shim was created to allow for backward compatibility of software as the operating system codebase changes over time. This Windows functionality has been abused by attackers to stealthily gain persistence and arbitrary code execution in legitimate Windows processes.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Persistence via Application Shimming", + "max_signals": 33, + "name": "Potential Application Shimming via Sdbinst", "query": "event.code:1 and process.name:sdbinst.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "fd4a992d-6130-4802-9ff8-829b89ae801f", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "D-SA", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1138", + "name": "Application Shimming", + "reference": "https://attack.mitre.org/techniques/T1138/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1138", + "name": "Application Shimming", + "reference": "https://attack.mitre.org/techniques/T1138/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_bits_jobs.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_bits_jobs.json deleted file mode 100644 index b6d97628f98ec5..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_bits_jobs.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Persistence via BITS Jobs", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Persistence via BITS Jobs", - "query": "event.code:1 and (process.name:bitsadmin.exe or process.args:*Start-BitsTransfer*)", - "risk_score": 50, - "rule_id": "7904fb20-172c-43fb-83e4-bfe27e3c702c", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_modification_of_existing_service.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_modification_of_existing_service.json deleted file mode 100644 index 782ce7a6eec92b..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_modification_of_existing_service.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Persistence via Modification of Existing Service", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Persistence via Modification of Existing Service", - "query": "event.code:1 and process.args:*sc*config*binpath* and (process.name:cmd.exe or process.name:powershell.exe or process.name:sc.exe)", - "risk_score": 50, - "rule_id": "3bb04809-84ab-4487-bd99-ccc58675bd40", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_netshell_helper_dll.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_netshell_helper_dll.json deleted file mode 100644 index 19e6ac51158eb3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_netshell_helper_dll.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Persistence via Netshell Helper DLL", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Persistence via Netshell Helper DLL", - "query": "event.code:1 and process.name:netsh.exe and process.args:*helper*", - "risk_score": 50, - "rule_id": "d7c2561d-2758-46ad-b5a9-247efb9eea21", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_powershell_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_powershell_connecting_to_the_internet.json deleted file mode 100644 index 50e3d6e0f38747..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_powershell_connecting_to_the_internet.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows: Powershell Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows: Powershell Connecting to the Internet", - "query": "process.name:powershell.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:169.254.169.254/32 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "a8cfa646-e4d8-48b5-884e-6204ba77fc8d", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json index 96faa2a88e3a63..23d05aaf526e3a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json @@ -1,17 +1,52 @@ { - "description": "Windows Priv Escalation via Accessibility Features", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Windows contains accessibility features that may be launched with a key combination before a user has logged in. An adversary can modify the way these programs are launched to get a command prompt or backdoor without logging in to the system.", + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Priv Escalation via Accessibility Features", + "max_signals": 33, + "name": "Potential Modification of Accessibility Binaries", "query": "event.code:1 and process.parent.name:winlogon.exe and (process.name:atbroker.exe or process.name:displayswitch.exe or process.name:magnify.exe or process.name:narrator.exe or process.name:osk.exe or process.name:sethc.exe or process.name:utilman.exe)", - "risk_score": 50, + "risk_score": 21, "rule_id": "7405ddf1-6c8e-41ce-818f-48bea6bcaed8", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "D-SA", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1015", + "name": "Accessibility Features", + "reference": "https://attack.mitre.org/techniques/T1015/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1015", + "name": "Accessibility Features", + "reference": "https://attack.mitre.org/techniques/T1015/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json index 572a9ede23e2af..5f5215ddff8c63 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json @@ -1,17 +1,40 @@ { - "description": "Windows Process Discovery via Tasklist Command", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Adversaries may attempt to get information about running processes on a system.", + "false_positives": [ + "Administrators may use the tasklist command to display a list of currently running processes. By itself, it does not indicate malicious activity. After obtaining a foothold, it's possible adversaries may use discovery commands like tasklist to get information about running processes." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Process Discovery via Tasklist Command", + "max_signals": 33, + "name": "Process Discovery via Tasklist", "query": "event.code:1 and process.name:tasklist.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "cc16f774-59f9-462d-8b98-d27ccd4519ec", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "D-SA", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0007", + "name": "Discovery", + "reference": "https://attack.mitre.org/tactics/TA0007/" + }, + "technique": [ + { + "id": "T1057", + "name": "Process Discovery", + "reference": "https://attack.mitre.org/techniques/T1057/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_execution_via_wmi.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_execution_via_wmi.json index 9e29c82e48872e..6d6343330a7ff9 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_execution_via_wmi.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_execution_via_wmi.json @@ -1,17 +1,39 @@ { - "description": "Process Execution via WMI", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of scrcons.exe, which is a Windows Management Instrumentation (WMI) Standard Event Consumer scripting application.", + "false_positives": [ + " Windows Management Instrumentation (WMI) processes can be used for an array of administrative capabilities. It's important to baseline your environment to determine any abnormal use of this tool." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Process Execution via WMI", + "max_signals": 33, + "name": "Execution via Scrcons", "query": "process.name:scrcons.exe", - "risk_score": 50, + "risk_score": 21, "rule_id": "7e6cd4b9-6346-4683-b3e6-6a3e66f3208f", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1047", + "name": "Windows Management Instrumentation", + "reference": "https://attack.mitre.org/techniques/T1047/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_acrobat_reader_possible_payload.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_acrobat_reader_possible_payload.json deleted file mode 100644 index e96c223765cbdb..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_acrobat_reader_possible_payload.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Process started by Acrobat reader - possible payload", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Process started by Acrobat reader - possible payload", - "query": "process.parent.name:AcroRd32.exe and event.code:1", - "risk_score": 50, - "rule_id": "b6422896-b6e3-45c3-9d9e-4eccb2a25270", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_ms_office_program_possible_payload.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_ms_office_program_possible_payload.json deleted file mode 100644 index c2e185cd0c7ebf..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_ms_office_program_possible_payload.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Process started by MS Office program - possible payload", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Process started by MS Office program - possible payload", - "query": "process.parent.name:EXCEL.EXE or process.parent.name:MSPUB.EXE or process.parent.name:OUTLOOK.EXE or process.parent.name:POWERPNT.EXE or process.parent.name:VISIO.EXE or process.parent.name:WINWORD.EXE and event.code:1", - "risk_score": 50, - "rule_id": "838dcec6-ce9a-4cdd-9ca8-f6512cf6d559", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_the_java_runtime.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_the_java_runtime.json deleted file mode 100644 index 6902807cb51d11..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_started_by_the_java_runtime.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "description": "Windows process started by the Java runtime", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows process started by the Java runtime", - "query": "process.parent.name:javaw.exe and event.code:1", - "risk_score": 50, - "rule_id": "159168a1-b1d0-4e5c-ad72-c1e9ae2edec2", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_psexec_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_psexec_activity.json deleted file mode 100644 index 280f061ed7785e..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_psexec_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "PSexec activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "PSexec activity", - "query": "process.name:PsExec.exe or process.name:PsExec64.exe", - "risk_score": 50, - "rule_id": "3e61ab8b-0f39-4d2e-ab64-332f0d0b3ad7", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json index 563553a24a3e7b..b35e016be15d7a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json @@ -1,17 +1,54 @@ { - "description": "Windows: Register Server Program Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies the native Windows tools regsvr32.exe and regsvr64.exe making a network connection. This may be indicative of an attacker bypassing whitelisting or running arbitrary scripts via a signed Microsoft binary.", + "false_positives": [ + "Security testing may produce events like this. Activity of this kind performed by non-engineers and ordinary users is unusual." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows: Register Server Program Connecting to the Internet", + "max_signals": 33, + "name": "Network Connection via Regsvr", "query": "(process.name:regsvr32.exe or process.name:regsvr64.exe) and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:169.254.169.254/32 and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, + "risk_score": 21, "rule_id": "fb02b8d3-71ee-4af1-bacd-215d23f17efa", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1117", + "name": "Regsvr32", + "reference": "https://attack.mitre.org/techniques/T1117/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1117", + "name": "Regsvr32", + "reference": "https://attack.mitre.org/techniques/T1117/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_registry_query_local.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_registry_query_local.json deleted file mode 100644 index d9bc00cfbd3367..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_registry_query_local.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Registry Query, Local", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Registry Query, Local", - "query": "event.code: 1 and process.name:reg.exe and process.args:*query* and process.args:*reg*", - "risk_score": 50, - "rule_id": "b9074c74-6d23-4b07-927e-cc18b318a088", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_registry_query_network.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_registry_query_network.json deleted file mode 100644 index ddf8ff569e35f7..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_registry_query_network.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Registry Query, Network", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Registry Query, Network", - "query": "event.code: 1 and process.name:reg.exe and process.args:*query* and process.args:*reg*", - "risk_score": 50, - "rule_id": "f5412e37-981e-4d37-a1b2-eddaf797445a", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_remote_management_execution.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_remote_management_execution.json deleted file mode 100644 index 0e67b777ac6dc5..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_remote_management_execution.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Remote Management Execution", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Remote Management Execution", - "query": "(process.name:wsmprovhost.exe or process.name:winrm.cmd) and (process.args:*Enable-PSRemoting -Force* or process.args:*Invoke-Command -computer_name* or process.args:*wmic*node*process call create*)", - "risk_score": 50, - "rule_id": "ced66221-3e07-40ee-8588-5f107e7d50d8", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_scheduled_task_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_scheduled_task_activity.json deleted file mode 100644 index 58fd2df8f15ef1..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_scheduled_task_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Scheduled Task Activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Scheduled Task Activity", - "query": "event.code:1 and (process.name:schtasks.exe or process.name:taskeng.exe) or (event.code:1 and process.name:svchost.exe and not process.parent.executable: \"C:\\Windows\\System32\\services.exe\" )", - "risk_score": 50, - "rule_id": "a1abd54d-3021-4f21-b2d1-0c6bc5c4051f", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_script_interpreter_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_script_interpreter_connecting_to_the_internet.json deleted file mode 100644 index 41559425538ab2..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_script_interpreter_connecting_to_the_internet.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows: Script Interpreter Connecting to the Internet", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows: Script Interpreter Connecting to the Internet", - "query": "(process.name:cscript.exe or process.name:wscript.exe) and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:10.0.0.0/8 and not destination.ip:172.16.0.0/12 and not destination.ip:192.168.0.0/16", - "risk_score": 50, - "rule_id": "2cc4597c-b0c9-4481-b1a6-e6c05cfc9f02", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_signed_binary_proxy_execution.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_signed_binary_proxy_execution.json index 64185c784e0282..cf5135cc490eb0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_signed_binary_proxy_execution.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_signed_binary_proxy_execution.json @@ -1,17 +1,54 @@ { - "description": "Windows Signed Binary Proxy Execution", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Binaries signed with trusted digital certificates can execute on Windows systems protected by digital signature validation. Adversaries may use these binaries to 'live off the land' and execute malicious files that could bypass application whitelisting and signature validation.", + "false_positives": [ + "Security testing may produce events like this. Activity of this kind performed by non-engineers and ordinary users is unusual." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Signed Binary Proxy Execution", + "max_signals": 33, + "name": "Execution via Signed Binary", "query": "event.code:1 and http and (process.name:certutil.exe or process.name:msiexec.exe)", - "risk_score": 50, + "risk_score": 21, "rule_id": "7edb573f-1f9b-4161-8c19-c7c383bb17f2", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1218", + "name": "Signed Binary Proxy Execution", + "reference": "https://attack.mitre.org/techniques/T1218/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1218", + "name": "Signed Binary Proxy Execution", + "reference": "https://attack.mitre.org/techniques/T1218/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_signed_binary_proxy_execution_download.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_signed_binary_proxy_execution_download.json index b1146f07612f67..117a40d0fdcee7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_signed_binary_proxy_execution_download.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_signed_binary_proxy_execution_download.json @@ -1,17 +1,54 @@ { - "description": "Windows Signed Binary Proxy Execution Download", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Binaries signed with trusted digital certificates can execute on Windows systems protected by digital signature validation. Adversaries may use these binaries to 'live off the land' and execute malicious files that could bypass application whitelisting and signature validation.", + "false_positives": [ + "Security testing may produce events like this. Activity of this kind performed by non-engineers and ordinary users is unusual." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows Signed Binary Proxy Execution Download", + "max_signals": 33, + "name": "Potential Download via Signed Binary", "query": " event.code:3 and http and (process.name:certutil.exe or process.name:replace.exe)", - "risk_score": 50, + "risk_score": 21, "rule_id": "68ecc190-cce2-4021-b976-c7c846ac0a00", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1218", + "name": "Signed Binary Proxy Execution", + "reference": "https://attack.mitre.org/techniques/T1218/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1218", + "name": "Signed Binary Proxy Execution", + "reference": "https://attack.mitre.org/techniques/T1218/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_suspicious_process_started_by_a_script.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_suspicious_process_started_by_a_script.json index c5a7db434ac386..3691c59d784fb7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_suspicious_process_started_by_a_script.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_suspicious_process_started_by_a_script.json @@ -1,16 +1,54 @@ { - "description": "Suspicious process started by a script", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies a suspicious process being spawned from a script interpreter, which could be indicative of a potential phishing attack.", + "false_positives": [ + "Security testing may produce events like this. Activity of this kind performed by non-engineers and ordinary users is unusual." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Suspicious process started by a script", + "max_signals": 33, + "name": "Suspicious Process Spawning from Script Interpreter", "query": "(process.parent.name:cmd.exe or process.parent.name:cscript.exe or process.parent.name:mshta.exe or process.parent.name:powershell.exe or process.parent.name:rundll32.exe or process.parent.name:wscript.exe or process.parent.name:wmiprvse.exe) and (process.name:bitsadmin.exe or process.name:certutil.exe or mshta.exe or process.name:nslookup.exe or process.name:schtasks.exe) and event.code:1", - "risk_score": 50, + "risk_score": 21, "rule_id": "89db767d-99f9-479f-8052-9205fd3090c4", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1064", + "name": "Scripting", + "reference": "https://attack.mitre.org/techniques/T1064/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1064", + "name": "Scripting", + "reference": "https://attack.mitre.org/techniques/T1064/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json index b13a20518893cf..3618d304dc32a3 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json @@ -1,16 +1,39 @@ { - "description": "Windows whoami command activity", - "enabled": false, - "from": "now-6m", - "immutable": true, - "interval": "5m", + "description": "Identifies use of whoami.exe which displays user, group, and privileges information for the user who is currently logged on to the local system.", + "false_positives": [ + "Some normal use of this program, at varying levels of frequency, may originate from scripts, automation tools and frameworks. Usage by non-engineers and ordinary users is unusual." + ], + "index": [ + "winlogbeat-*" + ], "language": "kuery", - "name": "Windows whoami command activity", + "max_signals": 33, + "name": "Whoami Process Activity", "query": "process.name:whoami.exe and event.code:1", - "risk_score": 50, + "risk_score": 21, "rule_id": "ef862985-3f13-4262-a686-5f357bbb9bc2", "severity": "low", - "to": "now", + "tags": [ + "Elastic", + "Windows" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0007", + "name": "Discovery", + "reference": "https://attack.mitre.org/tactics/TA0007/" + }, + "technique": [ + { + "id": "T1033", + "name": "System Owner/User Discovery", + "reference": "https://attack.mitre.org/techniques/T1033/" + } + ] + } + ], "type": "query", "version": 1 } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_windump_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_windump_activity.json deleted file mode 100644 index 8fc548b694b02b..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_windump_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "WinDump activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "WinDump activity", - "query": "process.name:WinDump.exe", - "risk_score": 50, - "rule_id": "a342cfcb-8420-46a4-8d85-53edc631e0d6", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_wireshark_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_wireshark_activity.json deleted file mode 100644 index 30ee18fe53557b..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_wireshark_activity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Windows Wireshark activity", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Windows Wireshark activity", - "query": "process.name:wireshark.exe", - "risk_score": 50, - "rule_id": "9af965ed-d501-4541-97f6-5f8d2a39737b", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_capturelosstoo_much_loss.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_capturelosstoo_much_loss.json deleted file mode 100644 index 87549a455c1d3e..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_capturelosstoo_much_loss.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Detected Zeek capture loss exceeds the percentage threshold", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice CaptureLoss::Too_Much_Loss", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"CaptureLoss::Too_Much_Loss\" or rule.name: \"CaptureLoss::Too_Much_Loss\")", - "risk_score": 50, - "rule_id": "c115a407-799b-45d6-962e-a639bb764c06", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_conncontent_gap.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_conncontent_gap.json deleted file mode 100644 index 69a82f9840a931..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_conncontent_gap.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Data has sequence hole; perhaps due to filtering.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Conn::Content_Gap", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Conn::Content_Gap\" or rule.name: \"Conn::Content_Gap\")", - "risk_score": 50, - "rule_id": "22d12b64-33f4-40ce-ad57-49dd870bc8e5", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_connretransmission_inconsistency.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_connretransmission_inconsistency.json deleted file mode 100644 index c5ba4eb8082aaf..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_connretransmission_inconsistency.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Possible evasion; usually just chud.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Conn::Retransmission_Inconsistency", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Conn::Retransmission_Inconsistency\" or rule.name: \"Conn::Retransmission_Inconsistency\")", - "risk_score": 50, - "rule_id": "53719624-55f0-4541-8370-f27f6766fb9e", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_dnsexternal_name.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_dnsexternal_name.json deleted file mode 100644 index cb5db1529aa0ec..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_dnsexternal_name.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Raised when a non-local name is found to be pointing at a local host.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice DNS::External_Name", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"DNS::External_Name\" or rule.name: \"DNS::External_Name\")", - "risk_score": 50, - "rule_id": "39c40c5a-110c-45b1-876f-969212e8814b", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_ftpbruteforcing.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_ftpbruteforcing.json deleted file mode 100644 index 43bc1f05a2212f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_ftpbruteforcing.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates a host bruteforcing FTP logins by watching for too many rejected usernames or failed passwords.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice FTP::Bruteforcing", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"FTP::Bruteforcing\" or rule.name: \"FTP::Bruteforcing\")", - "risk_score": 50, - "rule_id": "7e069475-817e-4e89-9245-1dfaa3083b11", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_ftpsite_exec_success.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_ftpsite_exec_success.json deleted file mode 100644 index 63b8b847563b57..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_ftpsite_exec_success.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a successful response to a “SITE EXEC” command/arg pair was seen.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice FTP::Site_Exec_Success", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"FTP::Site_Exec_Success\" or rule.name: \"FTP::Site_Exec_Success\")", - "risk_score": 50, - "rule_id": "4b9cb3e9-e26a-4bd2-bd1f-8d451b49838f", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_attack.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_attack.json deleted file mode 100644 index adc8878f6986aa..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_attack.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a host performed a heartbleed attack or scan.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Heartbleed::SSL_Heartbeat_Attack", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Heartbleed::SSL_Heartbeat_Attack\" or rule.name: \"Heartbleed::SSL_Heartbeat_Attack\")", - "risk_score": 50, - "rule_id": "68a33102-3680-4581-a48a-210b23925905", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_attack_success.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_attack_success.json deleted file mode 100644 index 3f03e5483cc315..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_attack_success.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a host performing a heartbleed attack was probably successful.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Heartbleed::SSL_Heartbeat_Attack_Success", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Heartbleed::SSL_Heartbeat_Attack_Success\" or rule.name: \"Heartbleed::SSL_Heartbeat_Attack_Success\")", - "risk_score": 50, - "rule_id": "241a61ae-b385-4f36-96c4-b2fb5446cc43", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_many_requests.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_many_requests.json deleted file mode 100644 index 2902c4a4b8e5fe..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_many_requests.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates we saw many heartbeat requests without a reply. Might be an attack.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Heartbleed::SSL_Heartbeat_Many_Requests", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Heartbleed::SSL_Heartbeat_Many_Requests\" or rule.name: \"Heartbleed::SSL_Heartbeat_Many_Requests\")", - "risk_score": 50, - "rule_id": "59d6a32c-753e-4c19-bb77-1befdc6e0e6a", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_odd_length.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_odd_length.json deleted file mode 100644 index 871999b842609a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_heartbleedssl_heartbeat_odd_length.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates we saw heartbeat requests with odd length. Probably an attack or scan.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Heartbleed::SSL_Heartbeat_Odd_Length", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Heartbleed::SSL_Heartbeat_Odd_Length\" or rule.name: \"Heartbleed::SSL_Heartbeat_Odd_Length\")", - "risk_score": 50, - "rule_id": "0c6e7be4-6cab-4ee1-ad51-7c1ffd0e9002", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_httpsql_injection_attacker.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_httpsql_injection_attacker.json deleted file mode 100644 index fe6bcb8a881003..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_httpsql_injection_attacker.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a host performing SQL injection attacks was detected.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice HTTP::SQL_Injection_Attacker", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"HTTP::SQL_Injection_Attacker\" or rule.name: \"HTTP::SQL_Injection_Attacker\")", - "risk_score": 50, - "rule_id": "4ca9ef93-7e7e-40a4-8d71-9130204d86e6", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_httpsql_injection_victim.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_httpsql_injection_victim.json deleted file mode 100644 index ed1f5bbaa13b2a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_httpsql_injection_victim.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a host was seen to have SQL injection attacks against it. This is tracked by IP address as opposed to hostname.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice HTTP::SQL_Injection_Victim", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"HTTP::SQL_Injection_Victim\" or rule.name: \"HTTP::SQL_Injection_Victim\")", - "risk_score": 50, - "rule_id": "dda43d7f-69bc-487f-b05c-2b518e9db622", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_intelnotice.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_intelnotice.json deleted file mode 100644 index 615f3b48276567..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_intelnotice.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "This notice is generated when an intelligence indicator is denoted to be notice-worthy.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Intel::Notice", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Intel::Notice\" or rule.name: \"Intel::Notice\")", - "risk_score": 50, - "rule_id": "122e153a-78f3-4e7e-a5b5-cfe0b917f109", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_noticetally.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_noticetally.json deleted file mode 100644 index cbe9fd654c4f80..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_noticetally.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Zeek notice reporting a count of how often a notice occurred.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Notice::Tally", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Notice::Tally\" or rule.name: \"Notice::Tally\")", - "risk_score": 50, - "rule_id": "7581fd81-25e8-489e-bcf3-69db068b7a6c", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltercannot_bpf_shunt_conn.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltercannot_bpf_shunt_conn.json deleted file mode 100644 index 2d35d42eb07a1d..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltercannot_bpf_shunt_conn.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Limitations in BPF make shunting some connections with BPF impossible. This notice encompasses those various cases.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice PacketFilter::Cannot_BPF_Shunt_Conn", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"PacketFilter::Cannot_BPF_Shunt_Conn\" or rule.name: \"PacketFilter::Cannot_BPF_Shunt_Conn\")", - "risk_score": 50, - "rule_id": "0031d83e-1fb4-4dd6-b938-97ae7044b051", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltercompile_failure.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltercompile_failure.json deleted file mode 100644 index 4013b77fe6e4ce..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltercompile_failure.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "This notice is generated if a packet filter cannot be compiled.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice PacketFilter::Compile_Failure", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"PacketFilter::Compile_Failure\" or rule.name: \"PacketFilter::Compile_Failure\")", - "risk_score": 50, - "rule_id": "335b2ddc-f806-46e8-8ffa-114d613aac92", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterdropped_packets.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterdropped_packets.json deleted file mode 100644 index 21229e4055f480..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterdropped_packets.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates packets were dropped by the packet filter.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice PacketFilter::Dropped_Packets", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"PacketFilter::Dropped_Packets\" or rule.name: \"PacketFilter::Dropped_Packets\")", - "risk_score": 50, - "rule_id": "4f212278-329b-4088-ae59-9091003dff22", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterinstall_failure.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterinstall_failure.json deleted file mode 100644 index 6f6ff30f99b570..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterinstall_failure.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Generated if a packet filter fails to install.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice PacketFilter::Install_Failure", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"PacketFilter::Install_Failure\" or rule.name: \"PacketFilter::Install_Failure\")", - "risk_score": 50, - "rule_id": "235988ec-d037-4f5f-a211-74106512b36d", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterno_more_conn_shunts_available.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterno_more_conn_shunts_available.json deleted file mode 100644 index 0785959078bb71..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfilterno_more_conn_shunts_available.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicative that PacketFilter::max_bpf_shunts connections are already being shunted with BPF filters and no more are allowed.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice PacketFilter::No_More_Conn_Shunts_Available", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"PacketFilter::No_More_Conn_Shunts_Available\" or rule.name: \"PacketFilter::No_More_Conn_Shunts_Available\")", - "risk_score": 50, - "rule_id": "de4016de-3374-41a0-a678-21d36c70af9a", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltertoo_long_to_compile_filter.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltertoo_long_to_compile_filter.json deleted file mode 100644 index e8dbcaaeec43e0..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_packetfiltertoo_long_to_compile_filter.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Generated when a notice takes too long to compile.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice PacketFilter::Too_Long_To_Compile_Filter", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"PacketFilter::Too_Long_To_Compile_Filter\" or rule.name: \"PacketFilter::Too_Long_To_Compile_Filter\")", - "risk_score": 50, - "rule_id": "71e93c42-7990-4233-a8a5-2631193df7db", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_protocoldetectorprotocol_found.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_protocoldetectorprotocol_found.json deleted file mode 100644 index 0caf01e3823c9b..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_protocoldetectorprotocol_found.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates a protocol was detected on a non-standard port.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice ProtocolDetector::Protocol_Found", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"ProtocolDetector::Protocol_Found\" or rule.name: \"ProtocolDetector::Protocol_Found\")", - "risk_score": 50, - "rule_id": "777586b6-4757-489e-a6e8-676b7df70b39", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_protocoldetectorserver_found.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_protocoldetectorserver_found.json deleted file mode 100644 index 196c9dc7241c8c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_protocoldetectorserver_found.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates a server was detected on a non-standard port for the protocol.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice ProtocolDetector::Server_Found", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"ProtocolDetector::Server_Found\" or rule.name: \"ProtocolDetector::Server_Found\")", - "risk_score": 50, - "rule_id": "7d7f7635-6900-4f63-b14b-477a909ea90a", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_scanaddress_scan.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_scanaddress_scan.json deleted file mode 100644 index 34c8a126e424c0..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_scanaddress_scan.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Address scans detect that a host appears to be scanning some number of destinations on a single port.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Scan::Address_Scan", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Scan::Address_Scan\" or rule.name: \"Scan::Address_Scan\")", - "risk_score": 50, - "rule_id": "9d320fca-4ec1-4511-bdbc-7edf9673c07d", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_scanport_scan.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_scanport_scan.json deleted file mode 100644 index 1334f2c08ad09f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_scanport_scan.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Port scans detect that an attacking host appears to be scanning a single victim host on several ports.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Scan::Port_Scan", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Scan::Port_Scan\" or rule.name: \"Scan::Port_Scan\")", - "risk_score": 50, - "rule_id": "d09fbf7a-47a7-4130-8dd7-b386cca81a42", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturescount_signature.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturescount_signature.json deleted file mode 100644 index 1dc25388dc688f..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturescount_signature.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "The same signature has triggered multiple times for a host.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Signatures::Count_Signature", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Signatures::Count_Signature\" or rule.name: \"Signatures::Count_Signature\")", - "risk_score": 50, - "rule_id": "a704589c-8ba9-4a3c-8e39-ab9360cade17", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturesmultiple_sig_responders.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturesmultiple_sig_responders.json deleted file mode 100644 index 06cf39c1c3dbdd..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturesmultiple_sig_responders.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Host has triggered the same signature on multiple hosts.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Signatures::Multiple_Sig_Responders", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Signatures::Multiple_Sig_Responders\" or rule.name: \"Signatures::Multiple_Sig_Responders\")", - "risk_score": 50, - "rule_id": "4f313ae8-cbc6-4082-9599-526f8ccb7303", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturesmultiple_signatures.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturesmultiple_signatures.json deleted file mode 100644 index 350e6dfc30e187..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturesmultiple_signatures.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Host has triggered many signatures on the same host.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Signatures::Multiple_Signatures", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Signatures::Multiple_Signatures\" or rule.name: \"Signatures::Multiple_Signatures\")", - "risk_score": 50, - "rule_id": "ab90d81c-79e1-4f62-a61e-484c4bedb2b0", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturessensitive_signature.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturessensitive_signature.json deleted file mode 100644 index c1438edf2e4acf..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturessensitive_signature.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Generic notice type for notice-worthy signature matches.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Signatures::Sensitive_Signature", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Signatures::Sensitive_Signature\" or rule.name: \"Signatures::Sensitive_Signature\")", - "risk_score": 50, - "rule_id": "ac394dec-67e8-417f-bb06-ae0bd75556b0", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturessignature_summary.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturessignature_summary.json deleted file mode 100644 index 7fd878ceb6c7f8..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_signaturessignature_summary.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Summarize the number of times a host triggered a signature.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Signatures::Signature_Summary", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Signatures::Signature_Summary\" or rule.name: \"Signatures::Signature_Summary\")", - "risk_score": 50, - "rule_id": "d17fe857-eb67-4843-ab63-bf4852e49396", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpblocklist_blocked_host.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpblocklist_blocked_host.json deleted file mode 100644 index 1e2579dfd1b4ec..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpblocklist_blocked_host.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "The originator’s address is seen in the block list error message. This is useful to detect local hosts sending SPAM with a high positive rate.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SMTP::Blocklist_Blocked_Host", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SMTP::Blocklist_Blocked_Host\" or rule.name: \"SMTP::Blocklist_Blocked_Host\")", - "risk_score": 50, - "rule_id": "402d5f78-82cd-4320-8b69-3185e44daf07", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpblocklist_error_message.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpblocklist_error_message.json deleted file mode 100644 index ae4794bd5481f4..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpblocklist_error_message.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "An SMTP server sent a reply mentioning an SMTP block list.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SMTP::Blocklist_Error_Message", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SMTP::Blocklist_Error_Message\" or rule.name: \"SMTP::Blocklist_Error_Message\")", - "risk_score": 50, - "rule_id": "b9bb4a93-8c5c-4942-9193-e2dc97230034", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpsuspicious_origination.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpsuspicious_origination.json deleted file mode 100644 index ed871f4aa68986..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_smtpsuspicious_origination.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "SMTP message orignated from country or network configured to be suspicious.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SMTP::Suspicious_Origination", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SMTP::Suspicious_Origination\" or rule.name: \"SMTP::Suspicious_Origination\")", - "risk_score": 50, - "rule_id": "cc6e9fef-d936-4faf-8936-e576c089d8b2", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_softwaresoftware_version_change.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_softwaresoftware_version_change.json deleted file mode 100644 index 5a5cd3f48245f9..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_softwaresoftware_version_change.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that an interesting software application changed versions on a host.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Software::Software_Version_Change", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Software::Software_Version_Change\" or rule.name: \"Software::Software_Version_Change\")", - "risk_score": 50, - "rule_id": "ea1d2c1b-ecfe-42a5-bd0b-56c7a1bd8075", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_softwarevulnerable_version.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_softwarevulnerable_version.json deleted file mode 100644 index 8addd5ed395624..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_softwarevulnerable_version.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a vulnerable version of software was detected.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Software::Vulnerable_Version", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Software::Vulnerable_Version\" or rule.name: \"Software::Vulnerable_Version\")", - "risk_score": 50, - "rule_id": "97b4d80c-7671-4301-85a6-954aa0ba96ce", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshinteresting_hostname_login.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshinteresting_hostname_login.json deleted file mode 100644 index f69ab099bf6d98..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshinteresting_hostname_login.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Generated if a login originates or responds with a host where the reverse hostname lookup resolves to a name matched by the SSH::interesting_hostnames regular expression.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSH::Interesting_Hostname_Login", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSH::Interesting_Hostname_Login\" or rule.name: \"SSH::Interesting_Hostname_Login\")", - "risk_score": 50, - "rule_id": "6a7f2b0a-3f24-4d58-aa84-243f1f0556d9", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshlogin_by_password_guesser.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshlogin_by_password_guesser.json deleted file mode 100644 index 3b12aae2f4dd8a..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshlogin_by_password_guesser.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a host previously identified as a \"password guesser\" has now had a successful login attempt.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSH::Login_By_Password_Guesser", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSH::Login_By_Password_Guesser\" or rule.name: \"SSH::Login_By_Password_Guesser\")", - "risk_score": 50, - "rule_id": "5600ad95-2244-43db-8a7d-77eea95f80db", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshpassword_guessing.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshpassword_guessing.json deleted file mode 100644 index 4fd7e8ec15ed70..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshpassword_guessing.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a host has been identified as crossing the SSH::password_guesses_limit threshold with failed logins.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSH::Password_Guessing", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSH::Password_Guessing\" or rule.name: \"SSH::Password_Guessing\")", - "risk_score": 50, - "rule_id": "e278142a-4ee7-4443-9b1f-421174b0dabf", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshwatched_country_login.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshwatched_country_login.json deleted file mode 100644 index ecd57510441ae0..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sshwatched_country_login.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "SSH login was seen to or from a \"watched\" country based on the SSH::watched_countries variable", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSH::Watched_Country_Login", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSH::Watched_Country_Login\" or rule.name: \"SSH::Watched_Country_Login\")", - "risk_score": 50, - "rule_id": "983f4b7e-38cd-4d7f-8be6-40447431561e", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_expired.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_expired.json deleted file mode 100644 index 0309896ed31eea..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_expired.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a certificate’s NotValidAfter date has lapsed and the certificate is now invalid.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSL::Certificate_Expired", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSL::Certificate_Expired\" or rule.name: \"SSL::Certificate_Expired\")", - "risk_score": 50, - "rule_id": "3981f48e-49a5-4a3e-9b44-900a0887526c", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_expires_soon.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_expires_soon.json deleted file mode 100644 index 8f76bdab1a7ea3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_expires_soon.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a certificate is going to expire within SSL::notify_when_cert_expiring_in.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSL::Certificate_Expires_Soon", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSL::Certificate_Expires_Soon\" or rule.name: \"SSL::Certificate_Expires_Soon\")", - "risk_score": 50, - "rule_id": "e8207172-3478-4b2c-85b7-6f13d97fff43", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_not_valid_yet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_not_valid_yet.json deleted file mode 100644 index 785ba45744022c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslcertificate_not_valid_yet.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a certificate’s NotValidBefore date is future dated.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSL::Certificate_Not_Valid_Yet", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSL::Certificate_Not_Valid_Yet\" or rule.name: \"SSL::Certificate_Not_Valid_Yet\")", - "risk_score": 50, - "rule_id": "45586490-99f6-4e11-8228-2229d727a3b4", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslinvalid_ocsp_response.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslinvalid_ocsp_response.json deleted file mode 100644 index 3704a1be0cd269..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslinvalid_ocsp_response.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "This indicates that the OCSP response was not deemed to be valid.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSL::Invalid_Ocsp_Response", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSL::Invalid_Ocsp_Response\" or rule.name: \"SSL::Invalid_Ocsp_Response\")", - "risk_score": 50, - "rule_id": "eb17fcbb-de22-4aa0-81aa-1c059bdd4f2b", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslinvalid_server_cert.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslinvalid_server_cert.json deleted file mode 100644 index c068a3ecf0d82c..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslinvalid_server_cert.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "This notice indicates that the result of validating the certificate along with its full certificate chain was invalid.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSL::Invalid_Server_Cert", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSL::Invalid_Server_Cert\" or rule.name: \"SSL::Invalid_Server_Cert\")", - "risk_score": 50, - "rule_id": "13f51fe0-fc74-4c45-90f3-6fb1cd26ec66", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslold_version.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslold_version.json deleted file mode 100644 index 8d180115eadeac..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslold_version.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a server is using a potentially unsafe version", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSL::Old_Version", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSL::Old_Version\" or rule.name: \"SSL::Old_Version\")", - "risk_score": 50, - "rule_id": "260b680e-c3d6-4c03-90cd-03c86e9f8ec1", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslweak_cipher.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslweak_cipher.json deleted file mode 100644 index 602445d1463fe3..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslweak_cipher.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a server is using a potentially unsafe cipher", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSL::Weak_Cipher", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSL::Weak_Cipher\" or rule.name: \"SSL::Weak_Cipher\")", - "risk_score": 50, - "rule_id": "25886074-6ae1-41c0-8546-e8cf55ed1b4b", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslweak_key.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslweak_key.json deleted file mode 100644 index b88752e9b8c945..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_sslweak_key.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a server is using a potentially unsafe key.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice SSL::Weak_Key", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"SSL::Weak_Key\" or rule.name: \"SSL::Weak_Key\")", - "risk_score": 50, - "rule_id": "e020f504-c0e5-4768-8e1f-1e2ec7bac961", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_teamcymrumalwarehashregistrymatch.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_teamcymrumalwarehashregistrymatch.json deleted file mode 100644 index 8a36b974dc4fc6..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_teamcymrumalwarehashregistrymatch.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "The hash value of a file transferred over HTTP matched in the malware hash registry.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice TeamCymruMalwareHashRegistry::Match", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"TeamCymruMalwareHashRegistry::Match\" or rule.name: \"TeamCymruMalwareHashRegistry::Match\")", - "risk_score": 50, - "rule_id": "a130a0ba-b083-4630-b0ea-cceb80d7720b", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_traceroutedetected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_traceroutedetected.json deleted file mode 100644 index ec05000118f35d..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_traceroutedetected.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Indicates that a host was seen running traceroutes.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Traceroute::Detected", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Traceroute::Detected\" or rule.name: \"Traceroute::Detected\")", - "risk_score": 50, - "rule_id": "aeefe077-f05d-44a7-b757-272fc51c334c", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_weirdactivity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_weirdactivity.json deleted file mode 100644 index dcc5dfcf124ca0..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/zeek_notice_weirdactivity.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Generic unusual but notice-worthy weird activity.", - "enabled": false, - "filters": [], - "from": "now-6m", - "immutable": true, - "interval": "5m", - "language": "kuery", - "name": "Zeek Notice Weird::Activity", - "query": "event.module: zeek and event.dataset: zeek.notice and (zeek.notice.note: \"Weird::Activity\" or rule.name: \"Weird::Activity\")", - "risk_score": 50, - "rule_id": "d5ad39d0-8421-4f79-ad93-8ddbf7f553b3", - "severity": "low", - "to": "now", - "type": "query", - "version": 1 -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.ts index e8fa0b562bd24e..e8e883701c6a94 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Alert } from '../../../../../alerting/server/types'; +import { SanitizedAlert } from '../../../../../alerting/common'; import { INTERNAL_RULE_ID_KEY } from '../../../../common/constants'; import { findRules } from './find_rules'; import { ReadRuleParams, isAlertType } from './types'; @@ -21,7 +21,7 @@ export const readRules = async ({ alertsClient, id, ruleId, -}: ReadRuleParams): Promise => { +}: ReadRuleParams): Promise => { if (id != null) { try { const rule = await alertsClient.get({ id }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts index e238e6398845cd..7b38794467df54 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts @@ -15,7 +15,7 @@ import { } from 'kibana/server'; import { SIGNALS_ID } from '../../../../common/constants'; import { AlertsClient } from '../../../../../alerting/server/alerts_client'; -import { ActionsClient } from '../../../../../actions/server/actions_client'; +import { ActionsClient } from '../../../../../../../plugins/actions/server'; import { RuleAlertParams, RuleTypeParams, RuleAlertParamsRest } from '../types'; import { RequestFacade } from '../../../types'; import { Alert } from '../../../../../alerting/server/types'; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_prepacked_rules.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_prepacked_rules.ts index 0d7fb7918b67e6..a169e5107c316c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_prepacked_rules.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_prepacked_rules.ts @@ -5,7 +5,7 @@ */ import { SavedObjectsClientContract } from 'kibana/server'; -import { ActionsClient } from '../../../../../actions'; +import { ActionsClient } from '../../../../../../../plugins/actions/server'; import { AlertsClient } from '../../../../../alerting'; import { updateRules } from './update_rules'; import { PrepackagedRules } from '../types'; @@ -38,7 +38,7 @@ export const updatePrepackagedRules = async ( tags, to, type, - threats, + threat, references, version, } = rule; @@ -70,7 +70,7 @@ export const updatePrepackagedRules = async ( tags, to, type, - threats, + threat, references, version, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_rules.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_rules.test.ts index c079c637d88b7a..0d426fb03bd378 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_rules.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_rules.test.ts @@ -5,6 +5,7 @@ */ import { calculateInterval, calculateName, calculateVersion } from './update_rules'; +import { UpdateRuleParams } from './types'; describe('update_rules', () => { describe('#calculateInterval', () => { @@ -25,20 +26,26 @@ describe('update_rules', () => { }); describe('#calculateVersion', () => { - test('given preVersion and nextVersion numbers being null it will return a 1', () => { - expect(calculateVersion(null, null)).toEqual(1); + test('returning the same version number if given an immutable but no updated version number', () => { + expect(calculateVersion(true, 1, { description: 'some description change' })).toEqual(1); }); - test('given preVersion and nextVersion numbers being undefined it will return a 1', () => { - expect(calculateVersion(undefined, undefined)).toEqual(1); + test('returning an updated version number if given an immutable and an updated version number', () => { + expect(calculateVersion(true, 2, { description: 'some description change' })).toEqual(2); }); - test('given prevVersion as null and nextVersion being defined, nextVersion will be returned', () => { - expect(calculateVersion(undefined, 5)).toEqual(5); + test('returning an updated version number if not given an immutable but but an updated description', () => { + expect(calculateVersion(false, 1, { description: 'some description change' })).toEqual(2); }); - test('given prevVersion as being defined but nextVersion is not, prevVersion will be incremented by 1', () => { - expect(calculateVersion(5, undefined)).toEqual(6); + test('returning the same version number but a undefined description', () => { + expect(calculateVersion(false, 1, { description: undefined })).toEqual(1); + }); + + test('returning an updated version number if not given an immutable but an updated falsy value', () => { + expect( + calculateVersion(false, 1, ({ description: false } as unknown) as UpdateRuleParams) + ).toEqual(2); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_rules.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_rules.ts index e2632791f859e3..e37e899c7de51d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_rules.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/update_rules.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { defaults } from 'lodash/fp'; -import { AlertAction, IntervalSchedule } from '../../../../../alerting/server/types'; +import { defaults, pickBy, isEmpty } from 'lodash/fp'; import { readRules } from './read_rules'; import { UpdateRuleParams, IRuleSavedAttributesSavedObjectAttributes } from './types'; import { addTags } from './add_tags'; @@ -25,23 +24,37 @@ export const calculateInterval = ( }; export const calculateVersion = ( - prevVersion: number | null | undefined, - nextVersion: number | null | undefined -) => { - if (nextVersion == null) { - if (prevVersion != null) { - return prevVersion + 1; + immutable: boolean, + currentVersion: number, + updateProperties: Partial> +): number => { + // early return if we are pre-packaged/immutable rule to be safe. We are never responsible + // for changing the version number of an immutable. Immutables are only responsible for changing + // their own version number. This would be really bad if an immutable version number is bumped by us + // due to a bug, hence the extra check and early bail if that is detected. + if (immutable === true) { + if (updateProperties.version != null) { + // we are an immutable rule but we are asking to update the version number so go ahead + // and update it to what is asked. + return updateProperties.version; } else { - // really should never hit this code but to just be - // safe let us always check the prev version and if - // its null or undefined return a 1 - return 1; + // we are immutable and not asking to update the version number so return the existing version + return currentVersion; } + } + + // white list all properties but the enabled/disabled flag. We don't want to auto-increment + // the version number if only the enabled/disabled flag is being set. Likewise if we get other + // properties we are not expecting such as updatedAt we do not to cause a version number bump + // on that either. + const removedNullValues = pickBy( + (value: unknown) => value != null, + updateProperties + ); + if (isEmpty(removedNullValues)) { + return currentVersion; } else { - // The user wants to custom update their version number which - // means this could be in the past. Up to the user if they want - // to do this - return nextVersion; + return currentVersion + 1; } }; @@ -90,7 +103,7 @@ export const updateRules = async ({ name, severity, tags, - threats, + threat, to, type, references, @@ -101,15 +114,35 @@ export const updateRules = async ({ return null; } - // TODO: Remove this as cast as soon as rule.actions TypeScript bug is fixed - // where it is trying to return AlertAction[] or RawAlertAction[] - const actions = (rule.actions as AlertAction[] | undefined) || []; - - const params = rule.params || {}; + const calculatedVersion = calculateVersion(rule.params.immutable, rule.params.version, { + description, + falsePositives, + query, + language, + outputIndex, + savedId, + timelineId, + timelineTitle, + meta, + filters, + from, + index, + interval, + maxSignals, + riskScore, + name, + severity, + tags, + threat, + to, + type, + references, + version, + }); const nextParams = defaults( { - ...params, + ...rule.params, }, { description, @@ -128,40 +161,29 @@ export const updateRules = async ({ maxSignals, riskScore, severity, - threats, + threat, to, type, updatedAt: new Date().toISOString(), references, - version: calculateVersion(rule.params.version, version), + version: calculatedVersion, } ); - const ruleCurrentStatus = savedObjectsClient - ? await savedObjectsClient.find({ - type: ruleStatusSavedObjectType, - perPage: 1, - sortField: 'statusDate', - sortOrder: 'desc', - search: rule.id, - searchFields: ['alertId'], - }) - : null; - if (rule.enabled && enabled === false) { await alertsClient.disable({ id: rule.id }); - // set current status for this rule to null to represent disabled, - // but keep last_success_at / last_failure_at properties intact for - // use on frontend while rule is disabled. - if (ruleCurrentStatus && ruleCurrentStatus.saved_objects.length > 0) { - const currentStatusToDisable = ruleCurrentStatus.saved_objects[0]; - currentStatusToDisable.attributes.status = null; - await savedObjectsClient?.update(ruleStatusSavedObjectType, currentStatusToDisable.id, { - ...currentStatusToDisable.attributes, - }); - } } else if (!rule.enabled && enabled === true) { await alertsClient.enable({ id: rule.id }); + const ruleCurrentStatus = savedObjectsClient + ? await savedObjectsClient.find({ + type: ruleStatusSavedObjectType, + perPage: 1, + sortField: 'statusDate', + sortOrder: 'desc', + search: rule.id, + searchFields: ['alertId'], + }) + : null; // set current status for this rule to be 'going to run' if (ruleCurrentStatus && ruleCurrentStatus.saved_objects.length > 0) { const currentStatusToDisable = ruleCurrentStatus.saved_objects[0]; @@ -173,27 +195,19 @@ export const updateRules = async ({ } else { // enabled is null or undefined and we do not touch the rule } - return alertsClient.update({ id: rule.id, data: { tags: addTags( - tags, + tags != null ? tags : rule.tags, // Add tags as an update if it exists, otherwise re-use the older tags rule.params.ruleId, immutable != null ? immutable : rule.params.immutable // Add new one if it exists, otherwise re-use old one ), name: calculateName({ updatedName: name, originalName: rule.name }), schedule: { - interval: calculateInterval( - interval, - // TODO: we assume the schedule is an interval schedule due to a problem - // in the Alerting api, which should be addressed by the following - // issue: https://github.com/elastic/kibana/issues/49703 - // Once this issue is closed, the type should be correctly returned by alerting - (rule.schedule as IntervalSchedule).interval - ), + interval: calculateInterval(interval, rule.schedule.interval), }, - actions, + actions: rule.actions, params: nextParams, }, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/import/multiple_ruleid_queries.ndjson b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/import/multiple_ruleid_queries.ndjson index a9de8b1e475a36..e395916363ab6b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/import/multiple_ruleid_queries.ndjson +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/import/multiple_ruleid_queries.ndjson @@ -1,3 +1,3 @@ -{"created_at":"2020-01-09T01:38:00.740Z","updated_at":"2020-01-09T01:38:00.740Z","created_by":"elastic_kibana","description":"Query with a rule_id that acts like an external id","enabled":true,"false_positives":[],"from":"now-6m","id":"6688f367-1aa2-4895-a5a8-b3701eecf57d","immutable":false,"interval":"5m","rule_id":"query-rule-id-1","language":"kuery","output_index":".siem-signals-frank-hassanabad-default","max_signals":100,"risk_score":1,"name":"Query with a rule id Number 1","query":"user.name: root or user.name: admin","references":[],"severity":"high","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threats":[],"version":1} -{"created_at":"2020-01-09T01:38:00.745Z","updated_at":"2020-01-09T01:38:00.745Z","created_by":"elastic_kibana","description":"Query with a rule_id that acts like an external id","enabled":true,"false_positives":[],"from":"now-6m","id":"7a912444-6cfa-4c8f-83f4-2b26fb2a2ed9","immutable":false,"interval":"5m","rule_id":"query-rule-id-2","language":"kuery","output_index":".siem-signals-frank-hassanabad-default","max_signals":100,"risk_score":2,"name":"Query with a rule id Number 2","query":"user.name: root or user.name: admin","references":[],"severity":"low","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threats":[],"version":1} +{"created_at":"2020-01-09T01:38:00.740Z","updated_at":"2020-01-09T01:38:00.740Z","created_by":"elastic_kibana","description":"Query with a rule_id that acts like an external id","enabled":true,"false_positives":[],"from":"now-6m","id":"6688f367-1aa2-4895-a5a8-b3701eecf57d","immutable":false,"interval":"5m","rule_id":"query-rule-id-1","language":"kuery","output_index":".siem-signals-frank-default","max_signals":100,"risk_score":1,"name":"Query with a rule id Number 1","query":"user.name: root or user.name: admin","references":[],"severity":"high","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threat":[],"version":1} +{"created_at":"2020-01-09T01:38:00.745Z","updated_at":"2020-01-09T01:38:00.745Z","created_by":"elastic_kibana","description":"Query with a rule_id that acts like an external id","enabled":true,"false_positives":[],"from":"now-6m","id":"7a912444-6cfa-4c8f-83f4-2b26fb2a2ed9","immutable":false,"interval":"5m","rule_id":"query-rule-id-2","language":"kuery","output_index":".siem-signals-frank-default","max_signals":100,"risk_score":2,"name":"Query with a rule id Number 2","query":"user.name: root or user.name: admin","references":[],"severity":"low","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threat":[],"version":1} {"exported_count":2,"missing_rules":[],"missing_rules_count":0} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_disabled.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_disabled.json index 38b3ed9f746967..f354351caa5f0d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_disabled.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_disabled.json @@ -4,8 +4,6 @@ "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin", "enabled": false } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_immutable.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_immutable.json deleted file mode 100644 index 681d66e16d0ba0..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_immutable.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "Query which is immutable", - "description": "Example query which is immutable", - "risk_score": 1, - "severity": "high", - "type": "query", - "from": "now-6m", - "to": "now", - "query": "user.name: root or user.name: admin", - "immutable": true -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_lucene.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_lucene.json index ed8849831a4793..03d5ab3c0b4e94 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_lucene.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_lucene.json @@ -4,8 +4,6 @@ "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin", "language": "lucene" } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_mitre_attack.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_mitre_attack.json index 721a172ce55d75..fec582ce772955 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_mitre_attack.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_mitre_attack.json @@ -1,13 +1,11 @@ { "name": "Query which has Mitre Attack Data", - "description": "Example query which has Mitre Attack Data as threats", + "description": "Example query which has Mitre Attack Data as threat", "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin", - "threats": [ + "threat": [ { "framework": "MITRE ATT&CK", "tactic": { @@ -15,7 +13,7 @@ "name": "impact", "reference": "https://attack.mitre.org/tactics/TA0040/" }, - "techniques": [ + "technique": [ { "id": "T1499", "name": "endpoint denial of service", @@ -30,7 +28,7 @@ "name": "Automated Exfiltration", "reference": "https://attack.mitre.org/techniques/T1020/" }, - "techniques": [ + "technique": [ { "id": "T1002", "name": "Data Compressed", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_timelineid.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_timelineid.json index eb87a14e0c6885..2bc4aa22759268 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_timelineid.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_timelineid.json @@ -4,8 +4,6 @@ "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin", "timeline_id": "timeline-id", "timeline_title": "timeline_title" diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_everything.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_everything.json index 4a90d904f31aba..082dd5205a142d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_everything.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_everything.json @@ -40,7 +40,7 @@ "from": "now-6m", "severity": "high", "type": "query", - "threats": [ + "threat": [ { "framework": "MITRE ATT&CK", "tactic": { @@ -48,7 +48,7 @@ "name": "impact", "reference": "https://attack.mitre.org/tactics/TA0040/" }, - "techniques": [ + "technique": [ { "id": "T1499", "name": "endpoint denial of service", @@ -63,7 +63,7 @@ "name": "Some other name", "reference": "https://example.com" }, - "techniques": [ + "technique": [ { "id": "some-other-id", "name": "some other technique name", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_filter.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_filter.json index c754ab73ea21e8..28ae121c7969ae 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_filter.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_filter.json @@ -5,8 +5,6 @@ "risk_score": 15, "severity": "high", "type": "query", - "from": "now-24h", - "to": "now", "query": "user.name: root or user.name: admin", "filters": [ { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_meta_data.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_meta_data.json index f9f5bf854e45c1..8d86605d648ec6 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_meta_data.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_meta_data.json @@ -4,8 +4,6 @@ "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin", "meta": { "whatever-you-want": { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_rule_id.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_rule_id.json index e4da1960075275..3347fb0e724b31 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_rule_id.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_rule_id.json @@ -5,7 +5,5 @@ "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin" } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_tags.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_tags.json index 954f5942180d66..2c61f08d4b480d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_tags.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_tags.json @@ -5,8 +5,6 @@ "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin", "tags": ["tag_1", "tag_2"] } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/simplest_filters.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/simplest_filters.json index 61e68f886ffe72..37f0e541298b27 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/simplest_filters.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/simplest_filters.json @@ -4,8 +4,6 @@ "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "filters": [ { "query": { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/simplest_query.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/simplest_query.json index e812b031a28fd0..407fa1dcc08847 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/simplest_query.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/simplest_query.json @@ -4,7 +4,5 @@ "risk_score": 1, "severity": "high", "type": "query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin" } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_by_rule_id.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_by_rule_id.json index 0e0be24c00207c..48b6a34cf2316b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_by_rule_id.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_by_rule_id.json @@ -5,7 +5,5 @@ "risk_score": 5, "severity": "high", "type": "saved_query", - "from": "now-6m", - "to": "now", "saved_id": "test-saved-id" } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_everything.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_everything.json index 2b7dbc8cccf0e5..9d8b0d6b4922dc 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_everything.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_everything.json @@ -40,7 +40,7 @@ "from": "now-6m", "severity": "high", "type": "saved_query", - "threats": [ + "threat": [ { "framework": "MITRE ATT&CK", "tactic": { @@ -48,7 +48,7 @@ "name": "impact", "reference": "https://attack.mitre.org/tactics/TA0040/" }, - "techniques": [ + "technique": [ { "id": "T1499", "name": "endpoint denial of service", @@ -63,7 +63,7 @@ "name": "Some other name", "reference": "https://example.com" }, - "techniques": [ + "technique": [ { "id": "some-other-id", "name": "some other technique name", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_filters.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_filters.json index 55f95e9644b8b3..2bb9845a507c3e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_filters.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_filters.json @@ -4,8 +4,6 @@ "risk_score": 1, "severity": "high", "type": "saved_query", - "from": "now-6m", - "to": "now", "filters": [ { "query": { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_query.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_query.json index ee37c4cb784d1a..786dcdb377a684 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_query.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_query.json @@ -4,8 +4,6 @@ "risk_score": 1, "severity": "high", "type": "saved_query", - "from": "now-6m", - "to": "now", "query": "user.name: root or user.name: admin", "saved_id": "test-saved-id" } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_query_filter.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_query_filter.json index 19801e7a98ac20..5e5c51d2243b00 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_query_filter.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/saved_query_with_query_filter.json @@ -5,8 +5,6 @@ "risk_score": 15, "severity": "high", "type": "query", - "from": "now-24h", - "to": "now", "query": "user.name: root or user.name: admin", "filters": [ { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/simplest_saved_query.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/simplest_saved_query.json index a3dbf0f1b09af6..ac9f224313b232 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/simplest_saved_query.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/saved_queries/simplest_saved_query.json @@ -4,7 +4,5 @@ "risk_score": 5, "severity": "high", "type": "saved_query", - "from": "now-6m", - "to": "now", "saved_id": "test-saved-id" } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/README.md b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/README.md index 8b6508c64dc5c5..38139f783c245d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/README.md +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/README.md @@ -4,15 +4,3 @@ use these type of rule based messages when writing pure REST API calls. These me more of what you would see "behind the scenes" when you are using Kibana UI which can create rules with additional "meta" data or other implementation details that aren't really a concern for a regular REST API user. - -To post all of them to see in the UI, with the scripts folder as your current working directory: - -```sh -./post_rule.sh ./rules/test_cases/*.json -``` - -To post only one at a time: - -```sh -./post_rule.sh ./rules/test_cases/.json -``` diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/imports/multiple_ruleid_queries_corrupted.ndjson b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/imports/multiple_ruleid_queries_corrupted.ndjson new file mode 100644 index 00000000000000..31acaa5bd9803f --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/imports/multiple_ruleid_queries_corrupted.ndjson @@ -0,0 +1,4 @@ +{"created_at":"2020-01-09T01:38:00.740Z","updated_at":"2020-01-09T01:38:00.740Z","created_by":"elastic_kibana","description":"Query with a rule_id that acts like an external id","enabled":true,"false_positives":[],"from":"now-6m","id":"6688f367-1aa2-4895-a5a8-b3701eecf57d","immutable":false,"interval":"5m","rule_id":"query-rule-id-1","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":1,"name":"Query with a rule id Number 1","query":"user.name: root or user.name: admin","references":[],"severity":"high","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threat":[],"version":1}, +{"created_at":"2020-01-09T01:38:00.745Z","updated_at":"2020-01-09T01:38:00.745Z","created_by":"elastic_kibana","enabled":true,"false_positives":[],"from":"now-6m","id":"7a912444-6cfa-4c8f-83f4-2b26fb2a2ed9","immutable":false,"interval":"5m","rule_id":"query-rule-id-2","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":2,"name":"Query with a rule id Number 2","query":"user.name: root or user.name: admin","references":[],"severity":"low","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threat":[],"version":1} +{"created_at":"2020-01-09T01:38:00.745Z","updated_at":"2020-01-09T01:38:00.745Z","created_by":"elastic_kibana","description":"Query with a rule_id that acts like an external id","enabled":true,"false_positives":[],"from":"now-6m","id":"7a912444-6cfa-4c8f-83f4-2b26fb2a2ed9","immutable":false,"interval":"5m","rule_id":"query-rule-id-3","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":2,"name":"Query with a rule id Number 2","query":"user.name: root or user.name: admin","references":[],"severity":"low","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threat":[],"version":1} +{"exported_count":2,"missing_rules":[],"missing_rules_count":0} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/multiple_ruleid_queries_corrupted.ndjson b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/multiple_ruleid_queries_corrupted.ndjson deleted file mode 100644 index 94fc36ef6f7bfa..00000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/multiple_ruleid_queries_corrupted.ndjson +++ /dev/null @@ -1,4 +0,0 @@ -{"created_at":"2020-01-09T01:38:00.740Z","updated_at":"2020-01-09T01:38:00.740Z","created_by":"elastic_kibana","description":"Query with a rule_id that acts like an external id","enabled":true,"false_positives":[],"from":"now-6m","id":"6688f367-1aa2-4895-a5a8-b3701eecf57d","immutable":false,"interval":"5m","rule_id":"query-rule-id-1","language":"kuery","output_index":".siem-signals-frank-hassanabad-default","max_signals":100,"risk_score":1,"name":"Query with a rule id Number 1","query":"user.name: root or user.name: admin","references":[],"severity":"high","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threats":[],"version":1}, -{"created_at":"2020-01-09T01:38:00.745Z","updated_at":"2020-01-09T01:38:00.745Z","created_by":"elastic_kibana","enabled":true,"false_positives":[],"from":"now-6m","id":"7a912444-6cfa-4c8f-83f4-2b26fb2a2ed9","immutable":false,"interval":"5m","rule_id":"query-rule-id-2","language":"kuery","output_index":".siem-signals-frank-hassanabad-default","max_signals":100,"risk_score":2,"name":"Query with a rule id Number 2","query":"user.name: root or user.name: admin","references":[],"severity":"low","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threats":[],"version":1} -{"created_at":"2020-01-09T01:38:00.745Z","updated_at":"2020-01-09T01:38:00.745Z","created_by":"elastic_kibana","description":"Query with a rule_id that acts like an external id","enabled":true,"false_positives":[],"from":"now-6m","id":"7a912444-6cfa-4c8f-83f4-2b26fb2a2ed9","immutable":false,"interval":"5m","rule_id":"query-rule-id-3","language":"kuery","output_index":".siem-signals-frank-hassanabad-default","max_signals":100,"risk_score":2,"name":"Query with a rule id Number 2","query":"user.name: root or user.name: admin","references":[],"severity":"low","updated_by":"elastic_kibana","tags":[],"to":"now","type":"query","threats":[],"version":1} -{"exported_count":2,"missing_rules":[],"missing_rules_count":0} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/filter_with_empty_query.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/filter_with_empty_query.json similarity index 100% rename from x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/filter_with_empty_query.json rename to x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/filter_with_empty_query.json diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/filter_without_query.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/filter_without_query.json similarity index 100% rename from x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/filter_without_query.json rename to x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/filter_without_query.json diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/query_filter_ui_meatadata_lucene.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/query_filter_ui_meatadata_lucene.json similarity index 100% rename from x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/query_filter_ui_meatadata_lucene.json rename to x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/query_filter_ui_meatadata_lucene.json diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/query_filter_ui_metadata.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/query_filter_ui_metadata.json similarity index 100% rename from x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/query_filter_ui_metadata.json rename to x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/query_filter_ui_metadata.json diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/query_with_errors.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/query_with_errors.json similarity index 100% rename from x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/query_with_errors.json rename to x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/query_with_errors.json diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/saved_query_ui_meta_empty_query.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/saved_query_ui_meta_empty_query.json similarity index 100% rename from x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/saved_query_ui_meta_empty_query.json rename to x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/queries/saved_query_ui_meta_empty_query.json diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/README.md b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/README.md new file mode 100644 index 00000000000000..2310ba979da202 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/README.md @@ -0,0 +1,367 @@ +This is a depth test which allows users and UI's to create "funnels" of information. You can funnel your data into smaller +and smaller data sets using this. For example, you might have 1,000k of events but generate only 100k of signals off +of those events. However, you then want to generate signals on top of signals that are only 10k. Likewise you might want +signals on top of signals on top of signals to generate only 1k. + +``` +events from indexes might be 1,000k (no depth) +signals -> events would be less such as 100k +signals -> signals -> events would be even less (such as 10k) +signals -> signals -> events would be even less (such as 1k) +``` + +This folder contains a rule called + +```sh +query_single_id.json +``` + +which will write a single signal document into the signals index by searching for a single document `"query": "_id: o8G7vm8BvLT8jmu5B1-M"` . Then another rule called + +```sh +signal_on_signal_depth_1.json +``` + +which has this key part of its query: `"query": "signal.parent.depth: 1 and _id: *"` which will only create signals +from all signals that point directly to an event (signal -> event). + +Then a second rule called + +```sh +signal_on_signal_depth_2.json +``` + +which will only create signals from all signals that point directly to another signal (signal -> signal) with this query + +```json +"query": "signal.parent.depth: 2 and _id: *" +``` + +## Setup + +You should first get a valid `_id` from the system from the last 24 hours by running any query within timeline +or in the system and copying its `_id`. Once you have that `_id` add it to `query_single_id.json`. For example if you have found an `_id` +in the last 24 hours of `sQevtW8BvLT8jmu5l0TA` add it to `query_single_id.json` under the key `query` like so: + +```json +"query": "_id: sQevtW8BvLT8jmu5l0TA", +``` + +Then get your current signal index: + +```json +./get_signal_index.sh +{ + "name": ".siem-signals-default" +} +``` + +And edit the `signal_on_signal.json` and add that index to the key of `index` so we are running that rule against the signals index: + +```json +"index": ".siem-signals-default" +``` + +Next you want to clear out all of your signals and all rules: + +```sh +./hard_reset.sh +``` + +Finally, insert and start the first the query like so: + +```sh +./post_rule.sh ./rules/test_cases/signals_on_signals/depth_test/query_single_id.json +``` + +Wait 30+ seconds to ensure that the single record shows up in your signals index. You can use dev tools in Kibana +to see this by first getting your configured signals index by running: + +```ts +./get_signal_index.sh +{ + "name": ".siem-signals-default" +} +``` + +And then you can query against that: + +```ts +GET .siem-signals-default/_search +``` + +Check your parent section of the signal and you will see something like this: + +```json +"parent" : { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 +}, +"ancestors" : [ + { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + } +] +``` + +The parent and ancestors structure is defined as: + +``` +rule -> The id of the rule. You can view the rule by ./get_rule_by_rule_id.sh ded57b36-9c4e-4ee4-805d-be4e92033e41 +id -> The original _id of the document +type -> The type of the document, it will be either event or signal +index -> The original location of the index +depth -> The depth of this signal. It will be at least 1 to indicate it is a signal generated from a event. Otherwise 2 or more to indicate a signal on signal and what depth we are at +ancestors -> An array tracking all of the parents of this particular signal. As depth increases this will too. +``` + +This is indicating that you have a single parent of an event from the signal (signal -> event) and this document has a single +ancestor of that event. Each 30 seconds that goes it will use de-duplication technique to ensure that this signal is not re-inserted. If after +each 30 seconds you DO SEE multiple signals then the bug is a de-duplication bug and a critical bug. If you ever see a duplicate rule in the +ancestors array then that is another CRITICAL bug which needs to be fixed. + +After this is ensured, the next step is to run a single signal on top of a signal by posting once + +```sh +./post_rule.sh ./rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_1.json +``` + +Notice in `signal_on_signal_depth_1.json` we do NOT have a `rule_id` set. This is intentional and is to make it so we can test N rules +running in the system which are generating signals on top of signals. After 30 seconds have gone by you should see that you now have two +documents in the signals index. The first signal is our original (signal -> event) document with a rule id: + +```json +"parent" : { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 +}, +"ancestors" : [ + { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + } +] +``` + +and the second document is a signal on top of a signal like so: + +```json +"parent" : { + "rule" : "1d3b3735-66ef-4e53-b7f5-4340026cc40c", + "id" : "4cc69c1cbecdd2ace4075fd1d8a5c28e7d46e4bf31aecc8d2da39252c50c96b4", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 +}, +"ancestors" : [ + { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "1d3b3735-66ef-4e53-b7f5-4340026cc40c", + "id" : "4cc69c1cbecdd2ace4075fd1d8a5c28e7d46e4bf31aecc8d2da39252c50c96b4", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + } +] +``` + +Notice that the depth indicates it is at level 2 and its parent is that of a signal. Also notice that the ancestors is an array of size 2 +indicating that this signal terminates at an event. Each and every signal ancestors array should terminate at an event and should ONLY contain 1 +event and NEVER 2 or more events. After 30+ seconds you should NOT see any new documents being created and you should be stable +at 2. Otherwise we have AND/OR a de-duplication issue, signal on signal issue. + +Now, post this same rule a second time as a second instance which is going to run against these two documents. + +```sh +./post_rule.sh ./rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_1.json +``` + +If you were to look at the number of rules you have: + +```sh +./find_rules.sh +``` + +You should see that you have 3 rules running concurrently at this point. Write down the `id` to keep track of them + +- 1 event rule which is always finding the same event continuously (id: 74e0dd0c-4609-416f-b65e-90f8b2564612) +- 1 signal rule which is finding ALL signals at depth 1 (id: 1d3b3735-66ef-4e53-b7f5-4340026cc40c) +- 1 signal rule which is finding ALL signals at depth 1 (id: c93ddb57-e7e9-4973-9886-72ddefb4d22e) + +The expected behavior is that eventually you will get 3 total documents but not additional ones after 1+ minutes. These will be: + +The original event rule 74e0dd0c-4609-416f-b65e-90f8b2564612 (event -> signal) + +```json +"parent" : { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 +}, +"ancestors" : [ + { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + } +] +``` + +The first signal to signal rule 1d3b3735-66ef-4e53-b7f5-4340026cc40c (signal -> event) + +```json +"parent" : { + "rule" : "1d3b3735-66ef-4e53-b7f5-4340026cc40c", + "id" : "4cc69c1cbecdd2ace4075fd1d8a5c28e7d46e4bf31aecc8d2da39252c50c96b4", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 +}, +"ancestors" : [ + { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "1d3b3735-66ef-4e53-b7f5-4340026cc40c", + "id" : "4cc69c1cbecdd2ace4075fd1d8a5c28e7d46e4bf31aecc8d2da39252c50c96b4", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + } +] +``` + +Then our second signal to signal rule c93ddb57-e7e9-4973-9886-72ddefb4d22e (signal -> event) which finds the same thing as the first +signal to signal + +```json +"parent" : { + "rule" : "c93ddb57-e7e9-4973-9886-72ddefb4d22e", + "id" : "4cc69c1cbecdd2ace4075fd1d8a5c28e7d46e4bf31aecc8d2da39252c50c96b4", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 +}, +"ancestors" : [ + { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "c93ddb57-e7e9-4973-9886-72ddefb4d22e", + "id" : "4cc69c1cbecdd2ace4075fd1d8a5c28e7d46e4bf31aecc8d2da39252c50c96b4", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + } +] +``` + +We should be able to post this depth level as many times as we want and get only 1 new document each time. If we decide though to +post `signal_on_signal_depth_2.json` like so: + +```sh +./post_rule.sh ./rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_2.json +``` + +The expectation is that a document for each of the previous depth 1 documents would be produced. Since we have 2 instances of +depth 1 rules running then the signals at depth 2 will produce two new ones and those two will look like so: + +```json +"parent" : { + "rule" : "a1f7b520-5bfd-451d-af59-428f60753fee", + "id" : "365236ce5e77770508152403b4e16613f407ae4b1a135a450dcfec427f2a3231", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 3 +}, +"ancestors" : [ + { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "1d3b3735-66ef-4e53-b7f5-4340026cc40c", + "id" : "4cc69c1cbecdd2ace4075fd1d8a5c28e7d46e4bf31aecc8d2da39252c50c96b4", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + }, + { + "rule" : "a1f7b520-5bfd-451d-af59-428f60753fee", + "id" : "365236ce5e77770508152403b4e16613f407ae4b1a135a450dcfec427f2a3231", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 3 + } +] +``` + +```json +"parent" : { + "rule" : "a1f7b520-5bfd-451d-af59-428f60753fee", + "id" : "e8b1f1adb40fd642fa524dea89ef94232e67b05e99fb0b2683f1e47e90b759fb", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 3 +}, +"ancestors" : [ + { + "rule" : "74e0dd0c-4609-416f-b65e-90f8b2564612", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "c93ddb57-e7e9-4973-9886-72ddefb4d22e", + "id" : "4cc69c1cbecdd2ace4075fd1d8a5c28e7d46e4bf31aecc8d2da39252c50c96b4", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + }, + { + "rule" : "a1f7b520-5bfd-451d-af59-428f60753fee", + "id" : "e8b1f1adb40fd642fa524dea89ef94232e67b05e99fb0b2683f1e47e90b759fb", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 3 + } +] +``` + +The total number of documents should be 5 at this point. If you were to post this same rule a second time to get a second instance +running you will end up with 7 documents as it will only re-report the first 2 and not interfere with the other rules. diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/query_single_id.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/query_single_id.json new file mode 100644 index 00000000000000..dc05c656d7cf1f --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/query_single_id.json @@ -0,0 +1,12 @@ +{ + "name": "Queries single id", + "description": "Finds only one id below to create a single signal. Change the query to your exact _id you want to test with", + "risk_score": 1, + "severity": "high", + "type": "query", + "from": "now-1d", + "interval": "30s", + "to": "now", + "query": "_id: o8G7vm8BvLT8jmu5B1-M", + "enabled": true +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_1.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_1.json new file mode 100644 index 00000000000000..fb13413a02791b --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_1.json @@ -0,0 +1,13 @@ +{ + "name": "Signal on Signals Rule 1 Depth 1", + "description": "Example Signal on Signal where it reports everything as a signal at depth 1", + "risk_score": 1, + "severity": "high", + "type": "query", + "from": "now-1d", + "interval": "30s", + "to": "now", + "query": "signal.parent.depth: 1 and _id: *", + "enabled": true, + "index": ".siem-signals-default" +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_2.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_2.json new file mode 100644 index 00000000000000..c1b7594653ec73 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/depth_test/signal_on_signal_depth_2.json @@ -0,0 +1,13 @@ +{ + "name": "Signal on Signals Rule 1 Depth 2", + "description": "Example Signal on Signal where it reports everything as a signal at Depth 2", + "risk_score": 1, + "severity": "high", + "type": "query", + "from": "now-1d", + "interval": "30s", + "to": "now", + "query": "signal.parent.depth: 2 and _id: *", + "enabled": true, + "index": ".siem-signals-default" +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/README.md b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/README.md new file mode 100644 index 00000000000000..b1a83f5317776f --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/README.md @@ -0,0 +1,375 @@ +This test is to ensure that signals will "halt" eventually when they are run against themselves. This isn't how anyone should setup +signals on signals but rather how we will eventually "halt" given the worst case situations where users are running signals on top of signals +that are duplicates of each other and going very far back in time. + +It contains a rule called + +```sh +query_single_id.json +``` + +which will write a single signal document into the signals index by searching for a single document `"query": "_id: o8G7vm8BvLT8jmu5B1-M"` . Then another rule called + +```sh +signal_on_signal.json +``` + +which will always generate a signal for EVERY single document it sees `"query": "_id: *"` + +## Setup + +You should first get a valid `_id` from the system from the last 24 hours by running any query within timeline +or in the system and copying its `_id`. Once you have that `_id` add it to `query_single_id.json`. For example if you have found an `_id` +in the last 24 hours of `sQevtW8BvLT8jmu5l0TA` add it to `query_single_id.json` under the key `query` like so: + +```json +"query": "_id: sQevtW8BvLT8jmu5l0TA", +``` + +Then get your current signal index: + +```json +./get_signal_index.sh +{ + "name": ".siem-signals-default" +} +``` + +And edit the `signal_on_signal.json` and add that index to the key of `index` so we are running that rule against the signals index: + +```json +"index": ".siem-signals-default" +``` + +Next you want to clear out all of your signals and all rules: + +```sh +./hard_reset.sh +``` + +Finally, insert and start the first the query like so: + +```sh +./post_rule.sh ./rules/test_cases/signals_on_signals/halting_test/query_single_id.json +``` + +Wait 30+ seconds to ensure that the single record shows up in your signals index. You can use dev tools in Kibana +to see this by first getting your configured signals index by running: + +```ts +./get_signal_index.sh +{ + "name": ".siem-signals-default" +} +``` + +And then you can query against that: + +```ts +GET .siem-signals-default/_search +``` + +Check your parent section of the signal and you will see something like this: + +```json +"parent" : { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 +}, +"ancestors" : [ + { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + } +] +``` + +The parent and ancestors structure is defined as: + +``` +rule -> The id of the rule. You can view the rule by ./get_rule_by_rule_id.sh ded57b36-9c4e-4ee4-805d-be4e92033e41 +id -> The original _id of the document +type -> The type of the document, it will be either event or signal +index -> The original location of the index +depth -> The depth of this signal. It will be at least 1 to indicate it is a signal generated from a event. Otherwise 2 or more to indicate a signal on signal and what depth we are at +ancestors -> An array tracking all of the parents of this particular signal. As depth increases this will too. +``` + +This is indicating that you have a single parent of an event from the signal (signal -> event) and this document has a single +ancestor of that event. Each 30 seconds that goes it will use de-duplication technique to ensure that this signal is not re-inserted. If after +each 30 seconds you DO SEE multiple signals then the bug is a de-duplication bug and a critical bug. If you ever see a duplicate rule in the +ancestors array then that is another CRITICAL bug which needs to be fixed. + +After this is ensured, the next step is to run a single signal on top of a signal by posting once + +```sh +./post_rule.sh ./rules/test_cases/signals_on_signals/halting_test/signal_on_signal.json +``` + +Notice in `signal_on_signal.json` we do NOT have a `rule_id` set. This is intentional and is to make it so we can test N rules +running in the system which are generating signals on top of signals. After 30 seconds have gone by you should see that you now have two +documents in the signals index. The first signal is our original (signal -> event) document with a rule id: + +(signal -> event) + +```json +"parent" : { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 +}, +"ancestors" : [ + { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + } +] +``` + +and the second document is a signal on top of a signal like so: + +(signal -> signal -> event) + +```json +"parent" : { + "rule" : "161fa5b8-0b96-4985-b066-0d99b2bcb904", + "id" : "9d8710925adbf1a9c469621805407e74334dd08ca2c2ea414840fe971a571938", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 +}, +"ancestors" : [ + { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "161fa5b8-0b96-4985-b066-0d99b2bcb904", + "id" : "9d8710925adbf1a9c469621805407e74334dd08ca2c2ea414840fe971a571938", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + } +] +``` + +Notice that the depth indicates it is at level 2 and its parent is that of a signal. Also notice that the ancestors is an array of size 2 +indicating that this signal terminates at an event. Each and every signal ancestors array should terminate at an event and should ONLY contain 1 +event and NEVER 2 or more events. After 30+ seconds you should NOT see any new documents being created and you should be stable +at 2. Otherwise we have AND/OR a de-duplication issue, signal on signal issue. + +Now, post a second signal that is going to run against these two documents. + +```sh +./post_rule.sh ./rules/test_cases/signals_on_signals/halting_test/signal_on_signal.json +``` + +If you were to look at the number of rules you have: + +```sh +./find_rules.sh +``` + +You should see that you have 3 rules running concurrently at this point. Write down the `id` to keep track of them + +- 1 event rule which is always finding the same event continuously (id: ded57b36-9c4e-4ee4-805d-be4e92033e41) +- 1 signal rule which is finding ALL signals (id: 161fa5b8-0b96-4985-b066-0d99b2bcb904) +- 1 signal rule which is finding ALL signals (id: f2b70c4a-4d8f-4db5-9ed7-d3ab0630e406) + +The expected behavior is that eventually you will get 5 total documents but not additional ones after 1+ minutes. These will be: + +The original event rule ded57b36-9c4e-4ee4-805d-be4e92033e41 (event -> signal) + +```json +"parent" : { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 +}, +"ancestors" : [ + { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + } +] +``` + +The first signal to signal rule 161fa5b8-0b96-4985-b066-0d99b2bcb904 (signal -> event) + +```json +"parent" : { + "rule" : "161fa5b8-0b96-4985-b066-0d99b2bcb904", + "id" : "9d8710925adbf1a9c469621805407e74334dd08ca2c2ea414840fe971a571938", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 +}, +"ancestors" : [ + { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "161fa5b8-0b96-4985-b066-0d99b2bcb904", + "id" : "9d8710925adbf1a9c469621805407e74334dd08ca2c2ea414840fe971a571938", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + } +] +``` + +Then our second signal to signal rule f2b70c4a-4d8f-4db5-9ed7-d3ab0630e406 (signal -> event) which finds the same thing as the first +signal to signal + +```json +"parent" : { + "rule" : "f2b70c4a-4d8f-4db5-9ed7-d3ab0630e406", + "id" : "9d8710925adbf1a9c469621805407e74334dd08ca2c2ea414840fe971a571938", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 +}, +"ancestors" : [ + { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "f2b70c4a-4d8f-4db5-9ed7-d3ab0630e406", + "id" : "9d8710925adbf1a9c469621805407e74334dd08ca2c2ea414840fe971a571938", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + } +] +``` + +But then f2b70c4a-4d8f-4db5-9ed7-d3ab0630e406 also finds the first signal to signal rule from 161fa5b8-0b96-4985-b066-0d99b2bcb904 +and writes that document out with a depth of 3. (signal -> signal -> event) + +```json +"parent" : { + "rule" : "f2b70c4a-4d8f-4db5-9ed7-d3ab0630e406", + "id" : "c627e5e2576f1b10952c6c57249947e89b6153b763a59fb9e391d0b56be8e7fe", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 3 +}, +"ancestors" : [ + { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "161fa5b8-0b96-4985-b066-0d99b2bcb904", + "id" : "9d8710925adbf1a9c469621805407e74334dd08ca2c2ea414840fe971a571938", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + }, + { + "rule" : "f2b70c4a-4d8f-4db5-9ed7-d3ab0630e406", + "id" : "c627e5e2576f1b10952c6c57249947e89b6153b763a59fb9e391d0b56be8e7fe", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 3 + } +] +``` + +Since it wrote that document, the first signal to signal 161fa5b8-0b96-4985-b066-0d99b2bcb904 writes out it found this newly created signal +(signal -> signal -> event) + +```json +"parent" : { + "rule" : "161fa5b8-0b96-4985-b066-0d99b2bcb904", + "id" : "efbe514e8d806a5ef3da7658cfa73961e25befefc84f622e963b45dcac798868", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 3 +}, +"ancestors" : [ + { + "rule" : "ded57b36-9c4e-4ee4-805d-be4e92033e41", + "id" : "o8G7vm8BvLT8jmu5B1-M", + "type" : "event", + "index" : "filebeat-8.0.0-2019.12.18-000001", + "depth" : 1 + }, + { + "rule" : "f2b70c4a-4d8f-4db5-9ed7-d3ab0630e406", + "id" : "9d8710925adbf1a9c469621805407e74334dd08ca2c2ea414840fe971a571938", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 2 + }, + { + "rule" : "161fa5b8-0b96-4985-b066-0d99b2bcb904", + "id" : "efbe514e8d806a5ef3da7658cfa73961e25befefc84f622e963b45dcac798868", + "type" : "signal", + "index" : ".siem-signals-default-000001", + "depth" : 3 + } +] +``` + +You will be "halted" at this point as the signal ancestry and de-duplication ensures that we do not report twice on signals and that we do not +create additional duplications. So what happens if we create a 3rd rule which does a signal on a signal? + +```sh +./post_rule.sh ./rules/test_cases/signals_on_signals/halting_test/signal_on_signal.json +``` + +That 3rd signal should find all previous 5 signals and write them out. So that's 5 more. Then each signal will report on those 5 giving a depth of +4 . Grand total will be 16. You can repeat this as many times as you want and should always see an eventual constant stop time of the signals. They should +never keep increasing for this test. + +What about ordering the adding of rules between the query of the document and the signals? This order should not matter and you should get the same +results regardless of if you add the signals -> signals rules first or the query a signal event document first. The same number of documents should also +be outputted. + +Why does it take sometimes several minutes before things become stable? This is because a rule can write a signal back to the index, then another rule +wakes up and writes its document, and the previous rules on next run see this one and creates another chain. This continues until the ancestor detection +part of the code realizes that it is going to create a cyclic if it adds the same rule a second time and you no longer have a DAG (Directed Acyclic Graph) +at which point it terminates. + +What would happen if I changed the rule look-back from `"from": "now-1d"` to something smaller such as `"from": "now-30s"`? Then you won't get the same +number potentially and things are indeterministic because depending on when your rule runs it might find a previous signal and it might not. This is ok +and normal as you are then running signals on signals at the same interval as each other and the rules at the moment. A signal on a signal does not detect +that another signal has written something and it needs to re-run within the same scheduled time period. It also does not detect that another rule has just +written something and does not re-schedule its self to re-run again or against that document. + +How do I then solve the ordering problem event and signal rules writing at the same time? See the `depth_test` folder for more tests around that but you +have a few options. You can run your event rules at 5 minute intervals + 5 minute look back, then your signals rule at a 10 minute interval + 10 minute look +back which will cause it to check the latest run and the previous run for signals to signals depth of 2. For expected signals that should operate at a depth +of 3, you would increase it by another 10 minute look back for a 20 minute interval + 20 minute look back. For level 4, you would increase that to 40 minute +look back and adjust your queries accordingly to check the depth for more efficiency in querying. See `depth_test` for more information. diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/query_single_id.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/query_single_id.json new file mode 100644 index 00000000000000..dc05c656d7cf1f --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/query_single_id.json @@ -0,0 +1,12 @@ +{ + "name": "Queries single id", + "description": "Finds only one id below to create a single signal. Change the query to your exact _id you want to test with", + "risk_score": 1, + "severity": "high", + "type": "query", + "from": "now-1d", + "interval": "30s", + "to": "now", + "query": "_id: o8G7vm8BvLT8jmu5B1-M", + "enabled": true +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/signal_on_signal.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/signal_on_signal.json new file mode 100644 index 00000000000000..0f3a3e5865aa19 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/test_cases/signals_on_signals/halting_test/signal_on_signal.json @@ -0,0 +1,13 @@ +{ + "name": "Signal on Signals Rule 1", + "description": "Example Signal on Signal where it reports everything as a signal", + "risk_score": 1, + "severity": "high", + "type": "query", + "from": "now-1d", + "interval": "30s", + "to": "now", + "query": "_id: *", + "enabled": true, + "index": ".siem-signals-default" +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/updates/update_query_everything.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/updates/update_query_everything.json index a47d0155727d8f..eb210cd8153d7e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/updates/update_query_everything.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/updates/update_query_everything.json @@ -40,7 +40,7 @@ "from": "now-6m", "severity": "high", "type": "query", - "threats": [ + "threat": [ { "framework": "MITRE ATT&CK", "tactic": { @@ -48,7 +48,7 @@ "name": "impact", "reference": "https://attack.mitre.org/tactics/TA0040/" }, - "techniques": [ + "technique": [ { "id": "T1499", "name": "endpoint denial of service", @@ -63,7 +63,7 @@ "name": "Some other name", "reference": "https://example.com" }, - "techniques": [ + "technique": [ { "id": "some-other-id", "name": "some other technique name", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/signals/sample_signal.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/signals/sample_signal.json index 8cba054d4d2054..48b00930412b46 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/signals/sample_signal.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/signals/sample_signal.json @@ -13,13 +13,8 @@ "id": "e6f890af316a25920c951acefc46bfef", "name": "suricata-iowa", "containerized": false, - "ip": [ - "10.128.0.21", - "fe80::4001:aff:fe80:15" - ], - "mac": [ - "42:01:0a:80:00:15" - ], + "ip": ["10.128.0.21", "fe80::4001:aff:fe80:15"], + "mac": ["42:01:0a:80:00:15"], "hostname": "suricata-iowa" }, "client": { @@ -73,11 +68,8 @@ "bytes": 80 }, "process": { - "args": [ - "\/usr\/bin\/python3", - "\/usr\/bin\/google_network_daemon" - ], - "executable": "\/usr\/bin\/python3.7", + "args": ["/usr/bin/python3", "/usr/bin/google_network_daemon"], + "executable": "/usr/bin/python3.7", "created": "2019-11-04T15:01:04.190Z", "pid": 808, "name": "google_network_" @@ -137,38 +129,26 @@ "rule": { "id": "8d9bb7f1-9d8a-4f13-ae18-ccaf4ff61893", "rule_id": "rule-1", - "false_positives": [ - - ], + "false_positives": [], "max_signals": 100, "risk_score": 1, "description": "Detecting root and admin users", "from": "now-6s", "immutable": false, - "index": [ - "auditbeat-*", - "filebeat-*", - "packetbeat-*", - "winlogbeat-*" - ], + "index": ["auditbeat-*", "filebeat-*", "packetbeat-*", "winlogbeat-*"], "interval": "5s", "language": "kuery", - "name": "Detect Root\/Admin Users", + "name": "Detect Root/Admin Users", "query": "user.name: root or user.name: admin", - "references": [ - "http:\/\/www.example.com", - "https:\/\/ww.example.com" - ], + "references": ["http://www.example.com", "https://ww.example.com"], "severity": "high", - "tags": [ - - ], + "tags": [], "type": "query", "to": "now", "enabled": true, "created_by": "elastic", "updated_by": "elastic", - "threats": [ + "threat": [ { "framework": "fake", "technique": { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/__mocks__/es_results.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/__mocks__/es_results.ts index ede82a597b238e..6507e6ca73edeb 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/__mocks__/es_results.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/__mocks__/es_results.ts @@ -33,7 +33,7 @@ export const sampleRuleAlertParams = ( timelineId: undefined, timelineTitle: undefined, meta: undefined, - threats: undefined, + threat: undefined, version: 1, updatedAt: '2019-12-17T15:04:25.343Z', createdAt: '2019-12-17T15:04:37.105Z', @@ -75,7 +75,7 @@ export const sampleDocWithSortId = (someUuid: string = sampleIdGuid): SignalSour sort: ['1234567891111'], }); -export const sampleEmptyDocSearchResults: SignalSearchResponse = { +export const sampleEmptyDocSearchResults = (): SignalSearchResponse => ({ took: 10, timed_out: false, _shards: { @@ -89,6 +89,44 @@ export const sampleEmptyDocSearchResults: SignalSearchResponse = { max_score: 100, hits: [], }, +}); + +export const sampleDocWithAncestors = (): SignalSearchResponse => { + const sampleDoc = sampleDocNoSortId(); + sampleDoc._source.signal = { + parent: { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ancestors: [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], + }; + + return { + took: 10, + timed_out: false, + _shards: { + total: 10, + successful: 10, + failed: 0, + skipped: 0, + }, + hits: { + total: 0, + max_score: 100, + hits: [sampleDoc], + }, + }; }; export const sampleBulkCreateDuplicateResult = { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_bulk_body.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_bulk_body.test.ts index 90860a817d2703..de11bf6fcc3c15 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_bulk_body.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_bulk_body.test.ts @@ -11,6 +11,7 @@ import { sampleIdGuid, } from './__mocks__/es_results'; import { buildBulkBody } from './build_bulk_body'; +import { SignalHit } from './types'; describe('buildBulkBody', () => { beforeEach(() => { @@ -32,18 +33,28 @@ describe('buildBulkBody', () => { }); // Timestamp will potentially always be different so remove it for the test delete fakeSignalSourceHit['@timestamp']; - expect(fakeSignalSourceHit).toEqual({ + const expected: Omit & { someKey: 'someValue' } = { someKey: 'someValue', event: { kind: 'signal', }, signal: { parent: { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', id: sampleIdGuid, type: 'event', index: 'myFakeSignalIndex', depth: 1, }, + ancestors: [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: sampleIdGuid, + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], original_time: 'someTimeStamp', status: 'open', rule: { @@ -74,7 +85,8 @@ describe('buildBulkBody', () => { updated_at: fakeSignalSourceHit.signal.rule?.updated_at, }, }, - }); + }; + expect(fakeSignalSourceHit).toEqual(expected); }); test('if bulk body builds original_event if it exists on the event to begin with', () => { @@ -99,7 +111,7 @@ describe('buildBulkBody', () => { }); // Timestamp will potentially always be different so remove it for the test delete fakeSignalSourceHit['@timestamp']; - expect(fakeSignalSourceHit).toEqual({ + const expected: Omit & { someKey: 'someValue' } = { someKey: 'someValue', event: { action: 'socket_opened', @@ -115,11 +127,21 @@ describe('buildBulkBody', () => { module: 'system', }, parent: { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', id: sampleIdGuid, type: 'event', index: 'myFakeSignalIndex', depth: 1, }, + ancestors: [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: sampleIdGuid, + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], original_time: 'someTimeStamp', status: 'open', rule: { @@ -150,7 +172,8 @@ describe('buildBulkBody', () => { updated_at: fakeSignalSourceHit.signal.rule?.updated_at, }, }, - }); + }; + expect(fakeSignalSourceHit).toEqual(expected); }); test('if bulk body builds original_event if it exists on the event to begin with but no kind information', () => { @@ -174,7 +197,7 @@ describe('buildBulkBody', () => { }); // Timestamp will potentially always be different so remove it for the test delete fakeSignalSourceHit['@timestamp']; - expect(fakeSignalSourceHit).toEqual({ + const expected: Omit & { someKey: 'someValue' } = { someKey: 'someValue', event: { action: 'socket_opened', @@ -189,11 +212,21 @@ describe('buildBulkBody', () => { module: 'system', }, parent: { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', id: sampleIdGuid, type: 'event', index: 'myFakeSignalIndex', depth: 1, }, + ancestors: [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: sampleIdGuid, + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], original_time: 'someTimeStamp', status: 'open', rule: { @@ -224,7 +257,8 @@ describe('buildBulkBody', () => { updated_at: fakeSignalSourceHit.signal.rule?.updated_at, }, }, - }); + }; + expect(fakeSignalSourceHit).toEqual(expected); }); test('if bulk body builds original_event if it exists on the event to begin with with only kind information', () => { @@ -246,7 +280,7 @@ describe('buildBulkBody', () => { }); // Timestamp will potentially always be different so remove it for the test delete fakeSignalSourceHit['@timestamp']; - expect(fakeSignalSourceHit).toEqual({ + const expected: Omit & { someKey: 'someValue' } = { someKey: 'someValue', event: { kind: 'signal', @@ -256,11 +290,21 @@ describe('buildBulkBody', () => { kind: 'event', }, parent: { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', id: sampleIdGuid, type: 'event', index: 'myFakeSignalIndex', depth: 1, }, + ancestors: [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: sampleIdGuid, + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], original_time: 'someTimeStamp', status: 'open', rule: { @@ -291,6 +335,7 @@ describe('buildBulkBody', () => { created_at: fakeSignalSourceHit.signal.rule?.created_at, }, }, - }); + }; + expect(fakeSignalSourceHit).toEqual(expected); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_rule.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_rule.ts index 1093ff3a8a462d..ba1b2f695156bc 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_rule.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_rule.ts @@ -56,7 +56,7 @@ export const buildRule = ({ filters: ruleParams.filters, created_by: createdBy, updated_by: updatedBy, - threats: ruleParams.threats, + threat: ruleParams.threat, version: ruleParams.version, created_at: ruleParams.createdAt, updated_at: ruleParams.updatedAt, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_signal.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_signal.test.ts index debc619fbf8b21..dcd36ab811e6a1 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_signal.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_signal.test.ts @@ -5,9 +5,8 @@ */ import { sampleDocNoSortId, sampleRule } from './__mocks__/es_results'; -import { buildSignal } from './build_signal'; -import { OutputRuleAlertRest } from '../types'; -import { Signal } from './types'; +import { buildSignal, buildAncestor, buildAncestorsSignal } from './build_signal'; +import { Signal, Ancestor } from './types'; describe('buildSignal', () => { beforeEach(() => { @@ -17,15 +16,25 @@ describe('buildSignal', () => { test('it builds a signal as expected without original_event if event does not exist', () => { const doc = sampleDocNoSortId('d5e8eb51-a6a0-456d-8a15-4b79bfec3d71'); delete doc._source.event; - const rule: Partial = sampleRule(); + const rule = sampleRule(); const signal = buildSignal(doc, rule); const expected: Signal = { parent: { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', type: 'event', index: 'myFakeSignalIndex', depth: 1, }, + ancestors: [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], original_time: 'someTimeStamp', status: 'open', rule: { @@ -66,15 +75,25 @@ describe('buildSignal', () => { kind: 'event', module: 'system', }; - const rule: Partial = sampleRule(); + const rule = sampleRule(); const signal = buildSignal(doc, rule); const expected: Signal = { parent: { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', type: 'event', index: 'myFakeSignalIndex', depth: 1, }, + ancestors: [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], original_time: 'someTimeStamp', original_event: { action: 'socket_opened', @@ -112,4 +131,131 @@ describe('buildSignal', () => { }; expect(signal).toEqual(expected); }); + + test('it builds a ancestor correctly if the parent does not exist', () => { + const doc = sampleDocNoSortId('d5e8eb51-a6a0-456d-8a15-4b79bfec3d71'); + doc._source.event = { + action: 'socket_opened', + dataset: 'socket', + kind: 'event', + module: 'system', + }; + const rule = sampleRule(); + const signal = buildAncestor(doc, rule); + const expected: Ancestor = { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }; + expect(signal).toEqual(expected); + }); + + test('it builds a ancestor correctly if the parent does exist', () => { + const doc = sampleDocNoSortId('d5e8eb51-a6a0-456d-8a15-4b79bfec3d71'); + doc._source.event = { + action: 'socket_opened', + dataset: 'socket', + kind: 'event', + module: 'system', + }; + doc._source.signal = { + parent: { + rule: '98c0bf9e-4d38-46f4-9a6a-8a820426256b', + id: '730ddf9e-5a00-4f85-9ddf-5878ca511a87', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ancestors: [ + { + rule: '98c0bf9e-4d38-46f4-9a6a-8a820426256b', + id: '730ddf9e-5a00-4f85-9ddf-5878ca511a87', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], + }; + const rule = sampleRule(); + const signal = buildAncestor(doc, rule); + const expected: Ancestor = { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'signal', + index: 'myFakeSignalIndex', + depth: 2, + }; + expect(signal).toEqual(expected); + }); + + test('it builds a signal ancestor correctly if the parent does not exist', () => { + const doc = sampleDocNoSortId('d5e8eb51-a6a0-456d-8a15-4b79bfec3d71'); + doc._source.event = { + action: 'socket_opened', + dataset: 'socket', + kind: 'event', + module: 'system', + }; + const rule = sampleRule(); + const signal = buildAncestorsSignal(doc, rule); + const expected: Ancestor[] = [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ]; + expect(signal).toEqual(expected); + }); + + test('it builds a signal ancestor correctly if the parent does exist', () => { + const doc = sampleDocNoSortId('d5e8eb51-a6a0-456d-8a15-4b79bfec3d71'); + doc._source.event = { + action: 'socket_opened', + dataset: 'socket', + kind: 'event', + module: 'system', + }; + doc._source.signal = { + parent: { + rule: '98c0bf9e-4d38-46f4-9a6a-8a820426256b', + id: '730ddf9e-5a00-4f85-9ddf-5878ca511a87', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ancestors: [ + { + rule: '98c0bf9e-4d38-46f4-9a6a-8a820426256b', + id: '730ddf9e-5a00-4f85-9ddf-5878ca511a87', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], + }; + const rule = sampleRule(); + const signal = buildAncestorsSignal(doc, rule); + const expected: Ancestor[] = [ + { + rule: '98c0bf9e-4d38-46f4-9a6a-8a820426256b', + id: '730ddf9e-5a00-4f85-9ddf-5878ca511a87', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'signal', + index: 'myFakeSignalIndex', + depth: 2, + }, + ]; + expect(signal).toEqual(expected); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_signal.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_signal.ts index 4131c843297ea2..7a63d6831ea97c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_signal.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_signal.ts @@ -4,17 +4,52 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SignalSourceHit, Signal } from './types'; +import { SignalSourceHit, Signal, Ancestor } from './types'; import { OutputRuleAlertRest } from '../types'; -export const buildSignal = (doc: SignalSourceHit, rule: Partial): Signal => { - const signal: Signal = { - parent: { +export const buildAncestor = ( + doc: SignalSourceHit, + rule: Partial +): Ancestor => { + const existingSignal = doc._source.signal?.parent; + if (existingSignal != null) { + return { + rule: rule.id != null ? rule.id : '', + id: doc._id, + type: 'signal', + index: doc._index, + depth: existingSignal.depth + 1, + }; + } else { + return { + rule: rule.id != null ? rule.id : '', id: doc._id, type: 'event', index: doc._index, depth: 1, - }, + }; + } +}; + +export const buildAncestorsSignal = ( + doc: SignalSourceHit, + rule: Partial +): Signal['ancestors'] => { + const newAncestor = buildAncestor(doc, rule); + const existingAncestors = doc._source.signal?.ancestors; + if (existingAncestors != null) { + return [...existingAncestors, newAncestor]; + } else { + return [newAncestor]; + } +}; + +export const buildSignal = (doc: SignalSourceHit, rule: Partial): Signal => { + const parent = buildAncestor(doc, rule); + const ancestors = buildAncestorsSignal(doc, rule); + const signal: Signal = { + parent, + ancestors, original_time: doc._source['@timestamp'], status: 'open', rule, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.test.ts index ac6f840943f180..0644d5e467a5a0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.test.ts @@ -33,7 +33,7 @@ describe('searchAfterAndBulkCreate', () => { test('if successful with empty search results', async () => { const sampleParams = sampleRuleAlertParams(); const result = await searchAfterAndBulkCreate({ - someResult: sampleEmptyDocSearchResults, + someResult: sampleEmptyDocSearchResults(), ruleParams: sampleParams, services: mockService, logger: mockLogger, @@ -51,6 +51,7 @@ describe('searchAfterAndBulkCreate', () => { expect(mockService.callCluster).toHaveBeenCalledTimes(0); expect(result).toEqual(true); }); + test('if successful iteration of while loop with maxDocs', async () => { const sampleParams = sampleRuleAlertParams(30); const someGuids = Array.from({ length: 13 }).map(x => uuid.v4()); @@ -103,6 +104,7 @@ describe('searchAfterAndBulkCreate', () => { expect(mockService.callCluster).toHaveBeenCalledTimes(5); expect(result).toEqual(true); }); + test('if unsuccessful first bulk create', async () => { const someGuids = Array.from({ length: 4 }).map(x => uuid.v4()); const sampleParams = sampleRuleAlertParams(10); @@ -126,6 +128,7 @@ describe('searchAfterAndBulkCreate', () => { expect(mockLogger.error).toHaveBeenCalled(); expect(result).toEqual(false); }); + test('if unsuccessful iteration of searchAfterAndBulkCreate due to empty sort ids', async () => { const sampleParams = sampleRuleAlertParams(); mockService.callCluster.mockReturnValueOnce({ @@ -156,6 +159,7 @@ describe('searchAfterAndBulkCreate', () => { expect(mockLogger.error).toHaveBeenCalled(); expect(result).toEqual(false); }); + test('if unsuccessful iteration of searchAfterAndBulkCreate due to empty sort ids and 0 total hits', async () => { const sampleParams = sampleRuleAlertParams(); mockService.callCluster.mockReturnValueOnce({ @@ -185,6 +189,7 @@ describe('searchAfterAndBulkCreate', () => { }); expect(result).toEqual(true); }); + test('if successful iteration of while loop with maxDocs and search after returns results with no sort ids', async () => { const sampleParams = sampleRuleAlertParams(10); const someGuids = Array.from({ length: 4 }).map(x => uuid.v4()); @@ -217,6 +222,7 @@ describe('searchAfterAndBulkCreate', () => { }); expect(result).toEqual(true); }); + test('if successful iteration of while loop with maxDocs and search after returns empty results with no sort ids', async () => { const sampleParams = sampleRuleAlertParams(10); const someGuids = Array.from({ length: 4 }).map(x => uuid.v4()); @@ -230,7 +236,7 @@ describe('searchAfterAndBulkCreate', () => { }, ], }) - .mockReturnValueOnce(sampleEmptyDocSearchResults); + .mockReturnValueOnce(sampleEmptyDocSearchResults()); const result = await searchAfterAndBulkCreate({ someResult: repeatedSearchResultsWithSortId(4, 1, someGuids), ruleParams: sampleParams, @@ -249,6 +255,7 @@ describe('searchAfterAndBulkCreate', () => { }); expect(result).toEqual(true); }); + test('if returns false when singleSearchAfter throws an exception', async () => { const sampleParams = sampleRuleAlertParams(10); const someGuids = Array.from({ length: 4 }).map(x => uuid.v4()); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 32f2c86914770d..370ed652808499 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -53,7 +53,7 @@ export const signalRulesAlertType = ({ maxSignals: schema.number({ defaultValue: DEFAULT_MAX_SIGNALS }), riskScore: schema.number(), severity: schema.string(), - threats: schema.nullable(schema.arrayOf(schema.object({}, { allowUnknowns: true }))), + threat: schema.nullable(schema.arrayOf(schema.object({}, { allowUnknowns: true }))), to: schema.string(), type: schema.string(), updatedAt: schema.string(), @@ -134,6 +134,27 @@ export const signalRulesAlertType = ({ logger.warn( `Signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}" has a time gap of ${gap.humanize()} (${gap.asMilliseconds()}ms), and could be missing signals within that time. Consider increasing your look behind time or adding more Kibana instances.` ); + // write a failure status whenever we have a time gap + // this is a temporary solution until general activity + // monitoring is developed as a feature + const gapDate = new Date().toISOString(); + await services.savedObjectsClient.create(ruleStatusSavedObjectType, { + alertId, + statusDate: gapDate, + status: 'failed', + lastFailureAt: gapDate, + lastSuccessAt: currentStatusSavedObject.attributes.lastSuccessAt, + lastFailureMessage: `Signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}" has a time gap of ${gap.humanize()} (${gap.asMilliseconds()}ms), and could be missing signals within that time. Consider increasing your look behind time or adding more Kibana instances.`, + lastSuccessMessage: currentStatusSavedObject.attributes.lastSuccessMessage, + }); + + if (ruleStatusSavedObjects.saved_objects.length >= 6) { + // delete fifth status and prepare to insert a newer one. + const toDelete = ruleStatusSavedObjects.saved_objects.slice(5); + await toDelete.forEach(async item => + services.savedObjectsClient.delete(ruleStatusSavedObjectType, item.id) + ); + } } // set searchAfter page size to be the lesser of default page size or maxSignals. const searchAfterSize = @@ -243,10 +264,8 @@ export const signalRulesAlertType = ({ } } } catch (err) { - // TODO: Error handling and writing of errors into a signal that has error - // handling/conditions logger.error( - `Error from signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}"` + `Error from signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}", ${err.message}` ); const sDate = new Date().toISOString(); currentStatusSavedObject.attributes.status = 'failed'; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.test.ts index ca4b1d1e8e84a7..d5f11c91a2b7cd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.test.ts @@ -14,10 +14,11 @@ import { sampleEmptyDocSearchResults, sampleBulkCreateDuplicateResult, sampleBulkCreateErrorResult, + sampleDocWithAncestors, } from './__mocks__/es_results'; import { savedObjectsClientMock } from 'src/core/server/mocks'; import { DEFAULT_SIGNALS_INDEX } from '../../../../common/constants'; -import { singleBulkCreate } from './single_bulk_create'; +import { singleBulkCreate, filterDuplicateRules } from './single_bulk_create'; export const mockService = { callCluster: jest.fn(), @@ -131,9 +132,9 @@ describe('singleBulkCreate', () => { expect(firstHash).not.toEqual(secondHash); }); }); + test('create successful bulk create', async () => { const sampleParams = sampleRuleAlertParams(); - const sampleSearchResult = sampleDocSearchResultsNoSortId; mockService.callCluster.mockReturnValueOnce({ took: 100, errors: false, @@ -144,7 +145,7 @@ describe('singleBulkCreate', () => { ], }); const successfulsingleBulkCreate = await singleBulkCreate({ - someResult: sampleSearchResult(), + someResult: sampleDocSearchResultsNoSortId(), ruleParams: sampleParams, services: mockService, logger: mockLogger, @@ -159,9 +160,9 @@ describe('singleBulkCreate', () => { }); expect(successfulsingleBulkCreate).toEqual(true); }); + test('create successful bulk create with docs with no versioning', async () => { const sampleParams = sampleRuleAlertParams(); - const sampleSearchResult = sampleDocSearchResultsNoSortIdNoVersion; mockService.callCluster.mockReturnValueOnce({ took: 100, errors: false, @@ -172,7 +173,7 @@ describe('singleBulkCreate', () => { ], }); const successfulsingleBulkCreate = await singleBulkCreate({ - someResult: sampleSearchResult(), + someResult: sampleDocSearchResultsNoSortIdNoVersion(), ruleParams: sampleParams, services: mockService, logger: mockLogger, @@ -187,12 +188,12 @@ describe('singleBulkCreate', () => { }); expect(successfulsingleBulkCreate).toEqual(true); }); + test('create unsuccessful bulk create due to empty search results', async () => { const sampleParams = sampleRuleAlertParams(); - const sampleSearchResult = sampleEmptyDocSearchResults; mockService.callCluster.mockReturnValue(false); const successfulsingleBulkCreate = await singleBulkCreate({ - someResult: sampleSearchResult, + someResult: sampleEmptyDocSearchResults(), ruleParams: sampleParams, services: mockService, logger: mockLogger, @@ -253,4 +254,71 @@ describe('singleBulkCreate', () => { expect(mockLogger.error).toHaveBeenCalled(); expect(successfulsingleBulkCreate).toEqual(true); }); + + test('filter duplicate rules will return an empty array given an empty array', () => { + const filtered = filterDuplicateRules( + '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + sampleEmptyDocSearchResults() + ); + expect(filtered).toEqual([]); + }); + + test('filter duplicate rules will return nothing filtered when the two rule ids do not match with each other', () => { + const filtered = filterDuplicateRules('some id', sampleDocWithAncestors()); + expect(filtered).toEqual([ + { + _index: 'myFakeSignalIndex', + _type: 'doc', + _score: 100, + _version: 1, + _id: 'e1e08ddc-5e37-49ff-a258-5393aa44435a', + _source: { + someKey: 'someValue', + '@timestamp': 'someTimeStamp', + signal: { + parent: { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ancestors: [ + { + rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + id: 'd5e8eb51-a6a0-456d-8a15-4b79bfec3d71', + type: 'event', + index: 'myFakeSignalIndex', + depth: 1, + }, + ], + }, + }, + }, + ]); + }); + + test('filters duplicate rules will return empty array when the two rule ids match each other', () => { + const filtered = filterDuplicateRules( + '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + sampleDocWithAncestors() + ); + expect(filtered).toEqual([]); + }); + + test('filter duplicate rules will return back search responses if they do not have a signal and will NOT filter the source out', () => { + const ancestors = sampleDocWithAncestors(); + ancestors.hits.hits[0]._source = { '@timestamp': 'some timestamp' }; + const filtered = filterDuplicateRules('04128c15-0d1b-4716-a4c5-46997ac7f3bd', ancestors); + expect(filtered).toEqual([ + { + _index: 'myFakeSignalIndex', + _type: 'doc', + _score: 100, + _version: 1, + _id: 'e1e08ddc-5e37-49ff-a258-5393aa44435a', + _source: { '@timestamp': 'some timestamp' }, + }, + ]); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.ts index a6290e57eb2258..cb5de4c974927e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.ts @@ -28,6 +28,28 @@ interface SingleBulkCreateParams { tags: string[]; } +/** + * This is for signals on signals to work correctly. If given a rule id this will check if + * that rule id already exists in the ancestor tree of each signal search response and remove + * those documents so they cannot be created as a signal since we do not want a rule id to + * ever be capable of re-writing the same signal continuously if both the _input_ and _output_ + * of the signals index happens to be the same index. + * @param ruleId The rule id + * @param signalSearchResponse The search response that has all the documents + */ +export const filterDuplicateRules = ( + ruleId: string, + signalSearchResponse: SignalSearchResponse +) => { + return signalSearchResponse.hits.hits.filter(doc => { + if (doc._source.signal == null) { + return true; + } else { + return !doc._source.signal.ancestors.some(ancestor => ancestor.rule === ruleId); + } + }); +}; + // Bulk Index documents. export const singleBulkCreate = async ({ someResult, @@ -43,6 +65,8 @@ export const singleBulkCreate = async ({ enabled, tags, }: SingleBulkCreateParams): Promise => { + someResult.hits.hits = filterDuplicateRules(id, someResult); + if (someResult.hits.hits.length === 0) { return true; } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/types.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/types.ts index 544250858a0832..9b7b2b8f1fff9e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/types.ts @@ -51,11 +51,16 @@ export type SearchTypes = | boolean | boolean[] | object - | object[]; + | object[] + | undefined; export interface SignalSource { [key: string]: SearchTypes; '@timestamp': string; + signal?: { + parent: Ancestor; + ancestors: Ancestor[]; + }; } export interface BulkResponse { @@ -123,14 +128,18 @@ export type SignalRuleAlertTypeDefinition = Omit & { executor: ({ services, params, state }: RuleExecutorOptions) => Promise; }; +export interface Ancestor { + rule: string; + id: string; + type: string; + index: string; + depth: number; +} + export interface Signal { rule: Partial; - parent: { - id: string; - type: string; - index: string; - depth: number; - }; + parent: Ancestor; + ancestors: Ancestor[]; original_time: string; original_event?: SearchTypes; status: 'open' | 'closed'; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/types.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/types.ts index c7bd92322360a8..d1c9845dbbcfcc 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/types.ts @@ -18,7 +18,7 @@ export interface IMitreAttack { export interface ThreatParams { framework: string; tactic: IMitreAttack; - techniques: IMitreAttack[]; + technique: IMitreAttack[]; } export interface RuleAlertParams { @@ -46,7 +46,7 @@ export interface RuleAlertParams { to: string; timelineId: string | undefined | null; timelineTitle: string | undefined | null; - threats: ThreatParams[] | undefined | null; + threat: ThreatParams[] | undefined | null; type: 'query' | 'saved_query'; version: number; updatedAt: string; diff --git a/x-pack/legacy/plugins/siem/server/lib/ecs_fields/index.ts b/x-pack/legacy/plugins/siem/server/lib/ecs_fields/index.ts index 237e4193683766..f85fb2c9fd7534 100644 --- a/x-pack/legacy/plugins/siem/server/lib/ecs_fields/index.ts +++ b/x-pack/legacy/plugins/siem/server/lib/ecs_fields/index.ts @@ -307,7 +307,7 @@ export const signalFieldsMap: Readonly> = { 'signal.rule.references': 'signal.rule.references', 'signal.rule.severity': 'signal.rule.severity', 'signal.rule.tags': 'signal.rule.tags', - 'signal.rule.threats': 'signal.rule.threats', + 'signal.rule.threat': 'signal.rule.threat', 'signal.rule.type': 'signal.rule.type', 'signal.rule.size': 'signal.rule.size', 'signal.rule.enabled': 'signal.rule.enabled', diff --git a/x-pack/legacy/plugins/siem/server/lib/events/query.events_over_time.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/events/query.events_over_time.dsl.ts index 4b1837497669f0..3a4281b980cc45 100644 --- a/x-pack/legacy/plugins/siem/server/lib/events/query.events_over_time.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/events/query.events_over_time.dsl.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query'; +import { createQueryFilterClauses, calculateTimeSeriesInterval } from '../../utils/build_query'; import { MatrixHistogramRequestOptions } from '../framework'; export const buildEventsOverTimeQuery = ({ @@ -28,18 +28,17 @@ export const buildEventsOverTimeQuery = ({ ]; const getHistogramAggregation = () => { - const interval = calculateTimeseriesInterval(from, to); + const interval = calculateTimeSeriesInterval(from, to); const histogramTimestampField = '@timestamp'; const dateHistogram = { date_histogram: { field: histogramTimestampField, - fixed_interval: `${interval}s`, - }, - }; - const autoDateHistogram = { - auto_date_histogram: { - field: histogramTimestampField, - buckets: 36, + fixed_interval: interval, + min_doc_count: 0, + extended_bounds: { + min: from, + max: to, + }, }, }; return { @@ -53,7 +52,7 @@ export const buildEventsOverTimeQuery = ({ size: 10, }, aggs: { - events: interval ? dateHistogram : autoDateHistogram, + events: dateHistogram, }, }, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/network/query_dns_histogram.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/network/query_dns_histogram.dsl.ts index 67457ab4840acd..1ce324e0ffff89 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/query_dns_histogram.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/query_dns_histogram.dsl.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query'; +import { createQueryFilterClauses, calculateTimeSeriesInterval } from '../../utils/build_query'; import { MatrixHistogramRequestOptions } from '../framework'; export const buildDnsHistogramQuery = ({ @@ -29,12 +29,12 @@ export const buildDnsHistogramQuery = ({ ]; const getHistogramAggregation = () => { - const interval = calculateTimeseriesInterval(from, to); + const interval = calculateTimeSeriesInterval(from, to); const histogramTimestampField = '@timestamp'; const dateHistogram = { date_histogram: { field: histogramTimestampField, - fixed_interval: `${interval}s`, + fixed_interval: interval, }, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/overview/elastic_adapter.test.ts b/x-pack/legacy/plugins/siem/server/lib/overview/elastic_adapter.test.ts index d904219c76531c..29035f4539be89 100644 --- a/x-pack/legacy/plugins/siem/server/lib/overview/elastic_adapter.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/overview/elastic_adapter.test.ts @@ -143,7 +143,8 @@ describe('Siem Overview elasticsearch_adapter', () => { mockNoDataResponse.aggregations.system_module.process_count.doc_count = 0; mockNoDataResponse.aggregations.system_module.user_count.doc_count = 0; mockNoDataResponse.aggregations.system_module.filebeat_count.doc_count = 0; - mockNoDataResponse.aggregations.winlog_count.doc_count = 0; + mockNoDataResponse.aggregations.winlog_module.security_event_count.doc_count = 0; + mockNoDataResponse.aggregations.winlog_module.mwsysmon_operational_event_count.doc_count = 0; const mockCallWithRequest = jest.fn(); mockCallWithRequest.mockResolvedValue(mockNoDataResponse); const mockFramework: FrameworkAdapter = { @@ -181,7 +182,8 @@ describe('Siem Overview elasticsearch_adapter', () => { endgameRegistry: 0, endgameSecurity: 0, filebeatSystemModule: 0, - winlogbeat: 0, + winlogbeatSecurity: 0, + winlogbeatMWSysmonOperational: 0, }); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/overview/elasticsearch_adapter.ts b/x-pack/legacy/plugins/siem/server/lib/overview/elasticsearch_adapter.ts index b6b56fab484025..982b47110c5135 100644 --- a/x-pack/legacy/plugins/siem/server/lib/overview/elasticsearch_adapter.ts +++ b/x-pack/legacy/plugins/siem/server/lib/overview/elasticsearch_adapter.ts @@ -117,7 +117,16 @@ export class ElasticsearchOverviewAdapter implements OverviewAdapter { 'aggregations.system_module.filebeat_count.doc_count', response ), - winlogbeat: getOr(null, 'aggregations.winlog_count.doc_count', response), + winlogbeatSecurity: getOr( + null, + 'aggregations.winlog_module.security_event_count.doc_count', + response + ), + winlogbeatMWSysmonOperational: getOr( + null, + 'aggregations.winlog_module.mwsysmon_operational_event_count.doc_count', + response + ), }; } } diff --git a/x-pack/legacy/plugins/siem/server/lib/overview/mock.ts b/x-pack/legacy/plugins/siem/server/lib/overview/mock.ts index d2de5853879f85..6196f45029313e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/overview/mock.ts +++ b/x-pack/legacy/plugins/siem/server/lib/overview/mock.ts @@ -137,7 +137,14 @@ export const mockResponseHost = { user_count: { doc_count: 1979 }, filebeat_count: { doc_count: 225 }, }, - winlog_count: { doc_count: 737 }, + winlog_module: { + security_event_count: { + doc_count: 523, + }, + mwsysmon_operational_event_count: { + doc_count: 214, + }, + }, }, }; @@ -160,5 +167,6 @@ export const mockResultHost = { endgameRegistry: 896, endgameSecurity: 897, filebeatSystemModule: 225, - winlogbeat: 737, + winlogbeatSecurity: 523, + winlogbeatMWSysmonOperational: 214, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/overview/query.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/overview/query.dsl.ts index 55af5505e7dce3..30656c011ee21d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/overview/query.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/overview/query.dsl.ts @@ -203,12 +203,28 @@ export const buildOverviewHostQuery = ({ }, }, }, - winlog_count: { + winlog_module: { filter: { term: { 'agent.type': 'winlogbeat', }, }, + aggs: { + mwsysmon_operational_event_count: { + filter: { + term: { + 'winlog.channel': 'Microsoft-Windows-Sysmon/Operational', + }, + }, + }, + security_event_count: { + filter: { + term: { + 'winlog.channel': 'Security', + }, + }, + }, + }, }, system_module: { filter: { diff --git a/x-pack/legacy/plugins/siem/server/plugin.ts b/x-pack/legacy/plugins/siem/server/plugin.ts index 9d1983cf1d4daa..96eef2f44e5a06 100644 --- a/x-pack/legacy/plugins/siem/server/plugin.ts +++ b/x-pack/legacy/plugins/siem/server/plugin.ts @@ -14,6 +14,7 @@ import { noteSavedObjectType, pinnedEventSavedObjectType, timelineSavedObjectType, + ruleStatusSavedObjectType, } from './saved_objects'; export type SiemPluginSecurity = Pick; @@ -57,6 +58,7 @@ export class Plugin { noteSavedObjectType, pinnedEventSavedObjectType, timelineSavedObjectType, + ruleStatusSavedObjectType, ], read: ['config'], }, @@ -80,6 +82,7 @@ export class Plugin { noteSavedObjectType, pinnedEventSavedObjectType, timelineSavedObjectType, + ruleStatusSavedObjectType, ], }, ui: [ diff --git a/x-pack/legacy/plugins/siem/server/saved_objects.ts b/x-pack/legacy/plugins/siem/server/saved_objects.ts index 1d65e351fc86a9..8b9a1891c8a500 100644 --- a/x-pack/legacy/plugins/siem/server/saved_objects.ts +++ b/x-pack/legacy/plugins/siem/server/saved_objects.ts @@ -12,9 +12,17 @@ import { timelineSavedObjectType, timelineSavedObjectMappings, } from './lib/timeline/saved_object_mappings'; -import { ruleStatusSavedObjectMappings } from './lib/detection_engine/rules/saved_object_mappings'; +import { + ruleStatusSavedObjectMappings, + ruleStatusSavedObjectType, +} from './lib/detection_engine/rules/saved_object_mappings'; -export { noteSavedObjectType, pinnedEventSavedObjectType, timelineSavedObjectType }; +export { + noteSavedObjectType, + pinnedEventSavedObjectType, + ruleStatusSavedObjectType, + timelineSavedObjectType, +}; export const savedObjectMappings = { ...timelineSavedObjectMappings, ...noteSavedObjectMappings, diff --git a/x-pack/legacy/plugins/siem/server/types.ts b/x-pack/legacy/plugins/siem/server/types.ts index bbcfbe7b9c0ec8..3fa2268afe92c3 100644 --- a/x-pack/legacy/plugins/siem/server/types.ts +++ b/x-pack/legacy/plugins/siem/server/types.ts @@ -9,6 +9,8 @@ import { Legacy } from 'kibana'; export interface ServerFacade { config: Legacy.Server['config']; plugins: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + actions: any; // We have to do this at the moment because the types are not compatible alerting?: Legacy.Server['plugins']['alerting']; elasticsearch: Legacy.Server['plugins']['elasticsearch']; spaces: Legacy.Server['plugins']['spaces']; diff --git a/x-pack/legacy/plugins/siem/server/utils/build_query/calculate_timeseries_interval.ts b/x-pack/legacy/plugins/siem/server/utils/build_query/calculate_timeseries_interval.ts index 752c686b243ac6..5b667f461fc602 100644 --- a/x-pack/legacy/plugins/siem/server/utils/build_query/calculate_timeseries_interval.ts +++ b/x-pack/legacy/plugins/siem/server/utils/build_query/calculate_timeseries_interval.ts @@ -89,13 +89,6 @@ export const calculateAuto = { }), }; -export const calculateTimeseriesInterval = ( - lowerBoundInMsSinceEpoch: number, - upperBoundInMsSinceEpoch: number -) => { - const duration = moment.duration(upperBoundInMsSinceEpoch - lowerBoundInMsSinceEpoch, 'ms'); - - const matchedInterval = calculateAuto.near(50, duration); - - return matchedInterval ? Math.max(matchedInterval.asSeconds(), 1) : null; +export const calculateTimeSeriesInterval = (from: number, to: number) => { + return `${Math.floor((to - from) / 32)}ms`; }; diff --git a/x-pack/legacy/plugins/siem/yarn.lock b/x-pack/legacy/plugins/siem/yarn.lock new file mode 120000 index 00000000000000..4b16253de2abe6 --- /dev/null +++ b/x-pack/legacy/plugins/siem/yarn.lock @@ -0,0 +1 @@ +../../../../yarn.lock \ No newline at end of file diff --git a/x-pack/legacy/plugins/spaces/index.ts b/x-pack/legacy/plugins/spaces/index.ts index 934b44b4accaff..2e6b878794777f 100644 --- a/x-pack/legacy/plugins/spaces/index.ts +++ b/x-pack/legacy/plugins/spaces/index.ts @@ -127,9 +127,6 @@ export const spaces = (kibana: Record) => kibanaIndex: config.get('kibana.index'), }, savedObjects: server.savedObjects, - tutorial: { - addScopedTutorialContextFactory: server.addScopedTutorialContextFactory, - }, auditLogger: { create: (pluginId: string) => new AuditLogger(server, pluginId, server.config(), server.plugins.xpack_main.info), diff --git a/x-pack/legacy/plugins/task_manager/server/task_manager.mock.ts b/x-pack/legacy/plugins/task_manager/server/task_manager.mock.ts deleted file mode 100644 index a4b80d902d0984..00000000000000 --- a/x-pack/legacy/plugins/task_manager/server/task_manager.mock.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - TaskManagerSetupContract, - TaskManagerStartContract, -} from '../../../../plugins/task_manager/server'; -import { Subject } from 'rxjs'; - -export const taskManagerMock = { - setup(overrides: Partial> = {}) { - const mocked: jest.Mocked = { - registerTaskDefinitions: jest.fn(), - addMiddleware: jest.fn(), - config$: new Subject(), - registerLegacyAPI: jest.fn(), - ...overrides, - }; - return mocked; - }, - start(overrides: Partial> = {}) { - const mocked: jest.Mocked = { - ensureScheduled: jest.fn(), - schedule: jest.fn(), - fetch: jest.fn(), - runNow: jest.fn(), - remove: jest.fn(), - ...overrides, - }; - return mocked; - }, -}; diff --git a/x-pack/legacy/plugins/transform/public/plugin.ts b/x-pack/legacy/plugins/transform/public/plugin.ts index 5d1c39add4ff60..3b02d07b8c150c 100644 --- a/x-pack/legacy/plugins/transform/public/plugin.ts +++ b/x-pack/legacy/plugins/transform/public/plugin.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { unmountComponentAtNode } from 'react-dom'; - import { i18n } from '@kbn/i18n'; - -import { SavedSearchLoader } from '../../../../../src/legacy/core_plugins/kibana/public/discover/np_ready/types'; - import { PLUGIN } from '../common/constants'; import { CLIENT_BASE_PATH } from './app/constants'; import { renderReact } from './app/app'; @@ -19,6 +15,7 @@ import { documentationLinksService } from './app/services/documentation'; import { httpService } from './app/services/http'; import { textService } from './app/services/text'; import { uiMetricService } from './app/services/ui_metric'; +import { createSavedSearchesLoader } from '../../../../../src/legacy/core_plugins/kibana/public/discover/saved_searches'; const REACT_ROOT_ID = 'transformReactRoot'; const KBN_MANAGEMENT_SECTION = 'elasticsearch/transform'; @@ -36,12 +33,13 @@ export class Plugin { docTitle, uiSettings, savedObjects, + overlays, } = core; const { management, savedSearches: coreSavedSearches, uiMetric } = plugins; // AppCore/AppPlugins to be passed on as React context const AppDependencies = { - core: { chrome, http, i18n: core.i18n, uiSettings, savedObjects }, + core: { chrome, http, i18n: core.i18n, uiSettings, savedObjects, overlays }, plugins: { management: { sections: management.sections }, savedSearches: coreSavedSearches, @@ -77,12 +75,13 @@ export class Plugin { routing.registerAngularRoute(`${CLIENT_BASE_PATH}/:section?/:subsection?/:view?/:id?`, { template, controllerAs: 'transformController', - controller: ( - $scope: any, - $route: any, - $http: ng.IHttpService, - savedSearches: SavedSearchLoader - ) => { + controller: ($scope: any, $route: any, $http: ng.IHttpService) => { + const savedSearches = createSavedSearchesLoader({ + savedObjectsClient: core.savedObjects.client, + indexPatterns: plugins.data.indexPatterns, + chrome: core.chrome, + overlays: core.overlays, + }); // NOTE: We depend upon Angular's $http service because it's decorated with interceptors, // e.g. to check license status per request. legacyHttp.setClient($http); diff --git a/x-pack/legacy/plugins/transform/public/shim.ts b/x-pack/legacy/plugins/transform/public/shim.ts index d739dd2edddcc8..758cc90210579f 100644 --- a/x-pack/legacy/plugins/transform/public/shim.ts +++ b/x-pack/legacy/plugins/transform/public/shim.ts @@ -9,16 +9,21 @@ import { npStart } from 'ui/new_platform'; import { management, MANAGEMENT_BREADCRUMB } from 'ui/management'; import routes from 'ui/routes'; import { docTitle } from 'ui/doc_title/doc_title'; +import { CoreStart } from 'kibana/public'; // @ts-ignore: allow traversal to fail on x-pack build import { createUiStatsReporter } from '../../../../../src/legacy/core_plugins/ui_metric/public'; import { SavedSearchLoader } from '../../../../../src/legacy/core_plugins/kibana/public/discover/np_ready/types'; +import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; export type npCore = typeof npStart.core; // AppCore/AppPlugins is the set of core features/plugins // we pass on via context/hooks to the app and its components. -export type AppCore = Pick; +export type AppCore = Pick< + CoreStart, + 'chrome' | 'http' | 'i18n' | 'savedObjects' | 'uiSettings' | 'overlays' +>; export interface AppPlugins { management: { @@ -64,6 +69,7 @@ export interface Plugins extends AppPlugins { uiMetric: { createUiStatsReporter: typeof createUiStatsReporter; }; + data: DataPublicPluginStart; } export function createPublicShim(): { core: Core; plugins: Plugins } { @@ -101,6 +107,7 @@ export function createPublicShim(): { core: Core; plugins: Plugins } { }, }, plugins: { + data: npStart.plugins.data, management: { sections: management, constants: { diff --git a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/lib/alert_api.test.ts b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/lib/alert_api.test.ts index 858c90258247ec..0106970cf9c38c 100644 --- a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/lib/alert_api.test.ts +++ b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/lib/alert_api.test.ts @@ -83,20 +83,20 @@ describe('loadAlerts', () => { const result = await loadAlerts({ http, searchText: 'apples', page: { index: 0, size: 10 } }); expect(result).toEqual(resolvedValue); expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "/api/alert/_find", - Object { - "query": Object { - "default_search_operator": "AND", - "filter": undefined, - "page": 1, - "per_page": 10, - "search": "apples", - "search_fields": "[\\"name\\",\\"tags\\"]", - }, - }, - ] - `); + Array [ + "/api/alert/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": undefined, + "page": 1, + "per_page": 10, + "search": "apples", + "search_fields": "[\\"name\\",\\"tags\\"]", + }, + }, + ] + `); }); test('should call find API with actionTypesFilter', async () => { @@ -115,20 +115,20 @@ describe('loadAlerts', () => { }); expect(result).toEqual(resolvedValue); expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "/api/alert/_find", - Object { - "query": Object { - "default_search_operator": "AND", - "filter": undefined, - "page": 1, - "per_page": 10, - "search": "foo", - "search_fields": "[\\"name\\",\\"tags\\"]", - }, - }, - ] - `); + Array [ + "/api/alert/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": undefined, + "page": 1, + "per_page": 10, + "search": "foo", + "search_fields": "[\\"name\\",\\"tags\\"]", + }, + }, + ] + `); }); test('should call find API with typesFilter', async () => { @@ -147,20 +147,20 @@ describe('loadAlerts', () => { }); expect(result).toEqual(resolvedValue); expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "/api/alert/_find", - Object { - "query": Object { - "default_search_operator": "AND", - "filter": "alert.attributes.alertTypeId:(foo or bar)", - "page": 1, - "per_page": 10, - "search": undefined, - "search_fields": undefined, - }, - }, - ] - `); + Array [ + "/api/alert/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.alertTypeId:(foo or bar)", + "page": 1, + "per_page": 10, + "search": undefined, + "search_fields": undefined, + }, + }, + ] + `); }); test('should call find API with actionTypesFilter and typesFilter', async () => { @@ -180,20 +180,20 @@ describe('loadAlerts', () => { }); expect(result).toEqual(resolvedValue); expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "/api/alert/_find", - Object { - "query": Object { - "default_search_operator": "AND", - "filter": "alert.attributes.alertTypeId:(foo or bar)", - "page": 1, - "per_page": 10, - "search": "baz", - "search_fields": "[\\"name\\",\\"tags\\"]", - }, - }, - ] - `); + Array [ + "/api/alert/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.alertTypeId:(foo or bar)", + "page": 1, + "per_page": 10, + "search": "baz", + "search_fields": "[\\"name\\",\\"tags\\"]", + }, + }, + ] + `); }); test('should call find API with searchText and tagsFilter and typesFilter', async () => { @@ -213,20 +213,20 @@ describe('loadAlerts', () => { }); expect(result).toEqual(resolvedValue); expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "/api/alert/_find", - Object { - "query": Object { - "default_search_operator": "AND", - "filter": "alert.attributes.alertTypeId:(foo or bar)", - "page": 1, - "per_page": 10, - "search": "apples, foo, baz", - "search_fields": "[\\"name\\",\\"tags\\"]", - }, - }, - ] - `); + Array [ + "/api/alert/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.alertTypeId:(foo or bar)", + "page": 1, + "per_page": 10, + "search": "apples, foo, baz", + "search_fields": "[\\"name\\",\\"tags\\"]", + }, + }, + ] + `); }); }); @@ -258,10 +258,17 @@ describe('createAlert', () => { tags: ['foo'], enabled: true, alertTypeId: 'test', - interval: '1m', + schedule: { + interval: '1m', + }, actions: [], params: {}, throttle: null, + consumer: '', + createdAt: new Date('1970-01-01T00:00:00.000Z'), + updatedAt: new Date('1970-01-01T00:00:00.000Z'), + apiKey: null, + apiKeyOwner: null, }; const resolvedValue: Alert = { ...alertToCreate, @@ -279,7 +286,7 @@ describe('createAlert', () => { Array [ "/api/alert", Object { - "body": "{\\"name\\":\\"test\\",\\"tags\\":[\\"foo\\"],\\"enabled\\":true,\\"alertTypeId\\":\\"test\\",\\"interval\\":\\"1m\\",\\"actions\\":[],\\"params\\":{},\\"throttle\\":null}", + "body": "{\\"name\\":\\"test\\",\\"tags\\":[\\"foo\\"],\\"enabled\\":true,\\"alertTypeId\\":\\"test\\",\\"schedule\\":{\\"interval\\":\\"1m\\"},\\"actions\\":[],\\"params\\":{},\\"throttle\\":null,\\"consumer\\":\\"\\",\\"createdAt\\":\\"1970-01-01T00:00:00.000Z\\",\\"updatedAt\\":\\"1970-01-01T00:00:00.000Z\\",\\"apiKey\\":null,\\"apiKeyOwner\\":null}", }, ] `); @@ -292,9 +299,16 @@ describe('updateAlert', () => { throttle: '1m', name: 'test', tags: ['foo'], - interval: '1m', + schedule: { + interval: '1m', + }, params: {}, actions: [], + consumer: '', + createdAt: new Date('1970-01-01T00:00:00.000Z'), + updatedAt: new Date('1970-01-01T00:00:00.000Z'), + apiKey: null, + apiKeyOwner: null, }; const resolvedValue: Alert = { ...alertToUpdate, @@ -314,7 +328,7 @@ describe('updateAlert', () => { Array [ "/api/alert/123", Object { - "body": "{\\"throttle\\":\\"1m\\",\\"name\\":\\"test\\",\\"tags\\":[\\"foo\\"],\\"interval\\":\\"1m\\",\\"params\\":{},\\"actions\\":[]}", + "body": "{\\"throttle\\":\\"1m\\",\\"name\\":\\"test\\",\\"tags\\":[\\"foo\\"],\\"schedule\\":{\\"interval\\":\\"1m\\"},\\"params\\":{},\\"actions\\":[],\\"consumer\\":\\"\\",\\"createdAt\\":\\"1970-01-01T00:00:00.000Z\\",\\"updatedAt\\":\\"1970-01-01T00:00:00.000Z\\",\\"apiKey\\":null,\\"apiKeyOwner\\":null}", }, ] `); diff --git a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/lib/alert_api.ts b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/lib/alert_api.ts index 9867acbd7a622a..0b4f5731c13153 100644 --- a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/lib/alert_api.ts +++ b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/lib/alert_api.ts @@ -83,7 +83,7 @@ export async function updateAlert({ id, }: { http: HttpSetup; - alert: Pick; + alert: Pick; id: string; }): Promise { return await http.put(`${BASE_ALERT_API_PATH}/${id}`, { diff --git a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alert_add/alert_add.tsx b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alert_add/alert_add.tsx index 9380392112c8e9..f11b0b948b2a79 100644 --- a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alert_add/alert_add.tsx +++ b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alert_add/alert_add.tsx @@ -72,7 +72,7 @@ function validateBaseProperties(alertObject: Alert) { }) ); } - if (!alertObject.interval) { + if (!(alertObject.schedule && alertObject.schedule.interval)) { errors.interval.push( i18n.translate('xpack.triggersActionsUI.sections.alertAdd.error.requiredIntervalText', { defaultMessage: 'Check interval is required.', @@ -94,7 +94,9 @@ export const AlertAdd = ({ refreshList }: Props) => { const initialAlert = { params: {}, alertTypeId: null, - interval: '1m', + schedule: { + interval: '1m', + }, actions: [], tags: [], }; @@ -148,7 +150,9 @@ export const AlertAdd = ({ refreshList }: Props) => { value: { params: {}, alertTypeId: null, - interval: '1m', + schedule: { + interval: '1m', + }, actions: [], tags: [], }, @@ -674,7 +678,9 @@ export const AlertAdd = ({ refreshList }: Props) => { const interval = e.target.value !== '' ? parseInt(e.target.value, 10) : null; setAlertInterval(interval); - setAlertProperty('interval', `${e.target.value}${alertIntervalUnit}`); + setAlertProperty('schedule', { + interval: `${e.target.value}${alertIntervalUnit}`, + }); }} /> @@ -686,7 +692,9 @@ export const AlertAdd = ({ refreshList }: Props) => { options={getTimeOptions((alertInterval ? alertInterval : 1).toString())} onChange={(e: any) => { setAlertIntervalUnit(e.target.value); - setAlertProperty('interval', `${alertInterval}${e.target.value}`); + setAlertProperty('schedule', { + interval: `${alertInterval}${e.target.value}`, + }); }} /> diff --git a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/alerts_list.test.tsx b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/alerts_list.test.tsx index 8f8aef5a16bd5f..9f77bfb3f8760f 100644 --- a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/alerts_list.test.tsx +++ b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/alerts_list.test.tsx @@ -145,7 +145,7 @@ describe('alerts_list component with items', () => { tags: ['tag1'], enabled: true, alertTypeId: 'test_alert_type', - interval: '5d', + schedule: { interval: '5d' }, actions: [], params: { name: 'test alert type name' }, scheduledTaskId: null, @@ -162,7 +162,7 @@ describe('alerts_list component with items', () => { tags: ['tag1'], enabled: true, alertTypeId: 'test_alert_type', - interval: '5d', + schedule: { interval: '5d' }, actions: [{ id: 'test', group: 'alert', params: { message: 'test' } }], params: { name: 'test alert type name' }, scheduledTaskId: null, @@ -348,7 +348,7 @@ describe('alerts_list with show only capability', () => { tags: ['tag1'], enabled: true, alertTypeId: 'test_alert_type', - interval: '5d', + schedule: { interval: '5d' }, actions: [], params: { name: 'test alert type name' }, scheduledTaskId: null, @@ -365,7 +365,7 @@ describe('alerts_list with show only capability', () => { tags: ['tag1'], enabled: true, alertTypeId: 'test_alert_type', - interval: '5d', + schedule: { interval: '5d' }, actions: [{ id: 'test', group: 'alert', params: { message: 'test' } }], params: { name: 'test alert type name' }, scheduledTaskId: null, diff --git a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/alerts_list.tsx b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/alerts_list.tsx index 64f06521c0f9d9..4b5e0d1948bfb6 100644 --- a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/alerts_list.tsx +++ b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/alerts_list.tsx @@ -31,6 +31,17 @@ import { hasDeleteAlertsCapability, hasSaveAlertsCapability } from '../../../lib const ENTER_KEY = 13; +interface AlertTypeState { + isLoading: boolean; + isInitialized: boolean; + data: AlertTypeIndex; +} +interface AlertState { + isLoading: boolean; + data: Alert[]; + totalItemCount: number; +} + export const AlertsList: React.FunctionComponent = () => { const { http, @@ -43,20 +54,24 @@ export const AlertsList: React.FunctionComponent = () => { const createAlertUiEnabled = injectedMetadata.getInjectedVar('createAlertUiEnabled'); const [actionTypes, setActionTypes] = useState([]); - const [alertTypesIndex, setAlertTypesIndex] = useState(undefined); - const [alerts, setAlerts] = useState([]); - const [data, setData] = useState([]); const [selectedIds, setSelectedIds] = useState([]); - const [isLoadingAlertTypes, setIsLoadingAlertTypes] = useState(false); - const [isLoadingAlerts, setIsLoadingAlerts] = useState(false); const [isPerformingAction, setIsPerformingAction] = useState(false); - const [totalItemCount, setTotalItemCount] = useState(0); const [page, setPage] = useState({ index: 0, size: 10 }); const [searchText, setSearchText] = useState(); const [inputText, setInputText] = useState(); const [typesFilter, setTypesFilter] = useState([]); const [actionTypesFilter, setActionTypesFilter] = useState([]); const [alertFlyoutVisible, setAlertFlyoutVisibility] = useState(false); + const [alertTypesState, setAlertTypesState] = useState({ + isLoading: false, + isInitialized: false, + data: {}, + }); + const [alertsState, setAlertsState] = useState({ + isLoading: false, + data: [], + totalItemCount: 0, + }); useEffect(() => { loadAlertsData(); @@ -66,13 +81,13 @@ export const AlertsList: React.FunctionComponent = () => { useEffect(() => { (async () => { try { - setIsLoadingAlertTypes(true); + setAlertTypesState({ ...alertTypesState, isLoading: true }); const alertTypes = await loadAlertTypes({ http }); const index: AlertTypeIndex = {}; for (const alertType of alertTypes) { index[alertType.id] = alertType; } - setAlertTypesIndex(index); + setAlertTypesState({ isLoading: false, data: index, isInitialized: true }); } catch (e) { toastNotifications.addDanger({ title: i18n.translate( @@ -80,8 +95,7 @@ export const AlertsList: React.FunctionComponent = () => { { defaultMessage: 'Unable to load alert types' } ), }); - } finally { - setIsLoadingAlertTypes(false); + setAlertTypesState({ ...alertTypesState, isLoading: false }); } })(); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -104,23 +118,8 @@ export const AlertsList: React.FunctionComponent = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useEffect(() => { - // Avoid flickering before alert types load - if (typeof alertTypesIndex === 'undefined') { - return; - } - const updatedData = alerts.map(alert => ({ - ...alert, - tagsText: alert.tags.join(', '), - alertType: alertTypesIndex[alert.alertTypeId] - ? alertTypesIndex[alert.alertTypeId].name - : alert.alertTypeId, - })); - setData(updatedData); - }, [alerts, alertTypesIndex]); - async function loadAlertsData() { - setIsLoadingAlerts(true); + setAlertsState({ ...alertsState, isLoading: true }); try { const alertsResponse = await loadAlerts({ http, @@ -129,8 +128,11 @@ export const AlertsList: React.FunctionComponent = () => { typesFilter, actionTypesFilter, }); - setAlerts(alertsResponse.data); - setTotalItemCount(alertsResponse.total); + setAlertsState({ + isLoading: false, + data: alertsResponse.data, + totalItemCount: alertsResponse.total, + }); } catch (e) { toastNotifications.addDanger({ title: i18n.translate( @@ -140,8 +142,7 @@ export const AlertsList: React.FunctionComponent = () => { } ), }); - } finally { - setIsLoadingAlerts(false); + setAlertsState({ ...alertsState, isLoading: false }); } } @@ -200,7 +201,7 @@ export const AlertsList: React.FunctionComponent = () => { setTypesFilter(types)} - options={Object.values(alertTypesIndex || {}) + options={Object.values(alertTypesState.data) .map(alertType => ({ value: alertType.id, name: alertType.name, @@ -241,7 +242,10 @@ export const AlertsList: React.FunctionComponent = () => { {selectedIds.length > 0 && canDelete && ( setIsPerformingAction(true)} onActionPerformed={() => { loadAlertsData(); @@ -282,8 +286,13 @@ export const AlertsList: React.FunctionComponent = () => { ({ @@ -296,7 +305,9 @@ export const AlertsList: React.FunctionComponent = () => { pagination={{ pageIndex: page.index, pageSize: page.size, - totalItemCount, + /* Don't display alert count until we have the alert types initialized */ + totalItemCount: + alertTypesState.isInitialized === false ? 0 : alertsState.totalItemCount, }} selection={ canDelete @@ -318,13 +329,14 @@ export const AlertsList: React.FunctionComponent = () => { ); }; -function pickFromData(data: AlertTableItem[], ids: string[]): AlertTableItem[] { - const result: AlertTableItem[] = []; - for (const id of ids) { - const match = data.find(item => item.id === id); - if (match) { - result.push(match); - } - } - return result; +function filterAlertsById(alerts: Alert[], ids: string[]): Alert[] { + return alerts.filter(alert => ids.includes(alert.id)); +} + +function convertAlertsToTableItems(alerts: Alert[], alertTypesIndex: AlertTypeIndex) { + return alerts.map(alert => ({ + ...alert, + tagsText: alert.tags.join(', '), + alertType: alertTypesIndex[alert.alertTypeId]?.name ?? alert.alertTypeId, + })); } diff --git a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/collapsed_item_actions.tsx b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/collapsed_item_actions.tsx index f063ab4f7cde3c..dc6fb15f0f2366 100644 --- a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/collapsed_item_actions.tsx +++ b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/application/sections/alerts_list/components/collapsed_item_actions.tsx @@ -44,8 +44,6 @@ export const CollapsedItemActions: React.FunctionComponent = ({ const canDelete = hasDeleteAlertsCapability(capabilities.get()); const canSave = hasSaveAlertsCapability(capabilities.get()); - const [isEnabled, setIsEnabled] = useState(item.enabled); - const [isMuted, setIsMuted] = useState(item.muteAll); const [isPopoverOpen, setIsPopoverOpen] = useState(false); const button = ( @@ -72,14 +70,12 @@ export const CollapsedItemActions: React.FunctionComponent = ({ { - if (isEnabled) { - setIsEnabled(false); + if (item.enabled) { await disableAlerts({ http, ids: [item.id] }); } else { - setIsEnabled(true); await enableAlerts({ http, ids: [item.id] }); } onAlertChanged(); @@ -95,15 +91,13 @@ export const CollapsedItemActions: React.FunctionComponent = ({ { - if (isMuted) { - setIsMuted(false); + if (item.muteAll) { await unmuteAlerts({ http, ids: [item.id] }); } else { - setIsMuted(true); await muteAlerts({ http, ids: [item.id] }); } onAlertChanged(); diff --git a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/types.ts b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/types.ts index 4cf28d3bbd06fc..7a8a0ead5e8c51 100644 --- a/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/types.ts +++ b/x-pack/legacy/plugins/triggers_actions_ui/np_ready/public/types.ts @@ -5,6 +5,8 @@ */ import { capabilities } from 'ui/capabilities'; import { TypeRegistry } from './application/type_registry'; +import { SanitizedAlert as Alert } from '../../../alerting/common'; +export { SanitizedAlert as Alert, AlertAction } from '../../../alerting/common'; export type ActionTypeIndex = Record; export type AlertTypeIndex = Record; @@ -71,30 +73,6 @@ export interface AlertType { name: string; } -export interface AlertAction { - group: string; - id: string; - params: Record; -} - -export interface Alert { - id: string; - name: string; - tags: string[]; - enabled: boolean; - alertTypeId: string; - interval: string; - actions: AlertAction[]; - params: Record; - scheduledTaskId?: string; - createdBy: string | null; - updatedBy: string | null; - apiKeyOwner?: string; - throttle: string | null; - muteAll: boolean; - mutedInstanceIds: string[]; -} - export type AlertWithoutId = Omit; export interface AlertTableItem extends Alert { diff --git a/x-pack/legacy/plugins/uptime/common/constants/client_defaults.ts b/x-pack/legacy/plugins/uptime/common/constants/client_defaults.ts index e991e0c6b82e11..d8a3ef8d7cbbb1 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/client_defaults.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/client_defaults.ts @@ -8,17 +8,28 @@ export const CLIENT_DEFAULTS = { ABSOLUTE_DATE_RANGE_START: 0, // 15 minutes ABSOLUTE_DATE_RANGE_END: 1000 * 60 * 15, - // 60 seconds + /** + * The application auto refreshes every 60s by default. + */ AUTOREFRESH_INTERVAL: 60 * 1000, - // polling defaults to "on" + /** + * The application's autorefresh feature is enabled. + */ AUTOREFRESH_IS_PAUSED: false, + COMMONLY_USED_DATE_RANGES: [ { start: 'now/d', end: 'now', label: 'Today' }, { start: 'now/w', end: 'now', label: 'Week to date' }, { start: 'now/M', end: 'now', label: 'Month to date' }, { start: 'now/y', end: 'now', label: 'Year to date' }, ], + /** + * The beginning of the default date range is 15m ago. + */ DATE_RANGE_START: 'now-15m', + /** + * The end of the default date range is now. + */ DATE_RANGE_END: 'now', FILTERS: '', MONITOR_LIST_PAGE_INDEX: 0, diff --git a/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts b/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts index 4c32769d73e847..540e60a28b066c 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts @@ -10,35 +10,13 @@ import { SortOrder, CursorDirection } from '../graphql/types'; * The Uptime UI utilizes a settings context, the defaults for which are stored here. */ export const CONTEXT_DEFAULTS = { - /** - * The application's autorefresh feature is enabled. - */ - AUTOREFRESH_IS_PAUSED: true, - /** - * The application autorefreshes every 10s by default. - */ - AUTOREFRESH_INTERVAL: 10000, /** * The application cannot assume a basepath. */ BASE_PATH: '', - /** - * The beginning of the default date range is 15m ago. - */ - DATE_RANGE_START: 'now-15m', - /** - * The end of the default date range is now. - */ - DATE_RANGE_END: 'now', CURSOR_PAGINATION: { cursorDirection: CursorDirection.AFTER, sortOrder: SortOrder.ASC, }, - - /** - * Defines the maximum number of monitors to iterate on - * in a single count session. The intention is to catch as many as possible. - */ - MAX_MONITORS_FOR_SNAPSHOT_COUNT: 1000000, }; diff --git a/x-pack/legacy/plugins/uptime/index.ts b/x-pack/legacy/plugins/uptime/index.ts index e090a2c85e1366..cf7332f97d466b 100644 --- a/x-pack/legacy/plugins/uptime/index.ts +++ b/x-pack/legacy/plugins/uptime/index.ts @@ -9,6 +9,7 @@ import { resolve } from 'path'; import { PluginInitializerContext } from 'src/core/server'; import { PLUGIN } from './common/constants'; import { KibanaServer, plugin } from './server'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; export const uptime = (kibana: any) => new kibana.Plugin({ @@ -30,6 +31,7 @@ export const uptime = (kibana: any) => main: 'plugins/uptime/app', order: 8900, url: '/app/uptime#/', + category: DEFAULT_APP_CATEGORIES.observability, }, home: ['plugins/uptime/register_feature'], }, diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx index 98780d23c5a629..11f6565734782e 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx @@ -12,6 +12,7 @@ import { start } from '../../../../../../../../../src/legacy/core_plugins/embedd import * as i18n from './translations'; // @ts-ignore import { MAP_SAVED_OBJECT_TYPE } from '../../../../../../maps/common/constants'; +import { Location } from '../../../../../common/runtime_types'; import { MapEmbeddable } from './types'; import { getLayerList } from './map_config'; @@ -22,10 +23,7 @@ export interface EmbeddedMapProps { downPoints: LocationPoint[]; } -export interface LocationPoint { - lat: string; - lon: string; -} +export type LocationPoint = Required; const EmbeddedPanel = styled.div` z-index: auto; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts index d4601baefdf30c..a43edae4382527 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts @@ -5,7 +5,7 @@ */ import lowPolyLayerFeatures from './low_poly_layer.json'; -import { LocationPoint } from './embedded_map'; +import { LocationPoint } from './embedded_map.js'; import { UptimeAppColors } from '../../../../uptime_app'; /** @@ -16,7 +16,7 @@ import { UptimeAppColors } from '../../../../uptime_app'; export const getLayerList = ( upPoints: LocationPoint[], downPoints: LocationPoint[], - { gray, danger }: Pick + { danger }: Pick ) => { return [getLowPolyLayer(), getDownPointsLayer(downPoints, danger), getUpPointsLayer(upPoints)]; }; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx index d35e1281260e2e..c93e16d0a080b5 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx @@ -9,7 +9,7 @@ import styled from 'styled-components'; import { EuiFlexGroup, EuiFlexItem, EuiErrorBoundary } from '@elastic/eui'; import { LocationStatusTags } from './location_status_tags'; import { EmbeddedMap, LocationPoint } from './embeddables/embedded_map'; -import { MonitorLocations } from '../../../../common/runtime_types'; +import { MonitorLocations, MonitorLocation } from '../../../../common/runtime_types'; import { UNNAMED_LOCATION } from '../../../../common/constants'; import { LocationMissingWarning } from './location_missing'; @@ -32,15 +32,23 @@ export const LocationMap = ({ monitorLocations }: LocationMapProps) => { let isGeoInfoMissing = false; if (monitorLocations?.locations) { - monitorLocations.locations.forEach((item: any) => { - if (item.geo?.name !== UNNAMED_LOCATION) { - if (item.summary.down === 0) { - upPoints.push(item.geo.location); + monitorLocations.locations.forEach((item: MonitorLocation) => { + if (item.geo?.name === UNNAMED_LOCATION || !item.geo?.location) { + isGeoInfoMissing = true; + } else if ( + item.geo?.name !== UNNAMED_LOCATION && + !!item.geo.location.lat && + !!item.geo.location.lon + ) { + // TypeScript doesn't infer that the above checks in this block's condition + // ensure that lat and lon are defined when we try to pass the location object directly, + // but if we destructure the values it does. Improvement to this block is welcome. + const { lat, lon } = item.geo.location; + if (item?.summary?.down === 0) { + upPoints.push({ lat, lon }); } else { - downPoints.push(item.geo.location); + downPoints.push({ lat, lon }); } - } else if (item.geo?.name === UNNAMED_LOCATION) { - isGeoInfoMissing = true; } }); } diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap index e32771faf5912c..1de49f12236992 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap @@ -36,6 +36,12 @@ exports[`MonitorList component renders a no items message when no data is provid "sortable": true, "width": "30%", }, + Object { + "aligh": "left", + "field": "state.url.full", + "name": "Url", + "render": [Function], + }, Object { "align": "center", "field": "histogram.points", @@ -128,6 +134,12 @@ exports[`MonitorList component renders the monitor list 1`] = ` "sortable": true, "width": "30%", }, + Object { + "aligh": "left", + "field": "state.url.full", + "name": "Url", + "render": [Function], + }, Object { "align": "center", "field": "histogram.points", diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_pagination.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_pagination.test.tsx.snap index a2cae3e1e3b6b7..aa9d3a3ed0d8c8 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_pagination.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_pagination.test.tsx.snap @@ -36,6 +36,12 @@ exports[`MonitorList component renders a no items message when no data is provid "sortable": true, "width": "30%", }, + Object { + "aligh": "left", + "field": "state.url.full", + "name": "Url", + "render": [Function], + }, Object { "align": "center", "field": "histogram.points", @@ -128,6 +134,12 @@ exports[`MonitorList component renders the monitor list 1`] = ` "sortable": true, "width": "30%", }, + Object { + "aligh": "left", + "field": "state.url.full", + "name": "Url", + "render": [Function], + }, Object { "align": "center", "field": "histogram.points", diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx index b1b25baf7d8737..1d0930f1faaefc 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx @@ -5,17 +5,20 @@ */ import { + EuiButtonIcon, EuiBasicTable, EuiFlexGroup, - EuiPanel, - EuiTitle, - EuiButtonIcon, EuiFlexItem, + EuiIcon, + EuiLink, + EuiPanel, EuiSpacer, + EuiTitle, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { get } from 'lodash'; import React, { useState, Fragment } from 'react'; +import styled from 'styled-components'; import { withUptimeGraphQL, UptimeGraphQLQueryProps } from '../../higher_order'; import { monitorStatesQuery } from '../../../queries/monitor_states_query'; import { @@ -47,6 +50,12 @@ interface MonitorListProps { type Props = UptimeGraphQLQueryProps & MonitorListProps; +const TruncatedEuiLink = styled(EuiLink)` + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; + export const MonitorListComponent = (props: Props) => { const { absoluteStartDate, @@ -99,6 +108,16 @@ export const MonitorListComponent = (props: Props) => { ), sortable: true, }, + { + aligh: 'left' as const, + field: 'state.url.full', + name: labels.URL, + render: (url: string, summary: MonitorSummary) => ( + + {url} + + ), + }, { align: 'center' as const, field: 'histogram.points', diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap index 389afa27fd21fe..0a280ac6b24b8c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap @@ -21,7 +21,7 @@ Array [ > Get https://expired.badssl.com: x509: certificate has expired or is not yet valid diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx index c2df9253ec8dcf..036882b49359f4 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx @@ -33,7 +33,7 @@ export const MostRecentError = ({ error, monitorId, timestamp }: MostRecentError const [getUrlParams] = useUrlParams(); const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = getUrlParams(); params.selectedPingStatus = 'down'; - const linkParameters = stringifyUrlParams(params); + const linkParameters = stringifyUrlParams(params, true); const timestampStr = timestamp ? moment(new Date(timestamp).valueOf()).fromNow() : ''; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/translations.ts b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/translations.ts index 9f17f6d7f27b00..beacdec1ae2654 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/translations.ts +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/translations.ts @@ -52,3 +52,7 @@ export const NO_DATA_MESSAGE = i18n.translate('xpack.uptime.monitorList.noItemMe defaultMessage: 'No uptime monitors found', description: 'This message is shown if the monitors table is rendered but has no items.', }); + +export const URL = i18n.translate('xpack.uptime.monitorList.table.url.name', { + defaultMessage: 'Url', +}); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap new file mode 100644 index 00000000000000..cfdbb5184d1707 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PingListExpandedRow renders expected elements for valid props 1`] = ` + + + docs +   + + , + } + } + /> + +`; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap index 9fdca0d5b99f16..9aed8780682ee0 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap @@ -1,77 +1,228 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`PingListExpandedRow doesn't render list items if the body field is undefined 1`] = ` - + + + + + + + `; exports[`PingListExpandedRow doesn't render list items if the http field is undefined 1`] = ` - + + + + + + + `; exports[`PingListExpandedRow doesn't render list items if the response field is undefined 1`] = ` - + + + + + + + `; exports[`PingListExpandedRow renders error information when an error field is present 1`] = ` - - Forbidden - , - "title": "Error", - }, - Object { - "description": - The Title", - "hash": "testhash", - } - } - /> - - , - "title": "Response Body", - }, - ] - } -/> + + + + + Forbidden + , + "title": "Error", + }, + Object { + "description": + The Title", + "hash": "testhash", + } + } + /> + + + , + "title": "Response Body", + }, + ] + } + /> + + + `; exports[`PingListExpandedRow renders expected elements for valid props 1`] = ` - - The Title", - "hash": "testhash", - } - } - /> - - , - "title": "Response Body", - }, - ] - } -/> + + + + + The Title", + "hash": "testhash", + } + } + /> + + + , + "title": "Response Body", + }, + ] + } + /> + + + +`; + +exports[`PingListExpandedRow renders link to docs if body is not recorded but it is present 1`] = ` +
    +
    +
    +
    + +
    +
    +
    +
    + Response Body +
    +
    +
    + Body size is 1MB. +
    +
    +
    + Body not recorded. Read our + + docs  + + + for more information on recording response bodies. +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`PingListExpandedRow shallow renders link to docs if body is not recorded but it is present 1`] = ` + + + + + + + + , + "title": "Response Body", + }, + ] + } + /> + + + `; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/doc_link_body.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/doc_link_body.test.tsx new file mode 100644 index 00000000000000..a29f647a226139 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/doc_link_body.test.tsx @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import React from 'react'; +import { DocLinkForBody } from '../doc_link_body'; + +describe('PingListExpandedRow', () => { + it('renders expected elements for valid props', () => { + expect(shallowWithIntl()).toMatchSnapshot(); + }); +}); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx index f8914b1d46484a..9dbe48ec5553a0 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { mountWithIntl, renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { PingListExpandedRowComponent } from '../expanded_row'; import { Ping } from '../../../../../common/graphql/types'; +import { DocLinkForBody } from '../doc_link_body'; describe('PingListExpandedRow', () => { let ping: Ping; @@ -56,4 +57,26 @@ describe('PingListExpandedRow', () => { delete ping.http; expect(shallowWithIntl()).toMatchSnapshot(); }); + + it(`shallow renders link to docs if body is not recorded but it is present`, () => { + // @ts-ignore this shouldn't be undefined unless the beforeEach block is modified + delete ping.http.response.body.content; + expect(shallowWithIntl()).toMatchSnapshot(); + }); + + it(`renders link to docs if body is not recorded but it is present`, () => { + // @ts-ignore this shouldn't be undefined unless the beforeEach block is modified + delete ping.http.response.body.content; + expect(renderWithIntl()).toMatchSnapshot(); + }); + + it(`mount component to find link to docs if body is not recorded but it is present`, () => { + // @ts-ignore this shouldn't be undefined unless the beforeEach block is modified + delete ping.http.response.body.content; + const component = mountWithIntl(); + + const docLinkComponent = component.find(DocLinkForBody); + + expect(docLinkComponent).toHaveLength(1); + }); }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/doc_link_body.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/doc_link_body.tsx new file mode 100644 index 00000000000000..9640529f391c03 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/doc_link_body.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { EuiIcon, EuiLink, EuiText } from '@elastic/eui'; + +const bodyDocsLink = + 'https://www.elastic.co/guide/en/beats/heartbeat/current/configuration-heartbeat-options.html#monitor-http-response'; + +export const DocLinkForBody = () => { + const docsLink = ( + + {i18n.translate('xpack.uptime.pingList.drawer.body.docsLink', { + defaultMessage: 'docs', + description: 'Docs link to set response body', + })} +   + + + ); + + return ( + + + + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx index 34aef698ee5df4..c684235122e34b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx @@ -5,10 +5,19 @@ */ // @ts-ignore formatNumber import { formatNumber } from '@elastic/eui/lib/services/format'; -import { EuiCodeBlock, EuiDescriptionList, EuiText } from '@elastic/eui'; -import React, { Fragment } from 'react'; +import { + EuiCallOut, + EuiCodeBlock, + EuiDescriptionList, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { Ping, HttpBody } from '../../../../common/graphql/types'; +import { DocLinkForBody } from './doc_link_body'; interface Props { ping: Ping; @@ -52,7 +61,7 @@ export const PingListExpandedRowComponent = ({ ping }: Props) => { } // Show the body, if present - if (ping.http && ping.http.response && ping.http.response.body) { + if (ping.http?.response?.body) { const body = ping.http.response.body; listItems.push({ @@ -60,12 +69,21 @@ export const PingListExpandedRowComponent = ({ ping }: Props) => { defaultMessage: 'Response Body', }), description: ( - + <> - - + + {body.content ? : } + ), }); } - return ; + return ( + + + + + + + + ); }; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx index 85517144edfc60..e8825dacc0078f 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx @@ -115,6 +115,14 @@ export const PingListComponent = ({ }) ); + const pings: Ping[] = data?.allPings?.pings ?? []; + + const hasStatus: boolean = pings.reduce( + (hasHttpStatus: boolean, currentPing: Ping) => + hasHttpStatus || !!currentPing.http?.response?.status_code, + false + ); + const columns: any[] = [ { field: 'monitor.status', @@ -172,55 +180,57 @@ export const PingListComponent = ({ }), }, { - align: 'right', + align: hasStatus ? 'right' : 'center', field: 'error.type', name: i18n.translate('xpack.uptime.pingList.errorTypeColumnLabel', { defaultMessage: 'Error type', }), render: (error: string) => error ?? '-', }, - ]; - const pings: Ping[] = data?.allPings?.pings ?? []; - const hasStatus: boolean = pings.reduce( - (hasHttpStatus: boolean, currentPing: Ping) => - hasHttpStatus || !!currentPing.http?.response?.status_code, - false - ); - if (hasStatus) { - columns.push({ - field: 'http.response.status_code', + // Only add this column is there is any status present in list + ...(hasStatus + ? [ + { + field: 'http.response.status_code', + align: 'right', + name: ( + + {i18n.translate('xpack.uptime.pingList.responseCodeColumnLabel', { + defaultMessage: 'Response code', + })} + + ), + render: (statusCode: string) => ( + + {statusCode} + + ), + }, + ] + : []), + { align: 'right', - name: ( - - {i18n.translate('xpack.uptime.pingList.responseCodeColumnLabel', { - defaultMessage: 'Response code', - })} - - ), - render: (statusCode: string) => ( - - {statusCode}{' '} - - ), - }); - } + width: '24px', + isExpander: true, + render: (item: Ping) => { + return ( + toggleDetails(item, itemIdToExpandedRowMap, setItemIdToExpandedRowMap)} + disabled={!item.error && !(item.http?.response?.body?.bytes > 0)} + aria-label={ + itemIdToExpandedRowMap[item.id] + ? i18n.translate('xpack.uptime.pingList.collapseRow', { + defaultMessage: 'Collapse', + }) + : i18n.translate('xpack.uptime.pingList.expandRow', { defaultMessage: 'Expand' }) + } + iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'} + /> + ); + }, + }, + ]; - columns.push({ - align: 'right', - width: '24px', - isExpander: true, - render: (item: Ping) => ( - toggleDetails(item, itemIdToExpandedRowMap, setItemIdToExpandedRowMap)} - aria-label={ - itemIdToExpandedRowMap[item.id] - ? i18n.translate('xpack.uptime.pingList.collapseRow', { defaultMessage: 'Collapse' }) - : i18n.translate('xpack.uptime.pingList.expandRow', { defaultMessage: 'Expand' }) - } - iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'} - /> - ), - }); const pagination: Pagination = { initialPageSize: 20, pageIndex: 0, diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/uptime_date_picker.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/uptime_date_picker.tsx index 2118faa7751301..7d2123af8ff9cd 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/uptime_date_picker.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/uptime_date_picker.tsx @@ -61,7 +61,7 @@ export const UptimeDatePicker = () => { updateUrl({ autorefreshInterval: refreshInterval === undefined ? autorefreshInterval : refreshInterval, - autorefreshPaused: isPaused, + autorefreshIsPaused: isPaused, }); }} /> diff --git a/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx b/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx index 4b3abb46ac1e4a..9f508497035620 100644 --- a/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx +++ b/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx @@ -5,10 +5,10 @@ */ import React, { createContext, useMemo } from 'react'; -import { useParams } from 'react-router-dom'; import { UptimeAppProps } from '../uptime_app'; -import { CONTEXT_DEFAULTS } from '../../common/constants'; +import { CLIENT_DEFAULTS, CONTEXT_DEFAULTS } from '../../common/constants'; import { CommonlyUsedRange } from '../components/functional/uptime_date_picker'; +import { useUrlParams } from '../hooks'; export interface UptimeSettingsContextValues { basePath: string; @@ -20,7 +20,9 @@ export interface UptimeSettingsContextValues { commonlyUsedRanges?: CommonlyUsedRange[]; } -const { BASE_PATH, DATE_RANGE_START, DATE_RANGE_END } = CONTEXT_DEFAULTS; +const { BASE_PATH } = CONTEXT_DEFAULTS; + +const { DATE_RANGE_START, DATE_RANGE_END } = CLIENT_DEFAULTS; /** * These are default values for the context. These defaults are typically @@ -39,7 +41,9 @@ export const UptimeSettingsContext = createContext(defaultContext); export const UptimeSettingsContextProvider: React.FC = ({ children, ...props }) => { const { basePath, isApmAvailable, isInfraAvailable, isLogsAvailable, commonlyUsedRanges } = props; - const { dateRangeStart, dateRangeEnd } = useParams(); + const [getUrlParams] = useUrlParams(); + + const { dateRangeStart, dateRangeEnd } = getUrlParams(); const value = useMemo(() => { return { diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/__snapshots__/stringify_url_params.test.ts.snap b/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/__snapshots__/stringify_url_params.test.ts.snap index 57add60bebe9ad..31f5ceff7d0463 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/__snapshots__/stringify_url_params.test.ts.snap +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/__snapshots__/stringify_url_params.test.ts.snap @@ -1,3 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`stringifyUrlParams creates expected string value 1`] = `"?autorefreshInterval=50000&autorefreshIsPaused=false&dateRangeStart=now-15m&dateRangeEnd=now&filters=monitor.id%3A%20bar&search=monitor.id%3A%20foo&selectedPingStatus=down&statusFilter=up"`; + +exports[`stringifyUrlParams creates expected string value when ignore empty is true 1`] = `"?autorefreshInterval=50000&filters=monitor.id%3A%20bar"`; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/stringify_url_params.test.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/stringify_url_params.test.ts index 4c999680fa53e2..a2f9b29c4ff584 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/stringify_url_params.test.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/stringify_url_params.test.ts @@ -20,4 +20,26 @@ describe('stringifyUrlParams', () => { }); expect(result).toMatchSnapshot(); }); + + it('creates expected string value when ignore empty is true', () => { + const result = stringifyUrlParams( + { + autorefreshInterval: 50000, + autorefreshIsPaused: false, + dateRangeStart: 'now-15m', + dateRangeEnd: 'now', + filters: 'monitor.id: bar', + search: undefined, + selectedPingStatus: undefined, + statusFilter: '', + pagination: undefined, + }, + true + ); + expect(result).toMatchSnapshot(); + + expect(result.includes('pagination')).toBeFalsy(); + expect(result.includes('search')).toBeFalsy(); + expect(result.includes('selectedPingStatus')).toBeFalsy(); + }); }); diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/stringify_url_params.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/stringify_url_params.ts index f1e90691267086..7d00a27d69032d 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/stringify_url_params.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/stringify_url_params.ts @@ -5,6 +5,38 @@ */ import qs from 'querystring'; -import { UptimeUrlParams } from './url_params/get_supported_url_params'; +import { UptimeUrlParams } from './url_params'; +import { CLIENT_DEFAULTS } from '../../../common/constants'; -export const stringifyUrlParams = (params: Partial) => `?${qs.stringify(params)}`; +const { + AUTOREFRESH_INTERVAL, + AUTOREFRESH_IS_PAUSED, + DATE_RANGE_START, + DATE_RANGE_END, +} = CLIENT_DEFAULTS; + +export const stringifyUrlParams = (params: Partial, ignoreEmpty = false) => { + if (ignoreEmpty) { + Object.keys(params).forEach((key: string) => { + // @ts-ignore + const val = params[key]; + if (val == null || val === '') { + // @ts-ignore + delete params[key]; + } + if (key === 'dateRangeStart' && val === DATE_RANGE_START) { + delete params[key]; + } + if (key === 'dateRangeEnd' && val === DATE_RANGE_END) { + delete params[key]; + } + if (key === 'autorefreshIsPaused' && val === AUTOREFRESH_IS_PAUSED) { + delete params[key]; + } + if (key === 'autorefreshInterval' && val === AUTOREFRESH_INTERVAL) { + delete params[key]; + } + }); + } + return `?${qs.stringify(params)}`; +}; diff --git a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx index 1c14d971120be0..36abee673b6829 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx @@ -33,11 +33,6 @@ interface OverviewPageProps { type Props = OverviewPageProps; -export type UptimeSearchBarQueryChangeHandler = (queryChangedEvent: { - query?: { text: string }; - queryText?: string; -}) => void; - const EuiFlexItemStyled = styled(EuiFlexItem)` && { min-width: 598px; @@ -109,7 +104,7 @@ export const OverviewPage = ({ autocomplete, setBreadcrumbs }: Props) => { statusFilter, }; - const linkParameters = stringifyUrlParams(params); + const linkParameters = stringifyUrlParams(params, true); return ( diff --git a/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx b/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx index d341a22bc583b3..e8705a2eb8eb32 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx @@ -7,7 +7,7 @@ import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; -import { useRouteMatch, useParams } from 'react-router-dom'; +import { useRouteMatch } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { UptimeDatePicker } from '../components/functional/uptime_date_picker'; import { AppState } from '../state'; @@ -17,6 +17,7 @@ import { stringifyUrlParams } from '../lib/helper/stringify_url_params'; import { getTitle } from '../lib/helper/get_title'; import { UMUpdateBreadcrumbs } from '../lib/lib'; import { MONITOR_ROUTE } from '../routes'; +import { useUrlParams } from '../hooks'; interface PageHeaderProps { monitorStatus?: any; @@ -28,7 +29,8 @@ export const PageHeaderComponent = ({ monitorStatus, setBreadcrumbs }: PageHeade path: MONITOR_ROUTE, }); - const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = useParams(); + const [getUrlParams] = useUrlParams(); + const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = getUrlParams(); const headingText = i18n.translate('xpack.uptime.overviewPage.headerText', { defaultMessage: 'Overview', @@ -52,7 +54,7 @@ export const PageHeaderComponent = ({ monitorStatus, setBreadcrumbs }: PageHeade useEffect(() => { if (monitorPage) { if (headerText) { - setBreadcrumbs(getMonitorPageBreadcrumb(headerText, stringifyUrlParams(params))); + setBreadcrumbs(getMonitorPageBreadcrumb(headerText, stringifyUrlParams(params, true))); } } else { setBreadcrumbs(getOverviewPageBreadcrumbs()); diff --git a/x-pack/legacy/plugins/uptime/public/routes.tsx b/x-pack/legacy/plugins/uptime/public/routes.tsx index 028f2d5958325a..07bba5163922e6 100644 --- a/x-pack/legacy/plugins/uptime/public/routes.tsx +++ b/x-pack/legacy/plugins/uptime/public/routes.tsx @@ -10,7 +10,7 @@ import { MonitorPage, OverviewPage, NotFoundPage } from './pages'; import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; import { UMUpdateBreadcrumbs } from './lib/lib'; -export const MONITOR_ROUTE = '/monitor/:monitorId/:location?'; +export const MONITOR_ROUTE = '/monitor/:monitorId?'; export const OVERVIEW_ROUTE = '/'; interface RouterProps { diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/framework/adapter_types.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/framework/adapter_types.ts index b490bf17e292c3..2f72081a709884 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/framework/adapter_types.ts @@ -48,7 +48,7 @@ export interface UptimeCoreSetup { } export interface UptimeCorePlugins { - savedObjects: SavedObjectsLegacyService; + savedObjects: SavedObjectsLegacyService; usageCollection: UsageCollectionSetup; xpack: any; } diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/elasticsearch_monitor_states_adapter.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/elasticsearch_monitor_states_adapter.ts index eaaa8087e57cdd..7ed973e6f057d2 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/elasticsearch_monitor_states_adapter.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/elasticsearch_monitor_states_adapter.ts @@ -61,7 +61,7 @@ export const elasticsearchMonitorStatesAdapter: UMMonitorStatesAdapter = { dateRangeEnd, CONTEXT_DEFAULTS.CURSOR_PAGINATION, filters && filters !== '' ? JSON.parse(filters) : null, - CONTEXT_DEFAULTS.MAX_MONITORS_FOR_SNAPSHOT_COUNT, + Infinity, statusFilter ); diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/search/query_context.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/search/query_context.ts index 03e228952f0e79..d97b7653402a32 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/search/query_context.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/search/query_context.ts @@ -55,19 +55,15 @@ export class QueryContext { return clauses; } - async dateRangeFilter(forceNoTimespan?: boolean): Promise { + async dateRangeFilter(): Promise { const timestampClause = { range: { '@timestamp': { gte: this.dateRangeStart, lte: this.dateRangeEnd } }, }; - if (forceNoTimespan === true || !(await this.hasTimespan())) { + if (!(await this.hasTimespan())) { return timestampClause; } - // @ts-ignore - const tsStart = DateMath.parse(this.dateRangeEnd).subtract(10, 'seconds'); - const tsEnd = DateMath.parse(this.dateRangeEnd)!; - return { bool: { filter: [ @@ -75,14 +71,7 @@ export class QueryContext { { bool: { should: [ - { - range: { - 'monitor.timespan': { - gte: tsStart.toISOString(), - lte: tsEnd.toISOString(), - }, - }, - }, + this.timespanClause(), { bool: { must_not: { exists: { field: 'monitor.timespan' } }, @@ -96,6 +85,29 @@ export class QueryContext { }; } + // timeRangeClause queries the given date range using the monitor timespan field + // which is a bit dicey since we may have data that predates this field existing, + // or we may have data that has it, but a slow ingestion process. + timespanClause() { + // We subtract 5m from the start to account for data that shows up late, + // for instance, with a large value for the elasticsearch refresh interval + // setting it lower can work very well on someone's laptop, but with real world + // latencies and slowdowns that's dangerous. Making this value larger makes things + // only slower, but only marginally so, and prevents people from seeing weird + // behavior. + const tsStart = DateMath.parse(this.dateRangeEnd)!.subtract(5, 'minutes'); + const tsEnd = DateMath.parse(this.dateRangeEnd)!; + + return { + range: { + 'monitor.timespan': { + gte: tsStart.toISOString(), + lte: tsEnd.toISOString(), + }, + }, + }; + } + async hasTimespan(): Promise { if (this.hasTimespanCache) { return this.hasTimespanCache; @@ -107,10 +119,7 @@ export class QueryContext { body: { query: { bool: { - filter: [ - await this.dateRangeFilter(true), - { exists: { field: 'monitor.timespan' } }, - ], + filter: [this.timespanClause()], }, }, }, diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts index c86e0db9ae04ad..e433931f03c8e6 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts @@ -346,16 +346,18 @@ export const elasticsearchMonitorsAdapter: UMMonitorsAdapter = { const result = await callES('search', params); const locations = result?.aggregations?.location?.buckets ?? []; - const getGeo = (locGeo: any) => { + const getGeo = (locGeo: { name: string; location?: string }) => { if (locGeo) { const { name, location } = locGeo; - const latLon = location.trim().split(','); + const latLon = location?.trim().split(','); return { name, - location: { - lat: latLon[0], - lon: latLon[1], - }, + location: latLon + ? { + lat: latLon[0], + lon: latLon[1], + } + : undefined, }; } else { return { diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx b/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx deleted file mode 100644 index de285ee15b59d9..00000000000000 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx +++ /dev/null @@ -1,50 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { ComponentType } from 'enzyme'; -import { - chromeServiceMock, - docLinksServiceMock, - uiSettingsServiceMock, - notificationServiceMock, - httpServiceMock, -} from '../../../../../../../src/core/public/mocks'; -import { AppContextProvider } from '../../../public/np_ready/application/app_context'; - -export const mockContextValue = { - docLinks: docLinksServiceMock.createStartContract(), - chrome: chromeServiceMock.createStartContract(), - legacy: { - TimeBuckets: class MockTimeBuckets { - setBounds(_domain: any) { - return {}; - } - getInterval() { - return { - expression: {}, - }; - } - }, - MANAGEMENT_BREADCRUMB: { text: 'test' }, - licenseStatus: {}, - }, - uiSettings: uiSettingsServiceMock.createSetupContract(), - toasts: notificationServiceMock.createSetupContract().toasts, - euiUtils: { - useChartsTheme: jest.fn(), - }, - // For our test harness, we don't use this mocked out http service - http: httpServiceMock.createSetupContract(), -}; - -export const withAppContext = (Component: ComponentType) => (props: any) => { - return ( - - - - ); -}; diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/index.ts b/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/index.ts deleted file mode 100644 index 814028fe599ff6..00000000000000 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/index.ts +++ /dev/null @@ -1,23 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { setup as watchListSetup } from './watch_list.helpers'; -import { setup as watchStatusSetup } from './watch_status.helpers'; -import { setup as watchCreateJsonSetup } from './watch_create_json.helpers'; -import { setup as watchCreateThresholdSetup } from './watch_create_threshold.helpers'; -import { setup as watchEditSetup } from './watch_edit.helpers'; - -export { nextTick, getRandomString, findTestSubject, TestBed } from '../../../../../../test_utils'; -export { wrapBodyResponse, unwrapBodyResponse } from './body_response'; -export { setupEnvironment } from './setup_environment'; - -export const pageHelpers = { - watchList: { setup: watchListSetup }, - watchStatus: { setup: watchStatusSetup }, - watchCreateJson: { setup: watchCreateJsonSetup }, - watchCreateThreshold: { setup: watchCreateThresholdSetup }, - watchEdit: { setup: watchEditSetup }, -}; diff --git a/x-pack/legacy/plugins/watcher/common/constants/plugin.ts b/x-pack/legacy/plugins/watcher/common/constants/plugin.ts deleted file mode 100644 index a4279a0dd0c414..00000000000000 --- a/x-pack/legacy/plugins/watcher/common/constants/plugin.ts +++ /dev/null @@ -1,17 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { LICENSE_TYPE_GOLD, LicenseType } from '../../../../common/constants'; - -export const PLUGIN = { - ID: 'watcher', - MINIMUM_LICENSE_REQUIRED: LICENSE_TYPE_GOLD as LicenseType, - getI18nName: (i18n: any): string => { - return i18n.translate('xpack.watcher.appName', { - defaultMessage: 'Watcher', - }); - }, -}; diff --git a/x-pack/legacy/plugins/watcher/common/models/action/action.js b/x-pack/legacy/plugins/watcher/common/models/action/action.js deleted file mode 100644 index e66a63eaed1862..00000000000000 --- a/x-pack/legacy/plugins/watcher/common/models/action/action.js +++ /dev/null @@ -1,48 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { set } from 'lodash'; -import { getActionType } from '../../../common/lib/get_action_type'; -import { ACTION_TYPES } from '../../../common/constants'; -import { LoggingAction } from './logging_action'; -import { EmailAction } from './email_action'; -import { SlackAction } from './slack_action'; -import { IndexAction } from './index_action'; -import { WebhookAction } from './webhook_action'; -import { PagerDutyAction } from './pagerduty_action'; -import { JiraAction } from './jira_action'; -import { UnknownAction } from './unknown_action'; - -const ActionTypes = {}; -set(ActionTypes, ACTION_TYPES.LOGGING, LoggingAction); -set(ActionTypes, ACTION_TYPES.EMAIL, EmailAction); -set(ActionTypes, ACTION_TYPES.SLACK, SlackAction); -set(ActionTypes, ACTION_TYPES.INDEX, IndexAction); -set(ActionTypes, ACTION_TYPES.WEBHOOK, WebhookAction); -set(ActionTypes, ACTION_TYPES.PAGERDUTY, PagerDutyAction); -set(ActionTypes, ACTION_TYPES.JIRA, JiraAction); -set(ActionTypes, ACTION_TYPES.UNKNOWN, UnknownAction); - -export class Action { - static getActionTypes = () => { - return ActionTypes; - }; - - // From Elasticsearch - static fromUpstreamJson(json) { - const type = getActionType(json.actionJson); - const ActionType = ActionTypes[type] || UnknownAction; - const { action } = ActionType.fromUpstreamJson(json); - return action; - } - - // From Kibana - static fromDownstreamJson(json) { - const ActionType = ActionTypes[json.type] || UnknownAction; - const { action } = ActionType.fromDownstreamJson(json); - return action; - } -} diff --git a/x-pack/legacy/plugins/watcher/index.js b/x-pack/legacy/plugins/watcher/index.js deleted file mode 100644 index 64237b532ea8d5..00000000000000 --- a/x-pack/legacy/plugins/watcher/index.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { pluginDefinition } from './plugin_definition'; - -export const watcher = kibana => new kibana.Plugin(pluginDefinition); diff --git a/x-pack/legacy/plugins/watcher/index.ts b/x-pack/legacy/plugins/watcher/index.ts new file mode 100644 index 00000000000000..fdf9ba1bad6e44 --- /dev/null +++ b/x-pack/legacy/plugins/watcher/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { resolve } from 'path'; + +const pluginDefinition = { + id: 'watcher', + configPrefix: 'xpack.watcher', + publicDir: resolve(__dirname, 'public'), + require: ['kibana'], + uiExports: { + styleSheetPaths: resolve(__dirname, 'public/index.scss'), + }, + init(server: any) {}, +}; + +export const watcher = (kibana: any) => new kibana.Plugin(pluginDefinition); diff --git a/x-pack/legacy/plugins/watcher/kibana.json b/x-pack/legacy/plugins/watcher/kibana.json deleted file mode 100644 index ccec8a1b776836..00000000000000 --- a/x-pack/legacy/plugins/watcher/kibana.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "watcher", - "version": "kibana", - "requiredPlugins": [ - "home" - ], - "server": true, - "ui": true -} diff --git a/x-pack/legacy/plugins/watcher/plugin_definition.ts b/x-pack/legacy/plugins/watcher/plugin_definition.ts deleted file mode 100644 index 2da05253fdb325..00000000000000 --- a/x-pack/legacy/plugins/watcher/plugin_definition.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { resolve } from 'path'; -import { plugin } from './server/np_ready'; -import { PLUGIN } from './common/constants'; - -export const pluginDefinition = { - id: PLUGIN.ID, - configPrefix: 'xpack.watcher', - publicDir: resolve(__dirname, 'public'), - require: ['kibana', 'elasticsearch', 'xpack_main'], - uiExports: { - styleSheetPaths: resolve(__dirname, 'public/np_ready/application/index.scss'), - managementSections: ['plugins/watcher/legacy'], - home: ['plugins/watcher/register_feature'], - }, - init(server: any) { - plugin({} as any).setup(server.newPlatform.setup.core, { - __LEGACY: { - route: server.route.bind(server), - plugins: { - watcher: server.plugins[PLUGIN.ID], - xpack_main: server.plugins.xpack_main, - }, - }, - }); - }, -}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/index.scss b/x-pack/legacy/plugins/watcher/public/index.scss similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/index.scss rename to x-pack/legacy/plugins/watcher/public/index.scss diff --git a/x-pack/legacy/plugins/watcher/public/legacy.ts b/x-pack/legacy/plugins/watcher/public/legacy.ts deleted file mode 100644 index 21fcd718ea1b73..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/legacy.ts +++ /dev/null @@ -1,147 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { CoreSetup, App, AppUnmount } from 'src/core/public'; -import { i18n } from '@kbn/i18n'; - -/* Legacy UI imports */ -import { npSetup, npStart } from 'ui/new_platform'; -import routes from 'ui/routes'; -import { management, MANAGEMENT_BREADCRUMB } from 'ui/management'; -import { TimeBuckets } from 'ui/time_buckets'; -// @ts-ignore -import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; -/* Legacy UI imports */ - -import { plugin } from './np_ready'; -import { PLUGIN } from '../common/constants'; -import { LICENSE_STATUS_INVALID, LICENSE_STATUS_UNAVAILABLE } from '../../../common/constants'; -import { manageAngularLifecycle } from './manage_angular_lifecycle'; - -const template = ` -
    -
    `; - -let elem: HTMLElement; -let mountApp: () => AppUnmount | Promise; -let unmountApp: AppUnmount | Promise; -routes.when('/management/elasticsearch/watcher/:param1?/:param2?/:param3?/:param4?', { - template, - controller: class WatcherController { - constructor($injector: any, $scope: any) { - const $route = $injector.get('$route'); - const licenseStatus = xpackInfo.get(`features.${PLUGIN.ID}`); - const shimCore: CoreSetup = { - ...npSetup.core, - application: { - ...npSetup.core.application, - register(app: App): void { - mountApp = () => - app.mount(npStart as any, { - element: elem, - appBasePath: '/management/elasticsearch/watcher/', - onAppLeave: () => undefined, - }); - }, - }, - }; - - // clean up previously rendered React app if one exists - // this happens because of React Router redirects - if (elem) { - ((unmountApp as unknown) as AppUnmount)(); - } - - $scope.$$postDigest(() => { - elem = document.getElementById('watchReactRoot')!; - const instance = plugin(); - instance.setup(shimCore, { - ...(npSetup.plugins as typeof npSetup.plugins & { eui_utils: any }), - __LEGACY: { - MANAGEMENT_BREADCRUMB, - TimeBuckets, - licenseStatus, - }, - }); - - instance.start(npStart.core, npStart.plugins); - - (mountApp() as Promise).then(fn => (unmountApp = fn)); - - manageAngularLifecycle($scope, $route, elem); - }); - } - } as any, - // @ts-ignore - controllerAs: 'watchRoute', -}); - -routes.defaults(/\/management/, { - resolve: { - watcherManagementSection: () => { - const watchesSection = management.getSection('elasticsearch/watcher'); - const licenseStatus = xpackInfo.get(`features.${PLUGIN.ID}`); - const { status } = licenseStatus; - - if (status === LICENSE_STATUS_INVALID || status === LICENSE_STATUS_UNAVAILABLE) { - return watchesSection.hide(); - } - - watchesSection.show(); - }, - }, -}); - -management.getSection('elasticsearch').register('watcher', { - display: i18n.translate('xpack.watcher.sections.watchList.managementSection.watcherDisplayName', { - defaultMessage: 'Watcher', - }), - order: 6, - url: '#/management/elasticsearch/watcher/', -} as any); - -management.getSection('elasticsearch/watcher').register('watches', { - display: i18n.translate('xpack.watcher.sections.watchList.managementSection.watchesDisplayName', { - defaultMessage: 'Watches', - }), - order: 1, -} as any); - -management.getSection('elasticsearch/watcher').register('watch', { - visible: false, -} as any); - -management.getSection('elasticsearch/watcher/watch').register('status', { - display: i18n.translate('xpack.watcher.sections.watchList.managementSection.statusDisplayName', { - defaultMessage: 'Status', - }), - order: 1, - visible: false, -} as any); - -management.getSection('elasticsearch/watcher/watch').register('edit', { - display: i18n.translate('xpack.watcher.sections.watchList.managementSection.editDisplayName', { - defaultMessage: 'Edit', - }), - order: 2, - visible: false, -} as any); - -management.getSection('elasticsearch/watcher/watch').register('new', { - display: i18n.translate( - 'xpack.watcher.sections.watchList.managementSection.newWatchDisplayName', - { - defaultMessage: 'New Watch', - } - ), - order: 1, - visible: false, -} as any); - -management.getSection('elasticsearch/watcher/watch').register('history-item', { - order: 1, - visible: false, -} as any); diff --git a/x-pack/legacy/plugins/watcher/public/manage_angular_lifecycle.ts b/x-pack/legacy/plugins/watcher/public/manage_angular_lifecycle.ts deleted file mode 100644 index efd40eaf83daad..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/manage_angular_lifecycle.ts +++ /dev/null @@ -1,28 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { unmountComponentAtNode } from 'react-dom'; - -export const manageAngularLifecycle = ($scope: any, $route: any, elem: HTMLElement) => { - const lastRoute = $route.current; - - const deregister = $scope.$on('$locationChangeSuccess', () => { - const currentRoute = $route.current; - if (lastRoute.$$route.template === currentRoute.$$route.template) { - $route.current = lastRoute; - } - }); - - $scope.$on('$destroy', () => { - if (deregister) { - deregister(); - } - - if (elem) { - unmountComponentAtNode(elem); - } - }); -}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/app_context.tsx b/x-pack/legacy/plugins/watcher/public/np_ready/application/app_context.tsx deleted file mode 100644 index 5696ab3cb91ba1..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/app_context.tsx +++ /dev/null @@ -1,65 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { createContext, useContext } from 'react'; -import { DocLinksStart } from 'src/core/public'; -import { ACTION_TYPES } from '../../../common/constants'; -import { AppDeps } from './app'; - -interface ContextValue extends Omit { - links: ReturnType; -} - -const AppContext = createContext(null as any); - -const generateDocLinks = ({ ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }: DocLinksStart) => { - const elasticDocLinkBase = `${ELASTIC_WEBSITE_URL}guide/en/`; - const esBase = `${elasticDocLinkBase}elasticsearch/reference/${DOC_LINK_VERSION}`; - const kibanaBase = `${elasticDocLinkBase}kibana/${DOC_LINK_VERSION}`; - const putWatchApiUrl = `${esBase}/watcher-api-put-watch.html`; - const executeWatchApiUrl = `${esBase}/watcher-api-execute-watch.html#watcher-api-execute-watch-action-mode`; - const watcherGettingStartedUrl = `${kibanaBase}/watcher-ui.html`; - const watchActionsConfigurationMap = { - [ACTION_TYPES.SLACK]: `${esBase}/actions-slack.html#configuring-slack`, - [ACTION_TYPES.PAGERDUTY]: `${esBase}/actions-pagerduty.html#configuring-pagerduty`, - [ACTION_TYPES.JIRA]: `${esBase}/actions-jira.html#configuring-jira`, - }; - - return { - putWatchApiUrl, - executeWatchApiUrl, - watcherGettingStartedUrl, - watchActionsConfigurationMap, - }; -}; - -export const AppContextProvider = ({ - children, - value, -}: { - value: AppDeps; - children: React.ReactNode; -}) => { - const { docLinks, ...rest } = value; - return ( - - {children} - - ); -}; - -export const useAppContext = () => { - const ctx = useContext(AppContext); - if (!ctx) { - throw new Error('"useAppContext" can only be called inside of AppContext.Provider!'); - } - return ctx; -}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/boot.tsx b/x-pack/legacy/plugins/watcher/public/np_ready/application/boot.tsx deleted file mode 100644 index 3f2a10f0046495..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/boot.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { SavedObjectsClientContract } from 'src/core/public'; - -import { App, AppDeps } from './app'; -import { setHttpClient, setSavedObjectsClient } from './lib/api'; -import { LegacyDependencies } from '../types'; - -interface BootDeps extends AppDeps { - element: HTMLElement; - savedObjects: SavedObjectsClientContract; - I18nContext: any; - legacy: LegacyDependencies; -} - -export const boot = (bootDeps: BootDeps) => { - const { I18nContext, element, legacy, savedObjects, ...appDeps } = bootDeps; - - setHttpClient(appDeps.http); - setSavedObjectsClient(savedObjects); - - render( - - - , - element - ); - return () => unmountComponentAtNode(element); -}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/watch_status.tsx b/x-pack/legacy/plugins/watcher/public/np_ready/application/components/watch_status.tsx deleted file mode 100644 index 8afd174f8561e6..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/watch_status.tsx +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { EuiIcon, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import { ACTION_STATES, WATCH_STATES } from '../../../../common/constants'; - -function StatusIcon({ status }: { status: string }) { - switch (status) { - case WATCH_STATES.FIRING: - case ACTION_STATES.FIRING: - return ; - case WATCH_STATES.OK: - case ACTION_STATES.OK: - case ACTION_STATES.ACKNOWLEDGED: - return ; - case ACTION_STATES.THROTTLED: - return ; - case WATCH_STATES.DISABLED: - return ; - case WATCH_STATES.CONFIG_ERROR: - case WATCH_STATES.ERROR: - case ACTION_STATES.CONFIG_ERROR: - case ACTION_STATES.ERROR: - return ; - } - return null; -} - -export function WatchStatus({ status, size = 's' }: { status: string; size?: 'xs' | 's' | 'm' }) { - return ( - - - - - - {status} - - - ); -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/api.ts b/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/api.ts deleted file mode 100644 index c08545904e3516..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/api.ts +++ /dev/null @@ -1,181 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import { HttpSetup, SavedObjectsClientContract } from 'src/core/public'; -import { Settings } from 'plugins/watcher/np_ready/application/models/settings'; -import { Watch } from 'plugins/watcher/np_ready/application/models/watch'; -import { WatchHistoryItem } from 'plugins/watcher/np_ready/application/models/watch_history_item'; -import { WatchStatus } from 'plugins/watcher/np_ready/application/models/watch_status'; - -import { BaseWatch, ExecutedWatchDetails } from '../../../../common/types/watch_types'; -import { useRequest, sendRequest } from './use_request'; - -import { ROUTES } from '../../../../common/constants'; - -let httpClient: HttpSetup; - -export const setHttpClient = (anHttpClient: HttpSetup) => { - httpClient = anHttpClient; -}; - -export const getHttpClient = () => { - return httpClient; -}; - -let savedObjectsClient: SavedObjectsClientContract; - -export const setSavedObjectsClient = (aSavedObjectsClient: SavedObjectsClientContract) => { - savedObjectsClient = aSavedObjectsClient; -}; - -export const getSavedObjectsClient = () => savedObjectsClient; - -const basePath = ROUTES.API_ROOT; - -export const useLoadWatches = (pollIntervalMs: number) => { - return useRequest({ - path: `${basePath}/watches`, - method: 'get', - pollIntervalMs, - deserializer: ({ watches = [] }: { watches: any[] }) => { - return watches.map((watch: any) => Watch.fromUpstreamJson(watch)); - }, - }); -}; - -export const useLoadWatchDetail = (id: string) => { - return useRequest({ - path: `${basePath}/watch/${id}`, - method: 'get', - deserializer: ({ watch = {} }: { watch: any }) => Watch.fromUpstreamJson(watch), - }); -}; - -export const useLoadWatchHistory = (id: string, startTime: string) => { - return useRequest({ - query: startTime ? { startTime } : undefined, - path: `${basePath}/watch/${id}/history`, - method: 'get', - deserializer: ({ watchHistoryItems = [] }: { watchHistoryItems: any }) => { - return watchHistoryItems.map((historyItem: any) => - WatchHistoryItem.fromUpstreamJson(historyItem) - ); - }, - }); -}; - -export const useLoadWatchHistoryDetail = (id: string | undefined) => { - return useRequest({ - path: !id ? '' : `${basePath}/history/${id}`, - method: 'get', - deserializer: ({ watchHistoryItem }: { watchHistoryItem: any }) => - WatchHistoryItem.fromUpstreamJson(watchHistoryItem), - }); -}; - -export const deleteWatches = async (watchIds: string[]) => { - const body = JSON.stringify({ - watchIds, - }); - const { results } = await getHttpClient().post(`${basePath}/watches/delete`, { body }); - return results; -}; - -export const deactivateWatch = async (id: string) => { - return sendRequest({ - path: `${basePath}/watch/${id}/deactivate`, - method: 'put', - }); -}; - -export const activateWatch = async (id: string) => { - return sendRequest({ - path: `${basePath}/watch/${id}/activate`, - method: 'put', - }); -}; - -export const loadWatch = async (id: string) => { - const { watch } = await getHttpClient().get(`${basePath}/watch/${id}`); - return Watch.fromUpstreamJson(watch); -}; - -export const getMatchingIndices = async (pattern: string) => { - if (!pattern.startsWith('*')) { - pattern = `*${pattern}`; - } - if (!pattern.endsWith('*')) { - pattern = `${pattern}*`; - } - const body = JSON.stringify({ pattern }); - const { indices } = await getHttpClient().post(`${basePath}/indices`, { body }); - return indices; -}; - -export const fetchFields = async (indexes: string[]) => { - const { fields } = await getHttpClient().post(`${basePath}/fields`, { - body: JSON.stringify({ indexes }), - }); - return fields; -}; - -export const createWatch = async (watch: BaseWatch) => { - return await getHttpClient().put(`${basePath}/watch/${watch.id}`, { - body: JSON.stringify(watch.upstreamJson), - }); -}; - -export const executeWatch = async (executeWatchDetails: ExecutedWatchDetails, watch: BaseWatch) => { - return sendRequest({ - path: `${basePath}/watch/execute`, - method: 'put', - body: JSON.stringify({ - executeDetails: executeWatchDetails.upstreamJson, - watch: watch.upstreamJson, - }), - }); -}; - -export const loadIndexPatterns = async () => { - const { savedObjects } = await getSavedObjectsClient().find({ - type: 'index-pattern', - fields: ['title'], - perPage: 10000, - }); - return savedObjects; -}; - -export const useGetWatchVisualizationData = (watchModel: BaseWatch, visualizeOptions: any) => { - return useRequest({ - path: `${basePath}/watch/visualize`, - method: 'post', - body: JSON.stringify({ - watch: watchModel.upstreamJson, - options: visualizeOptions.upstreamJson, - }), - deserializer: ({ visualizeData }: { visualizeData: any }) => visualizeData, - }); -}; - -export const useLoadSettings = () => { - return useRequest({ - path: `${basePath}/settings`, - method: 'get', - deserializer: (data: { - action_types: { - [key: string]: { - enabled: boolean; - }; - }; - }) => Settings.fromUpstreamJson(data), - }); -}; - -export const ackWatchAction = async (watchId: string, actionId: string) => { - const { watchStatus } = await getHttpClient().put( - `${basePath}/watch/${watchId}/action/${actionId}/acknowledge` - ); - return WatchStatus.fromUpstreamJson(watchStatus); -}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/action.js b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/action.js deleted file mode 100644 index 5d5c44d7ae5341..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/action.js +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get, set } from 'lodash'; -import { ACTION_TYPES } from '../../../../../common/constants'; -import { EmailAction } from './email_action'; -import { LoggingAction } from './logging_action'; -import { SlackAction } from './slack_action'; -import { WebhookAction } from './webhook_action'; -import { IndexAction } from './index_action'; -import { PagerDutyAction } from './pagerduty_action'; -import { JiraAction } from './jira_action'; -import { UnknownAction } from './unknown_action'; - -const ActionTypes = {}; -set(ActionTypes, ACTION_TYPES.EMAIL, EmailAction); -set(ActionTypes, ACTION_TYPES.LOGGING, LoggingAction); -set(ActionTypes, ACTION_TYPES.SLACK, SlackAction); -set(ActionTypes, ACTION_TYPES.WEBHOOK, WebhookAction); -set(ActionTypes, ACTION_TYPES.INDEX, IndexAction); -set(ActionTypes, ACTION_TYPES.PAGERDUTY, PagerDutyAction); -set(ActionTypes, ACTION_TYPES.JIRA, JiraAction); - -export class Action { - static getActionTypes = () => { - return ActionTypes; - }; - - static fromUpstreamJson(upstreamAction) { - const type = get(upstreamAction, 'type'); - const ActionType = ActionTypes[type] || UnknownAction; - - return ActionType.fromUpstreamJson(upstreamAction); - } -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action_status/action_status.js b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action_status/action_status.js deleted file mode 100644 index b177eb5bb22914..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action_status/action_status.js +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get } from 'lodash'; -import { getMoment } from '../../../../../common/lib/get_moment'; - -export class ActionStatus { - constructor(props = {}) { - this.id = get(props, 'id'); - this.state = get(props, 'state'); - this.isAckable = get(props, 'isAckable'); - this.lastAcknowledged = getMoment(get(props, 'lastAcknowledged')); - this.lastThrottled = getMoment(get(props, 'lastThrottled')); - this.lastExecution = getMoment(get(props, 'lastExecution')); - this.lastExecutionSuccessful = get(props, 'lastExecutionSuccessful'); - this.lastExecutionReason = get(props, 'lastExecutionReason'); - this.lastSuccessfulExecution = getMoment(get(props, 'lastSuccessfulExecution')); - - if (this.lastAcknowledged) { - this.lastAcknowledgedHumanized = this.lastAcknowledged.fromNow(); - } - if (this.lastExecution) { - this.lastExecutionHumanized = this.lastExecution.fromNow(); - } - if (this.lastThrottled) { - this.lastThrottledHumanized = this.lastThrottled.fromNow(); - } - } - - static fromUpstreamJson(upstreamActionStatus) { - return new ActionStatus(upstreamActionStatus); - } -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/index.d.ts b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/index.d.ts deleted file mode 100644 index a8ddb6ca2b76db..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/index.d.ts +++ /dev/null @@ -1,39 +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; - * you may not use this file except in compliance with the Elastic License. - */ -declare module 'plugins/watcher/np_ready/application/models/visualize_options' { - export const VisualizeOptions: any; -} - -declare module 'plugins/watcher/np_ready/application/models/watch' { - export const Watch: any; -} - -declare module 'plugins/watcher/np_ready/application/models/watch/threshold_watch' { - export const ThresholdWatch: any; -} - -declare module 'plugins/watcher/np_ready/application/models/watch/json_watch' { - export const JsonWatch: any; -} - -declare module 'plugins/watcher/np_ready/application/models/execute_details/execute_details' { - export const ExecuteDetails: any; -} - -declare module 'plugins/watcher/np_ready/application/models/watch_history_item' { - export const WatchHistoryItem: any; -} - -declare module 'plugins/watcher/np_ready/application/models/watch_status' { - export const WatchStatus: any; -} - -declare module 'plugins/watcher/np_ready/application/models/settings' { - export const Settings: any; -} -declare module 'plugins/watcher/np_ready/application/models/action' { - export const Action: any; -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/json_watch.js b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/json_watch.js deleted file mode 100644 index 2d18c233ed5b45..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/json_watch.js +++ /dev/null @@ -1,126 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import uuid from 'uuid'; -import { get } from 'lodash'; -import { BaseWatch } from './base_watch'; -import { ACTION_TYPES, WATCH_TYPES } from '../../../../../common/constants'; -import defaultWatchJson from './default_watch.json'; -import { i18n } from '@kbn/i18n'; - -/** - * {@code JsonWatch} allows a user to create a Watch by writing the raw JSON. - */ -export class JsonWatch extends BaseWatch { - constructor(props = {}) { - props.type = WATCH_TYPES.JSON; - props.id = typeof props.id === 'undefined' ? uuid.v4() : props.id; - super(props); - const existingWatch = get(props, 'watch'); - this.watch = existingWatch ? existingWatch : defaultWatchJson; - this.watchString = get( - props, - 'watchString', - JSON.stringify(existingWatch ? existingWatch : defaultWatchJson, null, 2) - ); - this.id = props.id; - } - - validate() { - const validationResult = {}; - const idRegex = /^[A-Za-z0-9\-\_]+$/; - const errors = { - id: [], - json: [], - }; - validationResult.errors = errors; - // Watch id validation - if (!this.id) { - errors.id.push( - i18n.translate('xpack.watcher.sections.watchEdit.json.error.requiredIdText', { - defaultMessage: 'ID is required', - }) - ); - } else if (!idRegex.test(this.id)) { - errors.id.push( - i18n.translate('xpack.watcher.sections.watchEdit.json.error.invalidIdText', { - defaultMessage: 'ID can only contain letters, underscores, dashes, and numbers.', - }) - ); - } - // JSON validation - if (!this.watchString || this.watchString === '') { - errors.json.push( - i18n.translate('xpack.watcher.sections.watchEdit.json.error.requiredJsonText', { - defaultMessage: 'JSON is required', - }) - ); - } else { - try { - const parsedJson = JSON.parse(this.watchString); - if (parsedJson && typeof parsedJson === 'object') { - const { actions } = parsedJson; - if (actions) { - // Validate if the action(s) provided is one of the supported actions - const invalidActions = Object.keys(actions).find(actionKey => { - const actionKeys = Object.keys(actions[actionKey]); - let type; - Object.keys(ACTION_TYPES).forEach(actionTypeKey => { - if ( - actionKeys.includes(ACTION_TYPES[actionTypeKey]) && - !actionKeys.includes(ACTION_TYPES.UNKNOWN) - ) { - type = ACTION_TYPES[actionTypeKey]; - } - }); - return !type; - }); - if (invalidActions) { - errors.json.push( - i18n.translate('xpack.watcher.sections.watchEdit.json.error.invalidActionType', { - defaultMessage: 'Unknown action type provided for action "{action}".', - values: { - action: invalidActions, - }, - }) - ); - } - } - } - } catch (e) { - errors.json.push( - i18n.translate('xpack.watcher.sections.watchEdit.json.error.invalidJsonText', { - defaultMessage: 'Invalid JSON', - }) - ); - } - } - return validationResult; - } - - get upstreamJson() { - const result = super.upstreamJson; - Object.assign(result, { - watch: this.watch, - }); - return result; - } - - static fromUpstreamJson(upstreamWatch) { - return new JsonWatch(upstreamWatch); - } - - static defaultWatchJson = defaultWatchJson; - static typeName = i18n.translate('xpack.watcher.models.jsonWatch.typeName', { - defaultMessage: 'Advanced Watch', - }); - static iconClass = ''; - static selectMessage = i18n.translate('xpack.watcher.models.jsonWatch.selectMessageText', { - defaultMessage: 'Set up a custom watch in raw JSON.', - }); - static isCreatable = true; - static selectSortOrder = 100; -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/monitoring_watch.js b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/monitoring_watch.js deleted file mode 100644 index 850953ebd963e7..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/monitoring_watch.js +++ /dev/null @@ -1,33 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { BaseWatch } from './base_watch'; -import { WATCH_TYPES } from '../../../../../common/constants'; - -/** - * {@code MonitoringWatch} system defined watches created by the Monitoring plugin. - */ -export class MonitoringWatch extends BaseWatch { - constructor(props = {}) { - props.type = WATCH_TYPES.MONITORING; - super(props); - } - - get upstreamJson() { - const result = super.upstreamJson; - Object.assign(result, { - watch: this.watch, - }); - - return result; - } - - static fromUpstreamJson(upstreamWatch) { - return new MonitoringWatch(upstreamWatch); - } - - static isCreatable = false; -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/threshold_watch.js b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/threshold_watch.js deleted file mode 100644 index 2383388dd89bf2..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/threshold_watch.js +++ /dev/null @@ -1,290 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { BaseWatch } from './base_watch'; -import uuid from 'uuid'; -import { WATCH_TYPES, SORT_ORDERS, COMPARATORS } from '../../../../../common/constants'; -import { getTimeUnitLabel } from '../../lib/get_time_unit_label'; -import { i18n } from '@kbn/i18n'; -import { aggTypes } from './agg_types'; -import { groupByTypes } from './group_by_types'; -import { comparators } from './comparators'; -const { BETWEEN } = COMPARATORS; -const DEFAULT_VALUES = { - AGG_TYPE: 'count', - TERM_SIZE: 5, - THRESHOLD_COMPARATOR: COMPARATORS.GREATER_THAN, - TIME_WINDOW_SIZE: 5, - TIME_WINDOW_UNIT: 'm', - TRIGGER_INTERVAL_SIZE: 1, - TRIGGER_INTERVAL_UNIT: 'm', - THRESHOLD: [1000, 5000], - GROUP_BY: 'all', -}; - -/** - * {@code ThresholdWatch} allows the user to create a watch by defining a threshold. - */ -export class ThresholdWatch extends BaseWatch { - constructor(props = {}) { - props.id = props.id || uuid.v4(); - props.type = WATCH_TYPES.THRESHOLD; - super(props); - - this.index = props.index; - this.timeField = props.timeField; - this.timeFields = props.timeFields || undefined; - this.triggerIntervalSize = - props.triggerIntervalSize == null - ? DEFAULT_VALUES.TRIGGER_INTERVAL_SIZE - : props.triggerIntervalSize; - this.triggerIntervalUnit = props.triggerIntervalUnit || DEFAULT_VALUES.TRIGGER_INTERVAL_UNIT; - this.aggType = props.aggType || DEFAULT_VALUES.AGG_TYPE; - this.aggField = props.aggField; - this.termSize = props.termSize == null ? DEFAULT_VALUES.TERM_SIZE : props.termSize; - this.termField = props.termField; - this.thresholdComparator = props.thresholdComparator || DEFAULT_VALUES.THRESHOLD_COMPARATOR; - this.timeWindowSize = - props.timeWindowSize == null ? DEFAULT_VALUES.TIME_WINDOW_SIZE : props.timeWindowSize; - this.timeWindowUnit = props.timeWindowUnit || DEFAULT_VALUES.TIME_WINDOW_UNIT; - this.groupBy = props.groupBy || DEFAULT_VALUES.GROUP_BY; - if (this.termField != null) { - this.groupBy = 'top'; - } - - //NOTE: The threshold must be of the appropriate type, i.e.,number/date. - //Conversion from string must occur by consumer when assigning a - //value to this property. - this.threshold = props.threshold == null ? DEFAULT_VALUES.THRESHOLD : props.threshold; - } - - get hasTermsAgg() { - return Boolean(this.termField); - } - - get termOrder() { - return this.thresholdComparator === COMPARATORS.GREATER_THAN - ? SORT_ORDERS.DESCENDING - : SORT_ORDERS.ASCENDING; - } - - get titleDescription() { - const staticPart = i18n.translate( - 'xpack.watcher.models.thresholdWatch.sendAlertOnSpecificConditionTitleDescription', - { - defaultMessage: 'Send an alert when your specified condition is met.', - } - ); - if (isNaN(this.triggerIntervalSize)) { - return staticPart; - } - - const timeUnitLabel = getTimeUnitLabel(this.triggerIntervalUnit, this.triggerIntervalSize); - const dynamicPartText = i18n.translate( - 'xpack.watcher.models.thresholdWatch.thresholdWatchIntervalTitleDescription', - { - defaultMessage: 'Your watch will run every {triggerIntervalSize} {timeUnitLabel}.', - values: { - triggerIntervalSize: this.triggerIntervalSize, - timeUnitLabel, - }, - } - ); - return `${staticPart} ${dynamicPartText}`; - } - validate() { - const validationResult = {}; - const errors = { - name: [], - index: [], - timeField: [], - triggerIntervalSize: [], - aggField: [], - termSize: [], - termField: [], - timeWindowSize: [], - }; - validationResult.errors = errors; - if (!this.name) { - errors.name.push( - i18n.translate('xpack.watcher.sections.watchEdit.threshold.error.requiredNameText', { - defaultMessage: 'Name is required.', - }) - ); - } - if (this.index !== undefined && this.index.length < 1) { - errors.index.push( - i18n.translate( - 'xpack.watcher.sections.watchEdit.threshold.enterOneOrMoreIndicesValidationMessage', - { - defaultMessage: 'Enter one or more indices.', - } - ) - ); - } - if ( - this.index !== undefined && - this.index.length > 0 && - this.timeFields !== undefined && - this.timeFields.length === 1 // first option will have empty value - ) { - errors.index.push( - i18n.translate('xpack.watcher.sections.watchEdit.threshold.invalidIndexValidationMessage', { - defaultMessage: 'Index does not have a time field.', - }) - ); - } - if (!this.timeField) { - errors.timeField.push( - i18n.translate( - 'xpack.watcher.sections.watchEdit.threshold.timeFieldIsRequiredValidationText', - { - defaultMessage: 'A time field is required.', - } - ) - ); - } - if (!this.triggerIntervalSize) { - errors.triggerIntervalSize.push( - i18n.translate( - 'xpack.watcher.sections.watchEdit.threshold.intervalSizeIsRequiredValidationMessage', - { - defaultMessage: 'Interval size is required.', - } - ) - ); - } - if (this.triggerIntervalSize !== undefined && this.triggerIntervalSize < 0) { - errors.triggerIntervalSize.push( - i18n.translate( - 'xpack.watcher.sections.watchEdit.threshold.intervalSizeNegativeNumberValidationMessage', - { - defaultMessage: 'Interval size cannot be a negative number.', - } - ) - ); - } - if (aggTypes[this.aggType].fieldRequired && !this.aggField) { - errors.aggField.push( - i18n.translate( - 'xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage', - { - defaultMessage: 'This field is required.', - } - ) - ); - } - // term field and term size only required if the group by type requires them - if (groupByTypes[this.groupBy].sizeRequired) { - if (!this.termSize) { - errors.termSize.push( - i18n.translate( - 'xpack.watcher.thresholdWatchExpression.aggType.xpack.watcher.thresholdWatchExpression.groupBy.requiredValueValidationMessage', - { - defaultMessage: 'A value is required.', - } - ) - ); - } - if (!this.termField) { - errors.termField.push( - i18n.translate( - 'xpack.watcher.thresholdWatchExpression.groupBy.requiredFieldValidationMessage', - { - defaultMessage: 'This field is required.', - } - ) - ); - } - } - - Array.from(Array(comparators[this.thresholdComparator].requiredValues)).forEach((value, i) => { - const key = `threshold${i}`; - errors[key] = []; - if (this.threshold[i] == null || this.threshold[i] === '') { - errors[key].push( - i18n.translate( - 'xpack.watcher.thresholdWatchExpression.thresholdLevel.valueIsRequiredValidationMessage', - { - defaultMessage: 'A value is required.', - } - ) - ); - } - }); - if ( - this.thresholdComparator === BETWEEN && - this.threshold[0] && - this.threshold[1] && - !(this.threshold[1] > this.threshold[0]) - ) { - errors.threshold1.push( - i18n.translate( - 'xpack.watcher.thresholdWatchExpression.thresholdLevel.secondValueMustBeGreaterMessage', - { - defaultMessage: 'Value must be greater than {lowerBound}.', - values: { - lowerBound: this.threshold[0], - }, - } - ) - ); - } - if (!this.timeWindowSize) { - errors.timeWindowSize.push( - i18n.translate( - 'xpack.watcher.thresholdWatchExpression.timeWindow.durationSizeIsRequiredValidationMessage', - { - defaultMessage: 'Window duration size is required.', - } - ) - ); - } - return validationResult; - } - get upstreamJson() { - const result = super.upstreamJson; - Object.assign(result, { - index: this.index, - timeField: this.timeField, - triggerIntervalSize: this.triggerIntervalSize, - triggerIntervalUnit: this.triggerIntervalUnit, - aggType: this.aggType, - aggField: this.aggField, - termSize: this.termSize, - termField: this.termField, - termOrder: this.termOrder, - thresholdComparator: this.thresholdComparator, - timeWindowSize: this.timeWindowSize, - timeWindowUnit: this.timeWindowUnit, - hasTermsAgg: this.hasTermsAgg, - threshold: - comparators[this.thresholdComparator].requiredValues > 1 - ? this.threshold - : this.threshold[0], - }); - - return result; - } - - static fromUpstreamJson(upstreamWatch) { - return new ThresholdWatch(upstreamWatch); - } - - get DEFAULT_VALUES() { - return DEFAULT_VALUES; - } - - static typeName = i18n.translate('xpack.watcher.models.thresholdWatch.typeName', { - defaultMessage: 'Threshold Alert', - }); - static iconClass = ''; - static selectMessage = i18n.translate('xpack.watcher.models.thresholdWatch.selectMessageText', { - defaultMessage: 'Send an alert on a specific condition', - }); - static isCreatable = true; - static selectSortOrder = 1; -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/watch.js b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/watch.js deleted file mode 100644 index fc33fab56d07c2..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/watch.js +++ /dev/null @@ -1,33 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get, set } from 'lodash'; -import { WATCH_TYPES } from '../../../../../common/constants'; -import { JsonWatch } from './json_watch'; -import { ThresholdWatch } from './threshold_watch'; -import { MonitoringWatch } from './monitoring_watch'; - -const WatchTypes = {}; -set(WatchTypes, WATCH_TYPES.JSON, JsonWatch); -set(WatchTypes, WATCH_TYPES.THRESHOLD, ThresholdWatch); -set(WatchTypes, WATCH_TYPES.MONITORING, MonitoringWatch); - -export class Watch { - static getWatchTypes = () => { - return WatchTypes; - }; - - static fromUpstreamJson(upstreamWatch = {}) { - const type = get(upstreamWatch, 'type'); - const WatchType = WatchTypes[type]; - - Object.assign(upstreamWatch, { - isNew: false, - }); - - return WatchType.fromUpstreamJson(upstreamWatch); - } -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_history_item/watch_history_item.js b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_history_item/watch_history_item.js deleted file mode 100644 index 785f9d19b23dd9..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_history_item/watch_history_item.js +++ /dev/null @@ -1,24 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import 'moment-duration-format'; -import { get } from 'lodash'; -import { getMoment } from '../../../../../common/lib/get_moment'; -import { WatchStatus } from '../watch_status'; - -export class WatchHistoryItem { - constructor(props = {}) { - this.id = props.id; - this.watchId = props.watchId; - this.details = props.details; - this.startTime = getMoment(props.startTime); - this.watchStatus = WatchStatus.fromUpstreamJson(get(props, 'watchStatus')); - } - - static fromUpstreamJson(upstreamHistory) { - return new WatchHistoryItem(upstreamHistory); - } -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_status/watch_status.js b/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_status/watch_status.js deleted file mode 100644 index 7b35493ebdfa22..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_status/watch_status.js +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get } from 'lodash'; -import { getMoment } from '../../../../../common/lib/get_moment'; -import { ActionStatus } from '../action_status'; - -export class WatchStatus { - constructor(props = {}) { - this.id = get(props, 'id'); - this.state = get(props, 'state'); - this.comment = get(props, 'comment'); - this.isActive = get(props, 'isActive'); - this.lastFired = getMoment(get(props, 'lastFired')); - this.lastChecked = getMoment(get(props, 'lastChecked')); - this.lastMetCondition = getMoment(get(props, 'lastMetCondition')); - - if (this.lastFired) { - this.lastFiredHumanized = this.lastFired.fromNow(); - } - - if (this.lastChecked) { - this.lastCheckedHumanized = this.lastChecked.fromNow(); - } - - const actionStatuses = get(props, 'actionStatuses', []); - this.actionStatuses = actionStatuses.map(actionStatus => - ActionStatus.fromUpstreamJson(actionStatus) - ); - } - - static fromUpstreamJson(upstreamWatchStatus) { - return new WatchStatus(upstreamWatchStatus); - } -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_status.tsx b/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_status.tsx deleted file mode 100644 index 53817c23e72eb7..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_status.tsx +++ /dev/null @@ -1,258 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useEffect, useState } from 'react'; -import { - EuiPageContent, - EuiSpacer, - EuiTabs, - EuiTab, - EuiFlexGroup, - EuiFlexItem, - EuiTitle, - EuiToolTip, - EuiBadge, - EuiButtonEmpty, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { WatchDetail } from './watch_detail'; -import { WatchHistory } from './watch_history'; -import { listBreadcrumb, statusBreadcrumb } from '../../../lib/breadcrumbs'; -import { useLoadWatchDetail, deactivateWatch, activateWatch } from '../../../lib/api'; -import { WatchDetailsContext } from '../watch_details_context'; -import { - getPageErrorCode, - PageError, - SectionLoading, - DeleteWatchesModal, -} from '../../../components'; -import { goToWatchList } from '../../../lib/navigation'; -import { useAppContext } from '../../../app_context'; - -interface WatchStatusTab { - id: string; - name: string; -} - -const WATCH_EXECUTION_HISTORY_TAB = 'watchExecutionHistoryTab'; -const WATCH_ACTIONS_TAB = 'watchActionsTab'; - -const WATCH_STATUS_TABS: WatchStatusTab[] = [ - { - id: WATCH_EXECUTION_HISTORY_TAB, - name: i18n.translate('xpack.watcher.sections.watchStatus.executionHistoryTabLabel', { - defaultMessage: 'Execution history', - }), - }, - { - id: WATCH_ACTIONS_TAB, - name: i18n.translate('xpack.watcher.sections.watchStatus.actionsTabLabel', { - defaultMessage: 'Action statuses', - }), - }, -]; - -export const WatchStatus = ({ - match: { - params: { id }, - }, -}: { - match: { - params: { - id: string; - }; - }; -}) => { - const { - chrome, - legacy: { MANAGEMENT_BREADCRUMB }, - toasts, - } = useAppContext(); - const { - error: watchDetailError, - data: watchDetail, - isLoading: isWatchDetailLoading, - } = useLoadWatchDetail(id); - - const [selectedTab, setSelectedTab] = useState(WATCH_EXECUTION_HISTORY_TAB); - const [isActivated, setIsActivated] = useState(undefined); - const [watchesToDelete, setWatchesToDelete] = useState([]); - const [isTogglingActivation, setIsTogglingActivation] = useState(false); - - useEffect(() => { - chrome.setBreadcrumbs([MANAGEMENT_BREADCRUMB, listBreadcrumb, statusBreadcrumb]); - }, [id, chrome, MANAGEMENT_BREADCRUMB]); - - const errorCode = getPageErrorCode(watchDetailError); - - if (isWatchDetailLoading) { - return ( - - - - ); - } - - if (errorCode) { - return ( - - - - ); - } - - if (watchDetail) { - const { isSystemWatch, id: watchId, watchStatus, name: watchName } = watchDetail; - - if (isActivated === undefined) { - // Set initial value for isActivated based on the watch we just loaded. - setIsActivated(typeof watchStatus.isActive !== 'undefined' ? watchStatus.isActive : false); - } - - const activationButtonText = isActivated ? ( - - ) : ( - - ); - - const toggleWatchActivation = async () => { - const toggleActivation = isActivated ? deactivateWatch : activateWatch; - - setIsTogglingActivation(true); - - const { error } = await toggleActivation(watchId); - - setIsTogglingActivation(false); - - if (error) { - const message = isActivated - ? i18n.translate( - 'xpack.watcher.sections.watchList.toggleActivatationErrorNotification.deactivateDescriptionText', - { - defaultMessage: "Couldn't deactivate watch", - } - ) - : i18n.translate( - 'xpack.watcher.sections.watchList.toggleActivatationErrorNotification.activateDescriptionText', - { - defaultMessage: "Couldn't activate watch", - } - ); - return toasts.addDanger(message); - } - - setIsActivated(!isActivated); - }; - - return ( - - - { - if (deleted) { - goToWatchList(); - } - setWatchesToDelete([]); - }} - watchesToDelete={watchesToDelete} - /> - - - -

    - -

    -
    -
    - {isSystemWatch ? ( - - - } - > - - - - - - ) : ( - - - - toggleWatchActivation()} - isLoading={isTogglingActivation} - > - {activationButtonText} - - - - { - setWatchesToDelete([watchId]); - }} - color="danger" - disabled={false} - > - - - - - - )} -
    - - - {WATCH_STATUS_TABS.map((tab, index) => ( - { - setSelectedTab(tab.id); - }} - isSelected={tab.id === selectedTab} - key={index} - data-test-subj="tab" - > - {tab.name} - - ))} - - - {selectedTab === WATCH_ACTIONS_TAB ? : } -
    -
    - ); - } - - return null; -}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/plugin.ts b/x-pack/legacy/plugins/watcher/public/np_ready/plugin.ts deleted file mode 100644 index 161de9b5fc0606..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/plugin.ts +++ /dev/null @@ -1,62 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; - -import { LegacyDependencies } from './types'; - -interface LegacyPlugins { - __LEGACY: LegacyDependencies; -} - -export class WatcherUIPlugin implements Plugin { - /* TODO: Remove this in future. We need this at mount (setup) but it's only available on start plugins. */ - euiUtils: any = null; - - setup({ application, notifications, http, uiSettings }: CoreSetup, { __LEGACY }: LegacyPlugins) { - application.register({ - id: 'watcher', - title: 'Watcher', - mount: async ( - { - core: { - docLinks, - chrome, - // Waiting for types to be updated. - // @ts-ignore - savedObjects, - i18n: { Context: I18nContext }, - }, - }, - { element } - ) => { - const euiUtils = this.euiUtils!; - const { boot } = await import('./application/boot'); - return boot({ - element, - toasts: notifications.toasts, - http, - uiSettings, - docLinks, - chrome, - euiUtils, - savedObjects: savedObjects.client, - I18nContext, - legacy: { - ...__LEGACY, - }, - }); - }, - }); - } - - start(core: CoreStart, { eui_utils }: any) { - // eslint-disable-next-line @typescript-eslint/camelcase - this.euiUtils = eui_utils; - } - - stop() {} -} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/types.ts b/x-pack/legacy/plugins/watcher/public/np_ready/types.ts deleted file mode 100644 index 22109f99c2c48b..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/np_ready/types.ts +++ /dev/null @@ -1,11 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export interface LegacyDependencies { - MANAGEMENT_BREADCRUMB: { text: string; href?: string }; - TimeBuckets: any; - licenseStatus: any; -} diff --git a/x-pack/legacy/plugins/watcher/public/register_feature.ts b/x-pack/legacy/plugins/watcher/public/register_feature.ts deleted file mode 100644 index 0de41e09f788e1..00000000000000 --- a/x-pack/legacy/plugins/watcher/public/register_feature.ts +++ /dev/null @@ -1,21 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { npSetup } from 'ui/new_platform'; -import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; - -npSetup.plugins.home.featureCatalogue.register({ - id: 'watcher', - title: 'Watcher', // This is a product name so we don't translate it. - category: FeatureCatalogueCategory.ADMIN, - description: i18n.translate('xpack.watcher.watcherDescription', { - defaultMessage: 'Detect changes in your data by creating, managing, and monitoring alerts.', - }), - icon: 'watchesApp', - path: '/app/kibana#/management/elasticsearch/watcher/watches', - showOnHomePage: true, -}); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/index.ts b/x-pack/legacy/plugins/watcher/server/np_ready/index.ts deleted file mode 100644 index 3f5e1a91209ead..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { PluginInitializerContext } from 'src/core/server'; -import { WatcherServerPlugin } from './plugin'; - -export const plugin = (ctx: PluginInitializerContext) => new WatcherServerPlugin(); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/legacy/plugins/watcher/server/np_ready/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js deleted file mode 100644 index 4a6ad50d6ebc57..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ /dev/null @@ -1,64 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { kibanaResponseFactory } from '../../../../../../../../../src/core/server'; -import { licensePreRoutingFactory } from '../license_pre_routing_factory'; -import { - LICENSE_STATUS_VALID, - LICENSE_STATUS_EXPIRED, -} from '../../../../../../../common/constants/license_status'; - -describe('license_pre_routing_factory', () => { - describe('#reportingFeaturePreRoutingFactory', () => { - let mockServer; - let mockLicenseCheckResults; - - beforeEach(() => { - mockServer = { - plugins: { - xpack_main: { - info: { - feature: () => ({ - getLicenseCheckResults: () => mockLicenseCheckResults, - }), - }, - }, - }, - }; - }); - - describe('status is not valid', () => { - beforeEach(() => { - mockLicenseCheckResults = { - status: LICENSE_STATUS_EXPIRED, - }; - }); - - it('replies with 403', () => { - const licensePreRouting = licensePreRoutingFactory(mockServer, () => {}); - const stubRequest = {}; - const response = licensePreRouting({}, stubRequest, kibanaResponseFactory); - expect(response.status).to.be(403); - }); - }); - - describe('status is valid', () => { - beforeEach(() => { - mockLicenseCheckResults = { - status: LICENSE_STATUS_VALID, - }; - }); - - it('replies with nothing', () => { - const licensePreRouting = licensePreRoutingFactory(mockServer, () => null); - const stubRequest = {}; - const response = licensePreRouting({}, stubRequest, kibanaResponseFactory); - expect(response).to.be(null); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/license_pre_routing_factory/license_pre_routing_factory.ts b/x-pack/legacy/plugins/watcher/server/np_ready/lib/license_pre_routing_factory/license_pre_routing_factory.ts deleted file mode 100644 index d2f49672461047..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/lib/license_pre_routing_factory/license_pre_routing_factory.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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - KibanaRequest, - KibanaResponseFactory, - RequestHandler, - RequestHandlerContext, -} from 'src/core/server'; -import { PLUGIN } from '../../../../common/constants'; -import { LICENSE_STATUS_VALID } from '../../../../../../common/constants/license_status'; -import { ServerShim } from '../../types'; - -export const licensePreRoutingFactory = ( - server: ServerShim, - handler: RequestHandler -): RequestHandler => { - const xpackMainPlugin = server.plugins.xpack_main; - - // License checking and enable/disable logic - return function licensePreRouting( - ctx: RequestHandlerContext, - request: KibanaRequest, - response: KibanaResponseFactory - ) { - const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); - const { status } = licenseCheckResults; - - if (status !== LICENSE_STATUS_VALID) { - return response.customError({ - body: { - message: licenseCheckResults.messsage, - }, - statusCode: 403, - }); - } - - return handler(ctx, request, response); - }; -}; diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/action_status/__tests__/action_status.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/action_status/__tests__/action_status.js deleted file mode 100644 index 21e27a1b12c460..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/action_status/__tests__/action_status.js +++ /dev/null @@ -1,344 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { ActionStatus } from '../action_status'; -import { ACTION_STATES } from '../../../../../common/constants'; -import moment from 'moment'; - -describe('action_status', () => { - describe('ActionStatus', () => { - describe('fromUpstreamJson factory method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-action', - actionStatusJson: { - ack: { - timestamp: '2017-03-01T20:56:58.442Z', - state: 'acked', - }, - last_execution: { - timestamp: '2017-03-01T20:55:49.679Z', - successful: true, - reason: 'reasons', - }, - last_throttle: { - timestamp: '2017-03-01T20:55:49.679Z', - }, - last_successful_execution: { - timestamp: '2017-03-01T20:55:49.679Z', - successful: true, - }, - }, - }; - }); - - it(`throws an error if no 'id' property in json`, () => { - delete upstreamJson.id; - expect(ActionStatus.fromUpstreamJson) - .withArgs(upstreamJson) - .to.throwError('JSON argument must contain an "id" property'); - }); - - it(`throws an error if no 'actionStatusJson' property in json`, () => { - delete upstreamJson.actionStatusJson; - expect(ActionStatus.fromUpstreamJson) - .withArgs(upstreamJson) - .to.throwError('JSON argument must contain an "actionStatusJson" property'); - }); - - it('returns correct ActionStatus instance', () => { - const actionStatus = ActionStatus.fromUpstreamJson({ - ...upstreamJson, - errors: { foo: 'bar' }, - }); - - expect(actionStatus.id).to.be(upstreamJson.id); - expect(actionStatus.lastAcknowledged).to.eql( - moment(upstreamJson.actionStatusJson.ack.timestamp) - ); - expect(actionStatus.lastExecution).to.eql( - moment(upstreamJson.actionStatusJson.last_execution.timestamp) - ); - expect(actionStatus.lastExecutionSuccessful).to.eql( - upstreamJson.actionStatusJson.last_execution.successful - ); - expect(actionStatus.lastExecutionReason).to.be( - upstreamJson.actionStatusJson.last_execution.reason - ); - expect(actionStatus.lastThrottled).to.eql( - moment(upstreamJson.actionStatusJson.last_throttle.timestamp) - ); - expect(actionStatus.lastSuccessfulExecution).to.eql( - moment(upstreamJson.actionStatusJson.last_successful_execution.timestamp) - ); - expect(actionStatus.errors).to.eql({ foo: 'bar' }); - }); - }); - - describe('state getter method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-action', - actionStatusJson: { - ack: { - timestamp: '2017-03-01T20:56:58.442Z', - state: 'acked', - }, - last_execution: { - timestamp: '2017-03-01T20:55:49.679Z', - successful: true, - reason: 'reasons', - }, - last_throttle: { - timestamp: '2017-03-01T20:55:49.679Z', - }, - last_successful_execution: { - timestamp: '2017-03-01T20:55:49.679Z', - successful: true, - }, - }, - }; - }); - - it(`correctly calculates ACTION_STATES.ERROR`, () => { - upstreamJson.actionStatusJson.last_execution.successful = false; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.ERROR); - }); - - it('correctly calculates ACTION_STATES.CONFIG_ERROR', () => { - const actionStatus = ActionStatus.fromUpstreamJson({ - ...upstreamJson, - errors: { foo: 'bar' }, - }); - expect(actionStatus.state).to.be(ACTION_STATES.CONFIG_ERROR); - }); - - it(`correctly calculates ACTION_STATES.OK`, () => { - upstreamJson.actionStatusJson.ack.state = 'awaits_successful_execution'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.OK); - }); - - describe(`correctly calculates ACTION_STATES.ACKNOWLEDGED`, () => { - it(`when lastAcknowledged is equal to lastExecution`, () => { - upstreamJson.actionStatusJson.ack.state = 'acked'; - upstreamJson.actionStatusJson.ack.timestamp = '2017-03-01T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.ACKNOWLEDGED); - }); - - it(`when lastAcknowledged is greater than lastExecution`, () => { - upstreamJson.actionStatusJson.ack.state = 'acked'; - upstreamJson.actionStatusJson.ack.timestamp = '2017-03-02T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.ACKNOWLEDGED); - }); - }); - - describe(`correctly calculates ACTION_STATES.THROTTLED`, () => { - it(`when lastThrottled is equal to lastExecution`, () => { - upstreamJson.actionStatusJson.ack.state = 'ackable'; - upstreamJson.actionStatusJson.last_throttle.timestamp = '2017-03-01T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.THROTTLED); - }); - - it(`when lastThrottled is greater than lastExecution`, () => { - upstreamJson.actionStatusJson.ack.state = 'ackable'; - upstreamJson.actionStatusJson.last_throttle.timestamp = '2017-03-02T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.THROTTLED); - }); - }); - - describe(`correctly calculates ACTION_STATES.FIRING`, () => { - it(`when lastSuccessfulExecution is equal to lastExecution`, () => { - delete upstreamJson.actionStatusJson.last_throttle; - upstreamJson.actionStatusJson.ack.state = 'ackable'; - upstreamJson.actionStatusJson.last_successful_execution.timestamp = - '2017-03-01T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.FIRING); - }); - - it(`when lastSuccessfulExecution is greater than lastExecution`, () => { - delete upstreamJson.actionStatusJson.last_throttle; - upstreamJson.actionStatusJson.ack.state = 'ackable'; - upstreamJson.actionStatusJson.last_successful_execution.timestamp = - '2017-03-02T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.FIRING); - }); - }); - - it(`correctly calculates ACTION_STATES.ERROR`, () => { - delete upstreamJson.actionStatusJson.last_throttle; - upstreamJson.actionStatusJson.ack.state = 'ackable'; - upstreamJson.actionStatusJson.last_successful_execution.timestamp = - '2017-03-01T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-02T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.ERROR); - }); - - it(`throws an error if it can not determine ACTION_STATE`, () => { - upstreamJson = { - id: 'my-action', - actionStatusJson: { - ack: { state: 'foo' }, - last_successful_execution: { successful: true }, - }, - }; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(() => { - actionStatus.state; - }).to.throwError(/could not determine action status/i); - }); - }); - - describe('isAckable getter method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-action', - actionStatusJson: { - ack: { - timestamp: '2017-03-01T20:56:58.442Z', - state: 'acked', - }, - last_execution: { - timestamp: '2017-03-01T20:55:49.679Z', - successful: true, - reason: 'reasons', - }, - last_throttle: { - timestamp: '2017-03-01T20:55:49.679Z', - }, - last_successful_execution: { - timestamp: '2017-03-01T20:55:49.679Z', - successful: true, - }, - }, - }; - }); - - it(`correctly calculated isAckable when in ACTION_STATES.OK`, () => { - upstreamJson.actionStatusJson.ack.state = 'awaits_successful_execution'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.OK); - expect(actionStatus.isAckable).to.be(false); - }); - - it(`correctly calculated isAckable when in ACTION_STATES.ACKNOWLEDGED`, () => { - upstreamJson.actionStatusJson.ack.state = 'acked'; - upstreamJson.actionStatusJson.ack.timestamp = '2017-03-01T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.ACKNOWLEDGED); - expect(actionStatus.isAckable).to.be(false); - }); - - it(`correctly calculated isAckable when in ACTION_STATES.THROTTLED`, () => { - upstreamJson.actionStatusJson.ack.state = 'ackable'; - upstreamJson.actionStatusJson.last_throttle.timestamp = '2017-03-01T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.THROTTLED); - expect(actionStatus.isAckable).to.be(true); - }); - - it(`correctly calculated isAckable when in ACTION_STATES.FIRING`, () => { - delete upstreamJson.actionStatusJson.last_throttle; - upstreamJson.actionStatusJson.ack.state = 'ackable'; - upstreamJson.actionStatusJson.last_successful_execution.timestamp = - '2017-03-01T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.FIRING); - expect(actionStatus.isAckable).to.be(true); - }); - - it(`correctly calculated isAckable when in ACTION_STATES.ERROR`, () => { - delete upstreamJson.actionStatusJson.last_throttle; - upstreamJson.actionStatusJson.ack.state = 'ackable'; - upstreamJson.actionStatusJson.last_successful_execution.timestamp = - '2017-03-01T00:00:00.000Z'; - upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-02T00:00:00.000Z'; - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - expect(actionStatus.state).to.be(ACTION_STATES.ERROR); - expect(actionStatus.isAckable).to.be(false); - }); - }); - - describe('downstreamJson getter method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-action', - actionStatusJson: { - ack: { - timestamp: '2017-03-01T20:56:58.442Z', - state: 'acked', - }, - last_execution: { - timestamp: '2017-03-01T20:55:49.679Z', - successful: true, - reason: 'reasons', - }, - last_throttle: { - timestamp: '2017-03-01T20:55:49.679Z', - }, - last_successful_execution: { - timestamp: '2017-03-01T20:55:49.679Z', - successful: true, - }, - }, - }; - }); - - it('returns correct JSON for client', () => { - const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); - - const json = actionStatus.downstreamJson; - - expect(json.id).to.be(actionStatus.id); - expect(json.state).to.be(actionStatus.state); - expect(json.isAckable).to.be(actionStatus.isAckable); - expect(json.lastAcknowledged).to.be(actionStatus.lastAcknowledged); - expect(json.lastThrottled).to.be(actionStatus.lastThrottled); - expect(json.lastExecution).to.be(actionStatus.lastExecution); - expect(json.lastExecutionSuccessful).to.be(actionStatus.lastExecutionSuccessful); - expect(json.lastExecutionReason).to.be(actionStatus.lastExecutionReason); - expect(json.lastSuccessfulExecution).to.be(actionStatus.lastSuccessfulExecution); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/action_status/action_status.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/action_status/action_status.js deleted file mode 100644 index 6a484e7d4303a1..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/action_status/action_status.js +++ /dev/null @@ -1,141 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get } from 'lodash'; -import { badImplementation, badRequest } from 'boom'; -import { getMoment } from '../../../../common/lib/get_moment'; -import { ACTION_STATES } from '../../../../common/constants'; -import { i18n } from '@kbn/i18n'; - -export class ActionStatus { - constructor(props) { - this.id = props.id; - this.actionStatusJson = props.actionStatusJson; - this.errors = props.errors; - - this.lastAcknowledged = getMoment(get(this.actionStatusJson, 'ack.timestamp')); - this.lastExecution = getMoment(get(this.actionStatusJson, 'last_execution.timestamp')); - this.lastExecutionSuccessful = get(this.actionStatusJson, 'last_execution.successful'); - this.lastExecutionReason = get(this.actionStatusJson, 'last_execution.reason'); - this.lastThrottled = getMoment(get(this.actionStatusJson, 'last_throttle.timestamp')); - this.lastSuccessfulExecution = getMoment( - get(this.actionStatusJson, 'last_successful_execution.timestamp') - ); - } - - get state() { - const actionStatusJson = this.actionStatusJson; - const ackState = actionStatusJson.ack.state; - - if (this.lastExecutionSuccessful === false) { - return ACTION_STATES.ERROR; - } - - if (this.errors) { - return ACTION_STATES.CONFIG_ERROR; - } - - if (ackState === 'awaits_successful_execution') { - return ACTION_STATES.OK; - } - - if (ackState === 'acked' && this.lastAcknowledged >= this.lastExecution) { - return ACTION_STATES.ACKNOWLEDGED; - } - - if (ackState === 'ackable' && this.lastThrottled >= this.lastExecution) { - return ACTION_STATES.THROTTLED; - } - - if (ackState === 'ackable' && this.lastSuccessfulExecution >= this.lastExecution) { - return ACTION_STATES.FIRING; - } - - if (ackState === 'ackable' && this.lastSuccessfulExecution < this.lastExecution) { - return ACTION_STATES.ERROR; - } - - // At this point, we cannot determine the action status so we thrown an error. - // We should never get to this point in the code. If we do, it means we are - // missing an action status and the logic to determine it. - throw badImplementation( - i18n.translate( - 'xpack.watcher.models.actionStatus.notDetermineActionStatusBadImplementationMessage', - { - defaultMessage: 'Could not determine action status; action = {actionStatusJson}', - values: { - actionStatusJson: JSON.stringify(actionStatusJson), - }, - } - ) - ); - } - - get isAckable() { - if (this.state === ACTION_STATES.THROTTLED || this.state === ACTION_STATES.FIRING) { - return true; - } - - return false; - } - - // generate object to send to kibana - get downstreamJson() { - const json = { - id: this.id, - state: this.state, - isAckable: this.isAckable, - lastAcknowledged: this.lastAcknowledged, - lastThrottled: this.lastThrottled, - lastExecution: this.lastExecution, - lastExecutionSuccessful: this.lastExecutionSuccessful, - lastExecutionReason: this.lastExecutionReason, - lastSuccessfulExecution: this.lastSuccessfulExecution, - }; - - return json; - } - - // generate object from elasticsearch response - static fromUpstreamJson(json) { - const missingPropertyError = missingProperty => - i18n.translate( - 'xpack.watcher.models.actionStatus.actionStatusJsonPropertyMissingBadRequestMessage', - { - defaultMessage: 'JSON argument must contain an "{missingProperty}" property', - values: { missingProperty }, - } - ); - - if (!json.id) { - throw badRequest(missingPropertyError('id')); - } - - if (!json.actionStatusJson) { - throw badRequest(missingPropertyError('actionStatusJson')); - } - - return new ActionStatus(json); - } - - /* - json.actionStatusJson should have the following structure: - { - "ack": { - "timestamp": "2017-03-01T20:56:58.442Z", - "state": "acked" - }, - "last_execution": { - "timestamp": "2017-03-01T20:55:49.679Z", - "successful": true - }, - "last_successful_execution": { - "timestamp": "2017-03-01T20:55:49.679Z", - "successful": true - } - } - */ -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/json_watch.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/json_watch.js deleted file mode 100644 index 2440d4ef338816..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/json_watch.js +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { isEmpty, cloneDeep, has, merge } from 'lodash'; -import { BaseWatch } from './base_watch'; -import { WATCH_TYPES } from '../../../../common/constants'; -import { serializeJsonWatch } from '../../../../common/lib/serialization'; - -export class JsonWatch extends BaseWatch { - // This constructor should not be used directly. - // JsonWatch objects should be instantiated using the - // fromUpstreamJson and fromDownstreamJson static methods - constructor(props) { - super(props); - - this.watch = props.watch; - } - - get watchJson() { - return serializeJsonWatch(this.name, this.watch); - } - - // To Kibana - get downstreamJson() { - const result = merge({}, super.downstreamJson, { - watch: this.watch, - }); - - return result; - } - - // From Elasticsearch - static fromUpstreamJson(json, options) { - const baseProps = super.getPropsFromUpstreamJson(json, options); - const watch = cloneDeep(baseProps.watchJson); - - if (has(watch, 'metadata.name')) { - delete watch.metadata.name; - } - if (has(watch, 'metadata.xpack')) { - delete watch.metadata.xpack; - } - - if (isEmpty(watch.metadata)) { - delete watch.metadata; - } - - const props = merge({}, baseProps, { - type: WATCH_TYPES.JSON, - watch, - }); - - return new JsonWatch(props); - } - - // From Kibana - static fromDownstreamJson(json) { - const props = merge({}, super.getPropsFromDownstreamJson(json), { - type: WATCH_TYPES.JSON, - watch: json.watch, - }); - - return new JsonWatch(props); - } -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/monitoring_watch.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/monitoring_watch.js deleted file mode 100644 index 4aced5d0092d96..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/monitoring_watch.js +++ /dev/null @@ -1,99 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { merge } from 'lodash'; -import { badRequest } from 'boom'; -import { BaseWatch } from './base_watch'; -import { WATCH_TYPES } from '../../../../common/constants'; -import { i18n } from '@kbn/i18n'; - -export class MonitoringWatch extends BaseWatch { - // This constructor should not be used directly. - // JsonWatch objects should be instantiated using the - // fromUpstreamJson and fromDownstreamJson static methods - constructor(props) { - super(props); - - this.isSystemWatch = true; - } - - get watchJson() { - const result = merge({}, super.watchJson); - - return result; - } - - getVisualizeQuery() { - throw badRequest( - i18n.translate( - 'xpack.watcher.models.monitoringWatch.getVisualizeQueryCalledBadRequestMessage', - { - defaultMessage: '{getVisualizeQuery} called for monitoring watch', - values: { - getVisualizeQuery: 'getVisualizeQuery', - }, - } - ) - ); - } - - formatVisualizeData() { - throw badRequest( - i18n.translate( - 'xpack.watcher.models.monitoringWatch.formatVisualizeDataCalledBadRequestMessage', - { - defaultMessage: '{formatVisualizeData} called for monitoring watch', - values: { - formatVisualizeData: 'formatVisualizeData', - }, - } - ) - ); - } - - // To Elasticsearch - get upstreamJson() { - throw badRequest( - i18n.translate('xpack.watcher.models.monitoringWatch.upstreamJsonCalledBadRequestMessage', { - defaultMessage: '{upstreamJson} called for monitoring watch', - values: { - upstreamJson: 'upstreamJson', - }, - }) - ); - } - - // To Kibana - get downstreamJson() { - const result = merge({}, super.downstreamJson); - - return result; - } - - // From Elasticsearch - static fromUpstreamJson(json) { - const props = merge({}, super.getPropsFromUpstreamJson(json), { - type: WATCH_TYPES.MONITORING, - }); - - return new MonitoringWatch(props); - } - - // From Kibana - static fromDownstreamJson() { - throw badRequest( - i18n.translate( - 'xpack.watcher.models.monitoringWatch.fromDownstreamJsonCalledBadRequestMessage', - { - defaultMessage: '{fromDownstreamJson} called for monitoring watch', - values: { - fromDownstreamJson: 'fromDownstreamJson', - }, - } - ) - ); - } -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/__tests__/format_visualize_data.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/__tests__/format_visualize_data.js deleted file mode 100644 index 14aa8f7873e18f..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/__tests__/format_visualize_data.js +++ /dev/null @@ -1,325 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { AGG_TYPES } from '../../../../../../common/constants'; -import { formatVisualizeData } from '../format_visualize_data'; - -describe('watch', () => { - describe('formatVisualizeData', () => { - it('correctly formats data from a Count query', () => { - const watch = { - aggType: AGG_TYPES.COUNT, - termField: undefined, - }; - - const response = { - aggregations: { - dateAgg: { - buckets: [ - { - key_as_string: '2017-06-17T00:00:00.000-05:00', - key: 1497675600000, - doc_count: 13622, - }, - { - key_as_string: '2017-06-17T12:00:00.000-05:00', - key: 1497718800000, - doc_count: 13639, - }, - { - key_as_string: '2017-06-18T00:00:00.000-05:00', - key: 1497762000000, - doc_count: 13811, - }, - { - key_as_string: '2017-06-18T12:00:00.000-05:00', - key: 1497805200000, - doc_count: 13461, - }, - ], - }, - }, - }; - - const expected = { - count: [ - [1497675600000, 13622], - [1497718800000, 13639], - [1497762000000, 13811], - [1497805200000, 13461], - ], - }; - - const actual = formatVisualizeData(watch, response); - - expect(actual).to.eql(expected); - }); - - it('correctly formats data from a Count Terms query', () => { - const watch = { - aggType: AGG_TYPES.COUNT, - termField: 'foo_term_field', - }; - - const response = { - aggregations: { - bucketAgg: { - buckets: [ - { - key: 'foo_term', - dateAgg: { - buckets: [ - { - key: 1498366800000, - doc_count: 8878, - }, - { - key: 1498410000000, - doc_count: 8674, - }, - { - key: 1498453200000, - doc_count: 8720, - }, - ], - }, - }, - { - key: 'bar_term', - dateAgg: { - buckets: [ - { - key: 1498366800000, - doc_count: 2163, - }, - { - key: 1498410000000, - doc_count: 2202, - }, - { - key: 1498453200000, - doc_count: 2311, - }, - ], - }, - }, - { - key: 'baz_term', - dateAgg: { - buckets: [ - { - key: 1497675600000, - doc_count: 891, - }, - { - key: 1497718800000, - doc_count: 866, - }, - { - key: 1497762000000, - doc_count: 906, - }, - ], - }, - }, - ], - }, - }, - }; - - const expected = { - foo_term: [ - [1498366800000, 8878], - [1498410000000, 8674], - [1498453200000, 8720], - ], - bar_term: [ - [1498366800000, 2163], - [1498410000000, 2202], - [1498453200000, 2311], - ], - baz_term: [ - [1497675600000, 891], - [1497718800000, 866], - [1497762000000, 906], - ], - }; - - const actual = formatVisualizeData(watch, response); - - expect(actual).to.eql(expected); - }); - - it('correctly formats data from a Non-Count query', () => { - const watch = { - aggType: AGG_TYPES.AVERAGE, - termField: undefined, - }; - - const response = { - aggregations: { - dateAgg: { - buckets: [ - { - key: 1497675600000, - metricAgg: { - value: 5721.5481573924535, - }, - }, - { - key: 1497718800000, - metricAgg: { - value: 5696.727765965246, - }, - }, - { - key: 1497762000000, - metricAgg: { - value: 5725.888567084208, - }, - }, - ], - }, - }, - }; - - const expected = { - [AGG_TYPES.AVERAGE]: [ - [1497675600000, 5721.5481573924535], - [1497718800000, 5696.727765965246], - [1497762000000, 5725.888567084208], - ], - }; - - const actual = formatVisualizeData(watch, response); - - expect(actual).to.eql(expected); - }); - - it('correctly formats data from a Non-Count Terms query', () => { - const watch = { - aggType: AGG_TYPES.AVERAGE, - termField: 'foo_term_field', - }; - - const response = { - aggregations: { - bucketAgg: { - buckets: [ - { - key: 'foo_term', - dateAgg: { - buckets: [ - { - key: 1498366800000, - metricAgg: { - value: 10741.000753579503, - }, - }, - { - key: 1498410000000, - metricAgg: { - value: 10350.321100917432, - }, - }, - { - key: 1498453200000, - metricAgg: { - value: 10534.54078549849, - }, - }, - ], - }, - metricAgg: { - value: 10477.102294853963, - }, - }, - { - key: 'bar_term', - dateAgg: { - buckets: [ - { - key: 1498366800000, - metricAgg: { - value: 5629.317614424411, - }, - }, - { - key: 1498410000000, - metricAgg: { - value: 5548.141689373297, - }, - }, - { - key: 1498453200000, - metricAgg: { - value: 5603.887494591086, - }, - }, - ], - }, - metricAgg: { - value: 5595.034518438806, - }, - }, - { - key: 'baz_term', - dateAgg: { - buckets: [ - { - key: 1498366800000, - metricAgg: { - value: 5577.867537733724, - }, - }, - { - key: 1498410000000, - metricAgg: { - value: 5543.652870647913, - }, - }, - { - key: 1498453200000, - metricAgg: { - value: 5553.1327981651375, - }, - }, - ], - }, - metricAgg: { - value: 5567.288459750643, - }, - }, - ], - }, - }, - }; - - const expected = { - foo_term: [ - [1498366800000, 10741.000753579503], - [1498410000000, 10350.321100917432], - [1498453200000, 10534.54078549849], - ], - bar_term: [ - [1498366800000, 5629.317614424411], - [1498410000000, 5548.141689373297], - [1498453200000, 5603.887494591086], - ], - baz_term: [ - [1498366800000, 5577.867537733724], - [1498410000000, 5543.652870647913], - [1498453200000, 5553.1327981651375], - ], - }; - - const actual = formatVisualizeData(watch, response); - - expect(actual).to.eql(expected); - }); - }); -}); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/format_visualize_data.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/format_visualize_data.js deleted file mode 100644 index c8a6ac08df2c15..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/format_visualize_data.js +++ /dev/null @@ -1,85 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { AGG_TYPES } from '../../../../../common/constants'; - -export function formatVisualizeData({ aggType, termField }, results) { - if (aggType === AGG_TYPES.COUNT && !Boolean(termField)) { - return formatCount(aggType, results); - } - - if (aggType === AGG_TYPES.COUNT && Boolean(termField)) { - return formatCountTerms(results); - } - - if (aggType !== AGG_TYPES.COUNT && !Boolean(termField)) { - return formatNonCount(aggType, results); - } - - if (aggType !== AGG_TYPES.COUNT && Boolean(termField)) { - return formatNonCountTerms(results); - } -} - -// Count without terms -// See ./data_samples/count.json -function formatCount(aggType, results) { - const result = {}; - const buckets = results.aggregations.dateAgg.buckets; - - buckets.forEach(({ key: date, doc_count: value }) => { - result[aggType] = result[aggType] || []; - result[aggType].push([date, value]); - }); - - return result; -} - -// Count with terms -// See ./data_samples/count_terms.json -function formatCountTerms(results) { - const result = {}; - const buckets = results.aggregations.bucketAgg.buckets; - - buckets.forEach(({ key: term, dateAgg: { buckets: subBuckets } }) => { - subBuckets.forEach(({ key: date, doc_count: value }) => { - result[term] = result[term] || []; - result[term].push([date, value]); - }); - }); - - return result; -} - -// Other metric without terms -// See ./data_samples/non_count.json -function formatNonCount(aggType, results) { - const result = {}; - const buckets = results.aggregations.dateAgg.buckets; - - buckets.forEach(({ key: date, metricAgg: { value } }) => { - result[aggType] = result[aggType] || []; - result[aggType].push([date, value]); - }); - - return result; -} - -// Other metric with terms -// See ./data_samples/non_count_terms.json -function formatNonCountTerms(results) { - const result = {}; - const buckets = results.aggregations.bucketAgg.buckets; - - buckets.forEach(({ key: term, dateAgg: { buckets: subBuckets } }) => { - subBuckets.forEach(({ key: date, metricAgg: { value } }) => { - result[term] = result[term] || []; - result[term].push([date, value]); - }); - }); - - return result; -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/threshold_watch.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/threshold_watch.js deleted file mode 100644 index e5410588ab566c..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/threshold_watch.js +++ /dev/null @@ -1,140 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { merge } from 'lodash'; -import { BaseWatch } from '../base_watch'; -import { WATCH_TYPES, COMPARATORS, SORT_ORDERS } from '../../../../../common/constants'; -import { serializeThresholdWatch } from '../../../../../common/lib/serialization'; - -import { buildVisualizeQuery } from './build_visualize_query'; -import { formatVisualizeData } from './format_visualize_data'; - -export class ThresholdWatch extends BaseWatch { - // This constructor should not be used directly. - // JsonWatch objects should be instantiated using the - // fromUpstreamJson and fromDownstreamJson static methods - constructor(props) { - super(props); - - this.index = props.index; - this.timeField = props.timeField; - this.triggerIntervalSize = props.triggerIntervalSize; - this.triggerIntervalUnit = props.triggerIntervalUnit; - this.aggType = props.aggType; - this.aggField = props.aggField; - this.termSize = props.termSize; - this.termField = props.termField; - this.thresholdComparator = props.thresholdComparator; - this.timeWindowSize = props.timeWindowSize; - this.timeWindowUnit = props.timeWindowUnit; - this.threshold = props.threshold; - } - - get hasTermsAgg() { - return Boolean(this.termField); - } - - get termOrder() { - return this.thresholdComparator === COMPARATORS.GREATER_THAN - ? SORT_ORDERS.DESCENDING - : SORT_ORDERS.ASCENDING; - } - - get watchJson() { - return serializeThresholdWatch(this); - } - - getVisualizeQuery(visualizeOptions) { - return buildVisualizeQuery(this, visualizeOptions); - } - - formatVisualizeData(results) { - return formatVisualizeData(this, results); - } - - // To Kibana - get downstreamJson() { - const result = merge({}, super.downstreamJson, { - index: this.index, - timeField: this.timeField, - triggerIntervalSize: this.triggerIntervalSize, - triggerIntervalUnit: this.triggerIntervalUnit, - aggType: this.aggType, - aggField: this.aggField, - termSize: this.termSize, - termField: this.termField, - thresholdComparator: this.thresholdComparator, - timeWindowSize: this.timeWindowSize, - timeWindowUnit: this.timeWindowUnit, - threshold: this.threshold, - }); - - return result; - } - - // from Elasticsearch - static fromUpstreamJson(json) { - const metadata = json.watchJson.metadata.watcherui; - - const props = merge({}, super.getPropsFromUpstreamJson(json), { - type: WATCH_TYPES.THRESHOLD, - index: metadata.index, - timeField: metadata.time_field, - triggerIntervalSize: metadata.trigger_interval_size, - triggerIntervalUnit: metadata.trigger_interval_unit, - aggType: metadata.agg_type, - aggField: metadata.agg_field, - termSize: metadata.term_size, - termField: metadata.term_field, - thresholdComparator: metadata.threshold_comparator, - timeWindowSize: metadata.time_window_size, - timeWindowUnit: metadata.time_window_unit, - threshold: Array.isArray(metadata.threshold) ? metadata.threshold : [metadata.threshold], - }); - - return new ThresholdWatch(props); - } - - // from Kibana - static fromDownstreamJson({ - id, - name, - actions, - index, - timeField, - triggerIntervalSize, - triggerIntervalUnit, - aggType, - aggField, - termSize, - termField, - thresholdComparator, - timeWindowSize, - timeWindowUnit, - threshold, - }) { - const props = { - type: WATCH_TYPES.THRESHOLD, - id, - name, - actions, - index, - timeField, - triggerIntervalSize, - triggerIntervalUnit, - aggType, - aggField, - termSize, - termField, - thresholdComparator, - timeWindowSize, - timeWindowUnit, - threshold, - }; - - return new ThresholdWatch(props); - } -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/watch.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/watch.js deleted file mode 100644 index cc92741de73ae0..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/watch.js +++ /dev/null @@ -1,73 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { set } from 'lodash'; -import { badRequest } from 'boom'; -import { WATCH_TYPES } from '../../../../common/constants'; -import { JsonWatch } from './json_watch'; -import { MonitoringWatch } from './monitoring_watch'; -import { ThresholdWatch } from './threshold_watch'; -import { getWatchType } from './lib/get_watch_type'; -import { i18n } from '@kbn/i18n'; - -const WatchTypes = {}; -set(WatchTypes, WATCH_TYPES.JSON, JsonWatch); -set(WatchTypes, WATCH_TYPES.MONITORING, MonitoringWatch); -set(WatchTypes, WATCH_TYPES.THRESHOLD, ThresholdWatch); - -export class Watch { - static getWatchTypes = () => { - return WatchTypes; - }; - - // from Kibana - static fromDownstreamJson(json) { - if (!json.type) { - throw badRequest( - i18n.translate('xpack.watcher.models.watch.typePropertyMissingBadRequestMessage', { - defaultMessage: 'JSON argument must contain an {type} property', - values: { - type: 'type', - }, - }) - ); - } - - const WatchType = WatchTypes[json.type]; - if (!WatchType) { - throw badRequest( - i18n.translate( - 'xpack.watcher.models.watch.unknownWatchTypeLoadingAttemptBadRequestMessage', - { - defaultMessage: 'Attempted to load unknown type {jsonType}', - values: { jsonType: json.type }, - } - ) - ); - } - - return WatchType.fromDownstreamJson(json); - } - - // from Elasticsearch - static fromUpstreamJson(json, options) { - if (!json.watchJson) { - throw badRequest( - i18n.translate('xpack.watcher.models.watch.watchJsonPropertyMissingBadRequestMessage', { - defaultMessage: 'JSON argument must contain a {watchJson} property', - values: { - watchJson: 'watchJson', - }, - }) - ); - } - - const type = getWatchType(json.watchJson); - const WatchType = WatchTypes[type]; - - return WatchType.fromUpstreamJson(json, options); - } -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_history_item/watch_history_item.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_history_item/watch_history_item.js deleted file mode 100644 index 391c68debfbd9f..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_history_item/watch_history_item.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { badRequest } from 'boom'; -import { getMoment } from '../../../../common/lib/get_moment'; -import { get, cloneDeep } from 'lodash'; -import { WatchStatus } from '../watch_status'; -import { i18n } from '@kbn/i18n'; - -export class WatchHistoryItem { - constructor(props) { - this.id = props.id; - this.watchId = props.watchId; - this.watchHistoryItemJson = props.watchHistoryItemJson; - this.includeDetails = Boolean(props.includeDetails); - - this.details = cloneDeep(this.watchHistoryItemJson); - this.startTime = getMoment(get(this.watchHistoryItemJson, 'result.execution_time')); - - const watchStatusJson = get(this.watchHistoryItemJson, 'status'); - const state = get(this.watchHistoryItemJson, 'state'); - this.watchStatus = WatchStatus.fromUpstreamJson({ id: this.watchId, watchStatusJson, state }); - } - - get downstreamJson() { - return { - id: this.id, - watchId: this.watchId, - details: this.includeDetails ? this.details : null, - startTime: this.startTime.toISOString(), - watchStatus: this.watchStatus.downstreamJson, - }; - } - - // generate object from elasticsearch response - static fromUpstreamJson(json, opts) { - if (!json.id) { - throw badRequest( - i18n.translate('xpack.watcher.models.watchHistoryItem.idPropertyMissingBadRequestMessage', { - defaultMessage: 'JSON argument must contain an {id} property', - values: { - id: 'id', - }, - }) - ); - } - if (!json.watchId) { - throw badRequest( - i18n.translate( - 'xpack.watcher.models.watchHistoryItem.watchIdPropertyMissingBadRequestMessage', - { - defaultMessage: 'JSON argument must contain a {watchId} property', - values: { - watchId: 'watchId', - }, - } - ) - ); - } - if (!json.watchHistoryItemJson) { - throw badRequest( - i18n.translate( - 'xpack.watcher.models.watchHistoryItem.watchHistoryItemJsonPropertyMissingBadRequestMessage', - { - defaultMessage: 'JSON argument must contain a {watchHistoryItemJson} property', - values: { - watchHistoryItemJson: 'watchHistoryItemJson', - }, - } - ) - ); - } - - const props = { ...json, ...opts }; - return new WatchHistoryItem(props); - } -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_status/__tests__/watch_status.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_status/__tests__/watch_status.js deleted file mode 100644 index 505e1733e03cd1..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_status/__tests__/watch_status.js +++ /dev/null @@ -1,314 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { WatchStatus } from '../watch_status'; -import { ACTION_STATES, WATCH_STATES, WATCH_STATE_COMMENTS } from '../../../../../common/constants'; -import moment from 'moment'; - -describe('watch_status', () => { - describe('WatchStatus', () => { - describe('fromUpstreamJson factory method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-watch', - watchStatusJson: { - state: { - active: true, - }, - last_checked: '2017-03-02T14:25:31.139Z', - last_met_condition: '2017-07-05T14:25:31.139Z', - actions: { - foo: {}, - bar: {}, - }, - }, - }; - }); - - it(`throws an error if no 'id' property in json`, () => { - delete upstreamJson.id; - expect(WatchStatus.fromUpstreamJson) - .withArgs(upstreamJson) - .to.throwError(/must contain an id property/i); - }); - - it(`throws an error if no 'watchStatusJson' property in json`, () => { - delete upstreamJson.watchStatusJson; - expect(WatchStatus.fromUpstreamJson) - .withArgs(upstreamJson) - .to.throwError(/must contain a watchStatusJson property/i); - }); - - it('returns correct WatchStatus instance', () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - expect(watchStatus.id).to.be(upstreamJson.id); - expect(watchStatus.watchStatusJson).to.eql(upstreamJson.watchStatusJson); - expect(watchStatus.isActive).to.eql(true); - expect(watchStatus.lastChecked).to.eql(moment(upstreamJson.watchStatusJson.last_checked)); - expect(watchStatus.lastMetCondition).to.eql( - moment(upstreamJson.watchStatusJson.last_met_condition) - ); - expect(watchStatus.actionStatuses.length).to.be(2); - - expect(watchStatus.actionStatuses[0].constructor.name).to.be('ActionStatus'); - expect(watchStatus.actionStatuses[1].constructor.name).to.be('ActionStatus'); - }); - }); - - describe('lastFired getter method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-watch', - watchStatusJson: { - actions: { - foo: { - last_execution: { - timestamp: '2017-07-05T00:00:00.000Z', - }, - }, - bar: { - last_execution: { - timestamp: '2025-07-05T00:00:00.000Z', - }, - }, - baz: {}, - }, - }, - }; - }); - - it(`returns the latest lastExecution from it's actions`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - expect(watchStatus.lastFired).to.eql( - moment(upstreamJson.watchStatusJson.actions.bar.last_execution.timestamp) - ); - }); - }); - - describe('comment getter method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-watch', - watchStatusJson: { - state: { - active: true, - }, - }, - }; - }); - - it(`correctly calculates WATCH_STATE_COMMENTS.OK there are no actions`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - watchStatus.isActive = true; - expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.OK); - }); - - it(`correctly calculates WATCH_STATE_COMMENTS.PARTIALLY_THROTTLED`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.FIRING }, - { state: ACTION_STATES.OK }, - ]; - - expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.PARTIALLY_THROTTLED); - }); - - it(`correctly calculates WATCH_STATE_COMMENTS.THROTTLED`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.THROTTLED }, - ]; - - expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.THROTTLED); - }); - - it(`correctly calculates WATCH_STATE_COMMENTS.PARTIALLY_ACKNOWLEDGED`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.ACKNOWLEDGED }, - { state: ACTION_STATES.OK }, - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.FIRING }, - ]; - - expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.PARTIALLY_ACKNOWLEDGED); - }); - - it(`correctly calculates WATCH_STATE_COMMENTS.ACKNOWLEDGED`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.ACKNOWLEDGED }, - { state: ACTION_STATES.ACKNOWLEDGED }, - { state: ACTION_STATES.ACKNOWLEDGED }, - ]; - - expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.ACKNOWLEDGED); - }); - - it(`correctly calculates WATCH_STATE_COMMENTS.FAILING`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.OK }, - { state: ACTION_STATES.ACKNOWLEDGED }, - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.FIRING }, - { state: ACTION_STATES.ERROR }, - ]; - - expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.FAILING); - }); - - it(`correctly calculates WATCH_STATE_COMMENTS.OK when watch is inactive`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - watchStatus.isActive = false; - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.OK }, - { state: ACTION_STATES.ACKNOWLEDGED }, - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.FIRING }, - { state: ACTION_STATES.ERROR }, - ]; - - expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.OK); - }); - }); - - describe('state getter method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-watch', - watchStatusJson: { - state: { - active: true, - }, - }, - }; - }); - - it(`correctly calculates WATCH_STATES.OK there are no actions`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - watchStatus.isActive = true; - expect(watchStatus.state).to.be(WATCH_STATES.OK); - }); - - it(`correctly calculates WATCH_STATES.FIRING`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - watchStatus.actionStatuses = [{ state: ACTION_STATES.OK }, { state: ACTION_STATES.FIRING }]; - expect(watchStatus.state).to.be(WATCH_STATES.FIRING); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.OK }, - { state: ACTION_STATES.FIRING }, - { state: ACTION_STATES.THROTTLED }, - ]; - expect(watchStatus.state).to.be(WATCH_STATES.FIRING); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.OK }, - { state: ACTION_STATES.FIRING }, - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.ACKNOWLEDGED }, - ]; - expect(watchStatus.state).to.be(WATCH_STATES.FIRING); - }); - - it(`correctly calculates WATCH_STATES.ERROR`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.OK }, - { state: ACTION_STATES.FIRING }, - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.ACKNOWLEDGED }, - { state: ACTION_STATES.ERROR }, - ]; - - expect(watchStatus.state).to.be(WATCH_STATES.ERROR); - }); - - it('correctly calculates WATCH_STATE.CONFIG_ERROR', () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.OK }, - { state: ACTION_STATES.CONFIG_ERROR }, - ]; - - expect(watchStatus.state).to.be(WATCH_STATES.CONFIG_ERROR); - }); - - it(`correctly calculates WATCH_STATES.DISABLED when watch is inactive`, () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - watchStatus.isActive = false; - - watchStatus.actionStatuses = [ - { state: ACTION_STATES.OK }, - { state: ACTION_STATES.FIRING }, - { state: ACTION_STATES.THROTTLED }, - { state: ACTION_STATES.ACKNOWLEDGED }, - { state: ACTION_STATES.ERROR }, - ]; - - expect(watchStatus.state).to.be(WATCH_STATES.DISABLED); - }); - }); - - describe('downstreamJson getter method', () => { - let upstreamJson; - beforeEach(() => { - upstreamJson = { - id: 'my-watch', - watchStatusJson: { - state: { - active: true, - }, - last_checked: '2017-03-02T14:25:31.139Z', - last_met_condition: '2017-07-05T14:25:31.139Z', - actions: { - foo: {}, - bar: {}, - }, - }, - }; - }); - - it('returns correct downstream JSON object', () => { - const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); - watchStatus.actionStatuses = [ - { id: 'foo', state: ACTION_STATES.OK }, - { id: 'bar', state: ACTION_STATES.OK }, - ]; - - const actual = watchStatus.downstreamJson; - - expect(actual.id).to.be(watchStatus.id); - expect(actual.state).to.be(watchStatus.state); - expect(actual.comment).to.be(watchStatus.comment); - expect(actual.isActive).to.be(watchStatus.isActive); - expect(actual.lastChecked).to.be(watchStatus.lastChecked); - expect(actual.lastMetCondition).to.be(watchStatus.lastMetCondition); - expect(actual.lastFired).to.be(watchStatus.lastFired); - expect(actual.actionStatuses.length).to.be(2); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_status/watch_status.js b/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_status/watch_status.js deleted file mode 100644 index 3cdc1d8eb62e70..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_status/watch_status.js +++ /dev/null @@ -1,200 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get, map, forEach, max } from 'lodash'; -import { badRequest } from 'boom'; -import { getMoment } from '../../../../common/lib/get_moment'; -import { ActionStatus } from '../action_status'; -import { ACTION_STATES, WATCH_STATES, WATCH_STATE_COMMENTS } from '../../../../common/constants'; -import { i18n } from '@kbn/i18n'; - -function getActionStatusTotals(watchStatus) { - const result = {}; - - forEach(ACTION_STATES, state => { - result[state] = 0; - }); - forEach(watchStatus.actionStatuses, actionStatus => { - result[actionStatus.state] = result[actionStatus.state] + 1; - }); - - return result; -} - -const WATCH_STATE_FAILED = 'failed'; - -export class WatchStatus { - constructor(props) { - this.id = props.id; - this.watchState = props.state; - this.watchStatusJson = props.watchStatusJson; - this.watchErrors = props.watchErrors || {}; - - this.isActive = Boolean(get(this.watchStatusJson, 'state.active')); - this.lastChecked = getMoment(get(this.watchStatusJson, 'last_checked')); - this.lastMetCondition = getMoment(get(this.watchStatusJson, 'last_met_condition')); - - const actionStatusesJson = get(this.watchStatusJson, 'actions', {}); - this.actionStatuses = map(actionStatusesJson, (actionStatusJson, id) => { - const json = { - id, - actionStatusJson, - errors: this.watchErrors.actions && this.watchErrors.actions[id], - }; - return ActionStatus.fromUpstreamJson(json); - }); - } - - get state() { - if (!this.isActive) { - return WATCH_STATES.DISABLED; - } - - if (this.watchState === WATCH_STATE_FAILED) { - return WATCH_STATES.ERROR; - } - - const totals = getActionStatusTotals(this); - - if (totals[ACTION_STATES.ERROR] > 0) { - return WATCH_STATES.ERROR; - } - - if (totals[ACTION_STATES.CONFIG_ERROR] > 0) { - return WATCH_STATES.CONFIG_ERROR; - } - - const firingTotal = - totals[ACTION_STATES.FIRING] + - totals[ACTION_STATES.ACKNOWLEDGED] + - totals[ACTION_STATES.THROTTLED]; - - if (firingTotal > 0) { - return WATCH_STATES.FIRING; - } - - return WATCH_STATES.OK; - } - - get comment() { - const totals = getActionStatusTotals(this); - const totalActions = this.actionStatuses.length; - let result = WATCH_STATE_COMMENTS.OK; - - if (totals[ACTION_STATES.THROTTLED] > 0 && totals[ACTION_STATES.THROTTLED] < totalActions) { - result = WATCH_STATE_COMMENTS.PARTIALLY_THROTTLED; - } - - if (totals[ACTION_STATES.THROTTLED] > 0 && totals[ACTION_STATES.THROTTLED] === totalActions) { - result = WATCH_STATE_COMMENTS.THROTTLED; - } - - if ( - totals[ACTION_STATES.ACKNOWLEDGED] > 0 && - totals[ACTION_STATES.ACKNOWLEDGED] < totalActions - ) { - result = WATCH_STATE_COMMENTS.PARTIALLY_ACKNOWLEDGED; - } - - if ( - totals[ACTION_STATES.ACKNOWLEDGED] > 0 && - totals[ACTION_STATES.ACKNOWLEDGED] === totalActions - ) { - result = WATCH_STATE_COMMENTS.ACKNOWLEDGED; - } - - if (totals[ACTION_STATES.ERROR] > 0) { - result = WATCH_STATE_COMMENTS.FAILING; - } - - if (!this.isActive) { - result = WATCH_STATE_COMMENTS.OK; - } - - return result; - } - - get lastFired() { - const actionStatus = max(this.actionStatuses, 'lastExecution'); - if (actionStatus) { - return actionStatus.lastExecution; - } - } - - // generate object to send to kibana - get downstreamJson() { - const json = { - id: this.id, - state: this.state, - comment: this.comment, - isActive: this.isActive, - lastChecked: this.lastChecked, - lastMetCondition: this.lastMetCondition, - lastFired: this.lastFired, - actionStatuses: map(this.actionStatuses, actionStatus => actionStatus.downstreamJson), - }; - - return json; - } - - // generate object from elasticsearch response - static fromUpstreamJson(json) { - if (!json.id) { - throw badRequest( - i18n.translate('xpack.watcher.models.watchStatus.idPropertyMissingBadRequestMessage', { - defaultMessage: 'JSON argument must contain an {id} property', - values: { - id: 'id', - }, - }) - ); - } - if (!json.watchStatusJson) { - throw badRequest( - i18n.translate( - 'xpack.watcher.models.watchStatus.watchStatusJsonPropertyMissingBadRequestMessage', - { - defaultMessage: 'JSON argument must contain a {watchStatusJson} property', - values: { - watchStatusJson: 'watchStatusJson', - }, - } - ) - ); - } - - return new WatchStatus(json); - } - - /* - json.watchStatusJson should have the following structure: - { - "state": { - "active": true, - "timestamp": "2017-03-01T19:05:49.400Z" - }, - "actions": { - "log-me-something": { - "ack": { - "timestamp": "2017-03-01T20:56:58.442Z", - "state": "acked" - }, - "last_execution": { - "timestamp": "2017-03-01T20:55:49.679Z", - "successful": true - }, - "last_successful_execution": { - "timestamp": "2017-03-01T20:55:49.679Z", - "successful": true - } - } - }, - "version": 15, - "last_checked": "2017-03-02T14:25:31.139Z", - "last_met_condition": "2017-03-02T14:25:31.139Z" - } - */ -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/plugin.ts b/x-pack/legacy/plugins/watcher/server/np_ready/plugin.ts deleted file mode 100644 index a311c31082183c..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/plugin.ts +++ /dev/null @@ -1,50 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import { Plugin, CoreSetup } from 'src/core/server'; -import { i18n } from '@kbn/i18n'; -import { PLUGIN } from '../../common/constants'; -import { ServerShim, RouteDependencies } from './types'; - -import { registerLicenseChecker } from '../../../../server/lib/register_license_checker'; -import { registerSettingsRoutes } from './routes/api/settings'; -import { registerIndicesRoutes } from './routes/api/indices'; -import { registerLicenseRoutes } from './routes/api/license'; -import { registerWatchesRoutes } from './routes/api/watches'; -import { registerWatchRoutes } from './routes/api/watch'; -import { registerListFieldsRoute } from './routes/api/register_list_fields_route'; -import { registerLoadHistoryRoute } from './routes/api/register_load_history_route'; - -export class WatcherServerPlugin implements Plugin { - async setup( - { http, elasticsearch: elasticsearchService }: CoreSetup, - { __LEGACY: serverShim }: { __LEGACY: ServerShim } - ) { - const elasticsearch = await elasticsearchService.adminClient; - const router = http.createRouter(); - const routeDependencies: RouteDependencies = { - elasticsearch, - elasticsearchService, - router, - }; - // Register license checker - registerLicenseChecker( - serverShim as any, - PLUGIN.ID, - PLUGIN.getI18nName(i18n), - PLUGIN.MINIMUM_LICENSE_REQUIRED - ); - - registerListFieldsRoute(routeDependencies, serverShim); - registerLoadHistoryRoute(routeDependencies, serverShim); - registerIndicesRoutes(routeDependencies, serverShim); - registerLicenseRoutes(routeDependencies, serverShim); - registerSettingsRoutes(routeDependencies, serverShim); - registerWatchesRoutes(routeDependencies, serverShim); - registerWatchRoutes(routeDependencies, serverShim); - } - start() {} - stop() {} -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/indices/register_indices_routes.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/indices/register_indices_routes.ts deleted file mode 100644 index 647a85c311532b..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/indices/register_indices_routes.ts +++ /dev/null @@ -1,12 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { registerGetRoute } from './register_get_route'; -import { RouteDependencies, ServerShim } from '../../../types'; - -export function registerIndicesRoutes(deps: RouteDependencies, legacy: ServerShim) { - registerGetRoute(deps, legacy); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/license/register_license_routes.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/license/register_license_routes.ts deleted file mode 100644 index c5965d9315b01e..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/license/register_license_routes.ts +++ /dev/null @@ -1,12 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { registerRefreshRoute } from './register_refresh_route'; -import { RouteDependencies, ServerShim } from '../../../types'; - -export function registerLicenseRoutes(deps: RouteDependencies, legacy: ServerShim) { - registerRefreshRoute(deps, legacy); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/settings/register_load_route.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/settings/register_load_route.ts deleted file mode 100644 index 710d079d810da8..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/settings/register_load_route.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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { IClusterClient, RequestHandler } from 'src/core/server'; -import { isEsError } from '../../../lib/is_es_error'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -// @ts-ignore -import { Settings } from '../../../models/settings'; -import { RouteDependencies, ServerShim } from '../../../types'; - -function fetchClusterSettings(client: IClusterClient) { - return client.callAsInternalUser('cluster.getSettings', { - includeDefaults: true, - filterPath: '**.xpack.notification', - }); -} - -export function registerLoadRoute(deps: RouteDependencies, legacy: ServerShim) { - const handler: RequestHandler = async (ctx, request, response) => { - try { - const settings = await fetchClusterSettings(deps.elasticsearch); - return response.ok({ body: Settings.fromUpstreamJson(settings).downstreamJson }); - } catch (e) { - // Case: Error from Elasticsearch JS client - if (isEsError(e)) { - return response.customError({ statusCode: e.statusCode, body: e }); - } - - // Case: default - return response.internalError({ body: e }); - } - }; - deps.router.get( - { - path: '/api/watcher/settings', - validate: false, - }, - licensePreRoutingFactory(legacy, handler) - ); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/settings/register_settings_routes.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/settings/register_settings_routes.ts deleted file mode 100644 index 0b24ec0e90bd42..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/settings/register_settings_routes.ts +++ /dev/null @@ -1,12 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { registerLoadRoute } from './register_load_route'; -import { RouteDependencies, ServerShim } from '../../../types'; - -export function registerSettingsRoutes(deps: RouteDependencies, legacy: ServerShim) { - registerLoadRoute(deps, legacy); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/action/register_action_routes.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/action/register_action_routes.ts deleted file mode 100644 index 022c844867938b..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/action/register_action_routes.ts +++ /dev/null @@ -1,12 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { registerAcknowledgeRoute } from './register_acknowledge_route'; -import { RouteDependencies, ServerShim } from '../../../../types'; - -export function registerActionRoutes(server: RouteDependencies, legacy: ServerShim) { - registerAcknowledgeRoute(server, legacy); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_delete_route.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_delete_route.ts deleted file mode 100644 index 3402cc283dba04..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_delete_route.ts +++ /dev/null @@ -1,52 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; - -function deleteWatch(callWithRequest: any, watchId: string) { - return callWithRequest('watcher.deleteWatch', { - id: watchId, - }); -} - -export function registerDeleteRoute(deps: RouteDependencies, legacy: ServerShim) { - const handler: RequestHandler = async (ctx, request, response) => { - const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); - - const { watchId } = request.params; - - try { - await deleteWatch(callWithRequest, watchId); - return response.noContent(); - } catch (e) { - // Case: Error from Elasticsearch JS client - if (isEsError(e)) { - const body = e.statusCode === 404 ? `Watch with id = ${watchId} not found` : e; - return response.customError({ statusCode: e.statusCode, body }); - } - - // Case: default - return response.internalError({ body: e }); - } - }; - - deps.router.delete( - { - path: '/api/watcher/watch/{watchId}', - validate: { - params: schema.object({ - watchId: schema.string(), - }), - }, - }, - licensePreRoutingFactory(legacy, handler) - ); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_load_route.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_load_route.ts deleted file mode 100644 index 7311ad08f73a60..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_load_route.ts +++ /dev/null @@ -1,69 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; -import { get } from 'lodash'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -// @ts-ignore -import { Watch } from '../../../models/watch'; -import { RouteDependencies, ServerShim } from '../../../types'; - -function fetchWatch(callWithRequest: any, watchId: string) { - return callWithRequest('watcher.getWatch', { - id: watchId, - }); -} - -export function registerLoadRoute(deps: RouteDependencies, legacy: ServerShim) { - const handler: RequestHandler = async (ctx, request, response) => { - const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); - - const id = request.params.id; - - try { - const hit = await fetchWatch(callWithRequest, id); - const watchJson = get(hit, 'watch'); - const watchStatusJson = get(hit, 'status'); - const json = { - id, - watchJson, - watchStatusJson, - }; - - const watch = Watch.fromUpstreamJson(json, { - throwExceptions: { - Action: false, - }, - }); - return response.ok({ - body: { watch: watch.downstreamJson }, - }); - } catch (e) { - // Case: Error from Elasticsearch JS client - if (isEsError(e)) { - const body = e.statusCode === 404 ? `Watch with id = ${id} not found` : e; - return response.customError({ statusCode: e.statusCode, body }); - } - - // Case: default - return response.internalError({ body: e }); - } - }; - deps.router.get( - { - path: '/api/watcher/watch/{id}', - validate: { - params: schema.object({ - id: schema.string(), - }), - }, - }, - licensePreRoutingFactory(legacy, handler) - ); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_watch_routes.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_watch_routes.ts deleted file mode 100644 index 5ecbf3e0d2b46f..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_watch_routes.ts +++ /dev/null @@ -1,28 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { registerDeleteRoute } from './register_delete_route'; -import { registerExecuteRoute } from './register_execute_route'; -import { registerLoadRoute } from './register_load_route'; -import { registerSaveRoute } from './register_save_route'; -import { registerHistoryRoute } from './register_history_route'; -import { registerActivateRoute } from './register_activate_route'; -import { registerDeactivateRoute } from './register_deactivate_route'; -import { registerVisualizeRoute } from './register_visualize_route'; -import { registerActionRoutes } from './action'; -import { RouteDependencies, ServerShim } from '../../../types'; - -export function registerWatchRoutes(deps: RouteDependencies, legacy: ServerShim) { - registerDeleteRoute(deps, legacy); - registerExecuteRoute(deps, legacy); - registerLoadRoute(deps, legacy); - registerSaveRoute(deps, legacy); - registerHistoryRoute(deps, legacy); - registerActivateRoute(deps, legacy); - registerDeactivateRoute(deps, legacy); - registerActionRoutes(deps, legacy); - registerVisualizeRoute(deps, legacy); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_delete_route.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_delete_route.ts deleted file mode 100644 index 29c539a0de138a..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_delete_route.ts +++ /dev/null @@ -1,63 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; - -function deleteWatches(callWithRequest: any, watchIds: string[]) { - const deletePromises = watchIds.map(watchId => { - return callWithRequest('watcher.deleteWatch', { - id: watchId, - }) - .then((success: Array<{ _id: string }>) => ({ success })) - .catch((error: Array<{ _id: string }>) => ({ error })); - }); - - return Promise.all(deletePromises).then(results => { - const errors: Error[] = []; - const successes: boolean[] = []; - results.forEach(({ success, error }) => { - if (success) { - successes.push(success._id); - } else if (error) { - errors.push(error._id); - } - }); - - return { - successes, - errors, - }; - }); -} - -export function registerDeleteRoute(deps: RouteDependencies, legacy: ServerShim) { - const handler: RequestHandler = async (ctx, request, response) => { - const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); - - try { - const results = await deleteWatches(callWithRequest, request.body.watchIds); - return response.ok({ body: { results } }); - } catch (e) { - return response.internalError({ body: e }); - } - }; - - deps.router.post( - { - path: '/api/watcher/watches/delete', - validate: { - body: schema.object({ - watchIds: schema.arrayOf(schema.string()), - }), - }, - }, - licensePreRoutingFactory(legacy, handler) - ); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_watches_routes.ts b/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_watches_routes.ts deleted file mode 100644 index dd5f55078e5913..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_watches_routes.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { registerListRoute } from './register_list_route'; -import { registerDeleteRoute } from './register_delete_route'; -import { RouteDependencies, ServerShim } from '../../../types'; - -export function registerWatchesRoutes(deps: RouteDependencies, legacy: ServerShim) { - registerListRoute(deps, legacy); - registerDeleteRoute(deps, legacy); -} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/types.ts b/x-pack/legacy/plugins/watcher/server/np_ready/types.ts deleted file mode 100644 index 3d4454aa2a8b77..00000000000000 --- a/x-pack/legacy/plugins/watcher/server/np_ready/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { IRouter, ElasticsearchServiceSetup, IClusterClient } from 'src/core/server'; -import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main'; - -export interface ServerShim { - route: any; - plugins: { - xpack_main: XPackMainPlugin; - watcher: any; - }; -} - -export interface RouteDependencies { - router: IRouter; - elasticsearchService: ElasticsearchServiceSetup; - elasticsearch: IClusterClient; -} diff --git a/x-pack/legacy/plugins/xpack_main/server/lib/__tests__/replace_injected_vars.js b/x-pack/legacy/plugins/xpack_main/server/lib/__tests__/replace_injected_vars.js index 55da11221bb101..ae929045cf5709 100644 --- a/x-pack/legacy/plugins/xpack_main/server/lib/__tests__/replace_injected_vars.js +++ b/x-pack/legacy/plugins/xpack_main/server/lib/__tests__/replace_injected_vars.js @@ -16,6 +16,7 @@ const buildRequest = (path = '/app/kibana') => { return { path, route: { settings: {} }, + headers: {}, raw: { req: { socket: {}, diff --git a/x-pack/plugins/actions/README.md b/x-pack/plugins/actions/README.md new file mode 100644 index 00000000000000..aa6f665e35255f --- /dev/null +++ b/x-pack/plugins/actions/README.md @@ -0,0 +1,470 @@ +# Kibana Actions + +The Kibana actions plugin provides a framework to create executable actions. You can: + +- Register an action type and associate a JavaScript function to run when actions + are executed. +- Get a list of registered action types +- Create an action from an action type and encrypted configuration object. +- Get a list of actions that have been created. +- Execute an action, passing it a parameter object. +- Perform CRUD operations on actions. + +----- + + +Table of Contents + +- [Kibana Actions](#kibana-actions) + - [Terminology](#terminology) + - [Usage](#usage) + - [Kibana Actions Configuration](#kibana-actions-configuration) + - [Configuration Options](#configuration-options) + - [Whitelisting Built-in Action Types](#whitelisting-built-in-action-types) + - [Configuration Utilities](#configuration-utilities) + - [Action types](#action-types) + - [Methods](#methods) + - [Executor](#executor) + - [Example](#example) + - [RESTful API](#restful-api) + - [`POST /api/action`: Create action](#post-apiaction-create-action) + - [`DELETE /api/action/{id}`: Delete action](#delete-apiactionid-delete-action) + - [`GET /api/action/_find`: Find actions](#get-apiactionfind-find-actions) + - [`GET /api/action/{id}`: Get action](#get-apiactionid-get-action) + - [`GET /api/action/types`: List action types](#get-apiactiontypes-list-action-types) + - [`PUT /api/action/{id}`: Update action](#put-apiactionid-update-action) + - [`POST /api/action/{id}/_execute`: Execute action](#post-apiactionidexecute-execute-action) + - [Firing actions](#firing-actions) + - [Example](#example-1) +- [Built-in Action Types](#built-in-action-types) + - [Server log](#server-log) + - [`config`](#config) + - [`secrets`](#secrets) + - [`params`](#params) + - [Email](#email) + - [`config`](#config-1) + - [`secrets`](#secrets-1) + - [`params`](#params-1) + - [Slack](#slack) + - [`config`](#config-2) + - [`secrets`](#secrets-2) + - [`params`](#params-2) + - [Index](#index) + - [`config`](#config-3) + - [`secrets`](#secrets-3) + - [`params`](#params-3) + - [Webhook](#webhook) + - [`config`](#config-4) + - [`secrets`](#secrets-4) + - [`params`](#params-4) + - [PagerDuty](#pagerduty) + - [`config`](#config-5) + - [`secrets`](#secrets-5) + - [`params`](#params-5) +- [Command Line Utility](#command-line-utility) + + +## Terminology + +**Action Type**: A programatically defined integration with another service, with an expected set of configuration and parameters properties, typically defined with a schema. Plugins can add new +action types. + +**Action**: A configuration object associated with an action type, that is ready to be executed. The configuration is persisted via Saved Objects, and some/none/all of the configuration properties can be stored encrypted. + +## Usage + +1. Develop and register an action type (see action types -> example). +2. Create an action by using the RESTful API (see actions -> create action). +3. Use alerts to execute actions or execute manually (see firing actions). + +## Kibana Actions Configuration +Implemented under the [Actions Config](./server/actions_config.ts). + +### Configuration Options + +Built-In-Actions are configured using the _xpack.actions_ namespoace under _kibana.yml_, and have the following configuration options: + +| Namespaced Key | Description | Type | +| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| _xpack.actions._**enabled** | Feature toggle which enabled Actions in Kibana. | boolean | +| _xpack.actions._**whitelistedHosts** | Which _hostnames_ are whitelisted for the Built-In-Action? This list should contain hostnames of every external service you wish to interact with using Webhooks, Email or any other built in Action. Note that you may use the string "\*" in place of a specific hostname to enable Kibana to target any URL, but keep in mind the potential use of such a feature to execute [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) attacks from your server. | Array | +| _xpack.actions._**enabledActionTypes** | A list of _actionTypes_ id's that are enabled. A "\*" may be used as an element to indicate all registered actionTypes should be enabled. The actionTypes registered for Kibana are `.server-log`, `.slack`, `.email`, `.index`, `.pagerduty`, `.webhook`. Default: `["*"]` | Array | + +#### Whitelisting Built-in Action Types +It is worth noting that the **whitelistedHosts** configuation applies to built-in action types (such as Slack, or PagerDuty) as well. + +Uniquely, the _PagerDuty Action Type_ has been configured to support the service's Events API (at _https://events.pagerduty.com/v2/enqueue_, which you can read about [here](https://v2.developer.pagerduty.com/docs/events-api-v2)) as a default, but this too, must be included in the whitelist before the PagerDuty action can be used. + + +### Configuration Utilities + +This module provides a Utilities for interacting with the configuration. + +| Method | Arguments | Description | Return Type | +| --------------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| isWhitelistedUri | _uri_: The URI you wish to validate is whitelisted | Validates whether the URI is whitelisted. This checks the configuration and validates that the hostname of the URI is in the list of whitelisted Hosts and returns `true` if it is whitelisted. If the configuration says that all URI's are whitelisted (using an "\*") then it will always return `true`. | Boolean | +| isWhitelistedHostname | _hostname_: The Hostname you wish to validate is whitelisted | Validates whether the Hostname is whitelisted. This checks the configuration and validates that the hostname is in the list of whitelisted Hosts and returns `true` if it is whitelisted. If the configuration says that all Hostnames are whitelisted (using an "\*") then it will always return `true`. | Boolean | +| isActionTypeEnabled | _actionType_: The actionType to check to see if it's enabled | Returns true if the actionType is enabled, otherwise false. | Boolean | +| ensureWhitelistedUri | _uri_: The URI you wish to validate is whitelisted | Validates whether the URI is whitelisted. This checks the configuration and validates that the hostname of the URI is in the list of whitelisted Hosts and throws an error if it is not whitelisted. If the configuration says that all URI's are whitelisted (using an "\*") then it will never throw. | No return value, throws if URI isn't whitelisted | +| ensureWhitelistedHostname | _hostname_: The Hostname you wish to validate is whitelisted | Validates whether the Hostname is whitelisted. This checks the configuration and validates that the hostname is in the list of whitelisted Hosts and throws an error if it is not whitelisted. If the configuration says that all Hostnames are whitelisted (using an "\*") then it will never throw | No return value, throws if Hostname isn't whitelisted | +| ensureActionTypeEnabled | _actionType_: The actionType to check to see if it's enabled | Throws an error if the actionType is not enabled | No return value, throws if actionType isn't enabled | + +## Action types + +### Methods + +**server.plugins.actions.setup.registerType(options)** + +The following table describes the properties of the `options` object. + +|Property|Description|Type| +|---|---|---| +|id|Unique identifier for the action type. For convention, ids starting with `.` are reserved for built in action types. We recommend using a convention like `.mySpecialAction` for your action types.|string| +|name|A user-friendly name for the action type. These will be displayed in dropdowns when chosing action types.|string| +|unencryptedAttributes|A list of opt-out attributes that don't need to be encrypted. These attributes won't need to be re-entered on import / export when the feature becomes available. These attributes will also be readable / displayed when it comes to a table / edit screen.|array of strings| +|validate.params|When developing an action type, it needs to accept parameters to know what to do with the action. (Example to, from, subject, body of an email). See the current built-in email action type for an example of the state-of-the-art validation.

    Technically, the value of this property should have a property named `validate()` which is a function that takes a params object to validate and returns a sanitized version of that object to pass to the execution function. Validation errors should be thrown from the `validate()` function and will be available as an error message|schema / validation function| +|validate.config|Similar to params, a config is required when creating an action (for example host, port, username, and password of an email server). |schema / validation function| +|executor|This is where the code of an action type lives. This is a function gets called for executing an action from either alerting or manually by using the exposed function (see firing actions). For full details, see executor section below.|Function| + +**Important** - The config object is persisted in ElasticSearch and updated via the ElasticSearch update document API. This API allows "partial updates" - and this can cause issues with the encryption used on specified properties. So, a `validate()` function should return values for all configuration properties, so that partial updates do not occur. Setting property values to `null` rather than `undefined`, or not including a property in the config object, is all you need to do to ensure partial updates won't occur. + +### Executor + +This is the primary function for an action type. Whenever the action needs to execute, this function will perform the action. It receives a variety of parameters. The following table describes the properties that the executor receives. + +**executor(options)** + +|Property|Description| +|---|---| +|actionId|The action saved object id that the action type is executing for.| +|config|The decrypted configuration given to an action. This comes from the action saved object that is partially or fully encrypted within the data store. If you would like to validate the config before being passed to the executor, define `validate.config` within the action type.| +|params|Parameters for the execution. These will be given at execution time by either an alert or manually provided when calling the plugin provided execute function.| +|services.callCluster(path, opts)|Use this to do Elasticsearch queries on the cluster Kibana connects to. This function is the same as any other `callCluster` in Kibana.

    **NOTE**: This currently authenticates as the Kibana internal user, but will change in a future PR.| +|services.savedObjectsClient|This is an instance of the saved objects client. This provides the ability to do CRUD on any saved objects within the same space the alert lives in.

    The scope of the saved objects client is tied to the user in context calling the execute API or the API key provided to the execute plugin function (only when security isenabled).| +|services.log(tags, [data], [timestamp])|Use this to create server logs. (This is the same function as server.log)| + +### Example + +The built-in email action type provides a good example of creating an action type with non-trivial configuration and params: +[x-pack/plugins/actions/server/builtin_action_types/email.ts](server/builtin_action_types/email.ts) + + +## RESTful API + +Using an action type requires an action to be created that will contain and encrypt configuration for a given action type. See below for CRUD operations using the API. + +### `POST /api/action`: Create action + +Payload: + +|Property|Description|Type| +|---|---|---| +|name|A name to reference and search in the future. This value will be used to populate dropdowns.|string| +|actionTypeId|The id value of the action type you want to call when the action executes.|string| +|config|The configuration the action type expects. See related action type to see what attributes are expected. This will also validate against the action type if config validation is defined.|object| +|secrets|The secrets the action type expects. See related action type to see what attributes are expected. This will also validate against the action type if secrets validation is defined.|object| + +### `DELETE /api/action/{id}`: Delete action + +Params: + +|Property|Description|Type| +|---|---|---| +|id|The id of the action you're trying to delete.|string| + +### `GET /api/action/_find`: Find actions + +Params: + +See the [saved objects API documentation for find](https://www.elastic.co/guide/en/kibana/master/saved-objects-api-find.html). All the properties are the same except that you cannot pass in `type`. + +### `GET /api/action/{id}`: Get action + +Params: + +|Property|Description|Type| +|---|---|---| +|id|The id of the action you're trying to get.|string| + +### `GET /api/action/types`: List action types + +No parameters. + +### `PUT /api/action/{id}`: Update action + +Params: + +|Property|Description|Type| +|---|---|---| +|id|The id of the action you're trying to update.|string| + +Payload: + +|Property|Description|Type| +|---|---|---| +|name|A name to reference and search in the future. This value will be used to populate dropdowns.|string| +|config|The configuration the action type expects. See related action type to see what attributes are expected. This will also validate against the action type if config validation is defined.|object| +|secrets|The secrets the action type expects. See related action type to see what attributes are expected. This will also validate against the action type if secrets validation is defined.|object| + +### `POST /api/action/{id}/_execute`: Execute action + +Params: + +|Property|Description|Type| +|---|---|---| +|id|The id of the action you're trying to execute.|string| + +Payload: + +|Property|Description|Type| +|---|---|---| +|params|The parameters the action type requires for the execution.|object| + +## Firing actions + +The plugin exposes an execute function that you can use to run actions. + +**server.plugins.actions.execute(options)** + +The following table describes the properties of the `options` object. + +|Property|Description|Type| +|---|---|---| +|id|The id of the action you want to execute.|string| +|params|The `params` value to give the action type executor.|object| +|spaceId|The space id the action is within.|string| +|apiKey|The Elasticsearch API key to use for context. (Note: only required and used when security is enabled).|string| + +## Example + +This example makes action `3c5b2bd4-5424-4e4b-8cf5-c0a58c762cc5` send an email. The action plugin will load the saved object and find what action type to call with `params`. + +``` +server.plugins.actions.execute({ + id: '3c5b2bd4-5424-4e4b-8cf5-c0a58c762cc5', + spaceId: 'default', // The spaceId of the action + params: { + from: 'example@elastic.co', + to: ['destination@elastic.co'], + subject: 'My email subject', + body: 'My email body', + }, +}); +``` + +# Built-in Action Types + +Kibana ships with a set of built-in action types: + +|Type|Id|Description| +|---|---|---| +|[Server log](#server-log)|`.log`|Logs messages to the Kibana log using `server.log()`| +|[Email](#email)|`.email`|Sends an email using SMTP| +|[Slack](#slack)|`.slack`|Posts a message to a slack channel| +|[Index](#index)|`.index`|Indexes document(s) into Elasticsearch| +|[Webhook](#webhook)|`.webhook`|Send a payload to a web service using HTTP POST or PUT| +|[PagerDuty](#pagerduty)|`.pagerduty`|Trigger, resolve, or acknowlege an incident to a PagerDuty service| + +---- +## Server log + +ID: `.log` + +The params properties are modelled after the arguments to the [Hapi.server.log()](https://hapijs.com/api#-serverlogtags-data-timestamp) function. + +### `config` + +This action has no `config` properties. + +### `secrets` + +This action type has no `secrets` properties. + +### `params` + +|Property|Description|Type| +|---|---|---| +|message|The message to log.|string| +|tags|Tags associated with the message to log.|string[] _(optional)_| + +---- +## Email + +ID: `.email` + +This action type uses [nodemailer](https://nodemailer.com/about/) to send emails. + +### `config` + +Either the property `service` must be provided, or the `host` and `port` properties must be provided. If `service` is provided, `host`, `port` and `secure` are ignored. For more information on the `gmail` service value specifically, see the [nodemailer gmail documentation](https://nodemailer.com/usage/using-gmail/). + +The `secure` property defaults to `false`. See the [nodemailer TLS documentation](https://nodemailer.com/smtp/#tls-options) for more information. + +The `from` field can be specified as in typical `"user@host-name"` format, or as `"human name "` format. See the [nodemailer address documentation](https://nodemailer.com/message/addresses/) for more information. + +|Property|Description|Type| +|---|---|---| +|service|the name of a [well-known email service provider](https://nodemailer.com/smtp/well-known/)|string _(optional)_| +|host|host name of the service provider|string _(optional)_| +|port|port number of the service provider|number _(optional)_| +|secure|whether to use TLS with the service provider|boolean _(optional)_| +|from|the from address for all emails sent with this action type|string| + +### `secrets` + +|Property|Description|Type| +|---|---|---| +|user|userid to use with the service provider|string| +|password|password to use with the service provider|string| + +### `params` + +There must be at least one entry in the `to`, `cc` and `bcc` arrays. + +The message text will be sent as both plain text and html text. Additional function may be provided later. + +The `to`, `cc`, and `bcc` array entries can be in the same format as the `from` property described in the config object above. + +|Property|Description|Type| +|---|---|---| +|to|list of to addressees|string[] _(optional)_| +|cc|list of cc addressees|string[] _(optional)_| +|bcc|list of bcc addressees|string[] _(optional)_| +|subject|the subject line of the email|string| +|message|the message text|string| + +---- + +## Slack + +ID: `.slack` + +This action type interfaces with the [Slack Incoming Webhooks feature](https://api.slack.com/incoming-webhooks). Currently the params property `message` will be used as the `text` property of the Slack incoming message. Additional function may be provided later. + +### `config` + +This action type has no `config` properties. + +### `secrets` + +|Property|Description|Type| +|---|---|---| +|webhookUrl|the url of the Slack incoming webhook|string| + +### `params` + +|Property|Description|Type| +|---|---|---| +|message|the message text|string| + +---- + +## Index + +ID: `.index` + +The config and params properties are modelled after the [Watcher Index Action](https://www.elastic.co/guide/en/elasticsearch/reference/master/actions-index.html). The index can be set in the config or params, and if set in config, then the index set in the params will be ignored. + +### `config` + +|Property|Description|Type| +|---|---|---| +|index|The Elasticsearch index to index into.|string _(optional)_| + +### `secrets` + +This action type has no `secrets` properties. + +### `params` + +|Property|Description|Type| +|---|---|---| +|index|The Elasticsearch index to index into.|string _(optional)_| +|doc_id|The optional _id of the document.|string _(optional)_| +|execution_time_field|The field that will store/index the action execution time.|string _(optional)_| +|refresh|Setting of the refresh policy for the write request|boolean _(optional)_| +|body|The documument body/bodies to index.|object or object[]| + +---- +## Webhook + +ID: `.webhook` + +The webhook action uses [axios](https://github.com/axios/axios) to send a POST or PUT request to a web service. + +### `config` + +|Property|Description|Type| +|---|---|---| +|url|Request URL|string| +|method|HTTP request method, either `post`_(default)_ or `put`|string _(optional)_| +|headers|Key-value pairs of the headers to send with the request|object, keys and values are strings _(optional)_| + +### `secrets` + +|Property|Description|Type| +|---|---|---| +|user|Username for HTTP Basic authentication|string| +|password|Password for HTTP Basic authentication|string| + +### `params` + +|Property|Description|Type| +|---|---|---| +|body|The HTTP request body|string _(optional)_| + +---- + +## PagerDuty + +ID: `.pagerduty` + +The PagerDuty action uses the [V2 Events API](https://v2.developer.pagerduty.com/docs/events-api-v2) to trigger, acknowlege, and resolve PagerDuty alerts. + +### `config` + +|Property|Description|Type| +|---|---|---| +|apiUrl|PagerDuty event URL. Defaults to `https://events.pagerduty.com/v2/enqueue`|string _(optional)_| + +### `secrets` + +|Property|Description|Type| +|---|---|---| +|routingKey|This is the 32 character PagerDuty Integration Key for an integration on a service or on a global ruleset.|string| + +### `params` + +|Property|Description|Type| +|---|---|---| +|eventAction|One of `trigger` _(default)_, `resolve`, or `acknowlege`. See [event action](https://v2.developer.pagerduty.com/docs/events-api-v2#event-action) for more details.| string _(optional)_| +|dedupKey|All actions sharing this key will be associated with the same PagerDuty alert. Used to correlate trigger and resolution. Defaults to `action:`. The maximum length is **255** characters. See [alert deduplication](https://v2.developer.pagerduty.com/docs/events-api-v2#alert-de-duplication) for details. | string _(optional)_| +|summary|A text summary of the event, defaults to `No summary provided`. The maximum length is **1024** characters. | string _(optional)_| +|source|The affected system, preferably a hostname or fully qualified domain name. Defaults to `Kibana Action `.| string _(optional)_| +|severity|The perceived severity of on the affected system. This can be one of `critical`, `error`, `warning` or `info`_(default)_.| string _(optional)_| +|timestamp|An [ISO-8601 format date-time](https://v2.developer.pagerduty.com/v2/docs/types#datetime), indicating the time the event was detected or generated.| string _(optional)_| +|component|The component of the source machine that is responsible for the event, for example `mysql` or `eth0`.| string _(optional)_| +|group|Logical grouping of components of a service, for example `app-stack`.| string _(optional)_| +|class|The class/type of the event, for example `ping failure` or `cpu load`.| string _(optional)_| + +For more details see [PagerDuty v2 event parameters](https://v2.developer.pagerduty.com/v2/docs/send-an-event-events-api-v2). + +# Command Line Utility + +The [`kbn-action`](https://github.com/pmuellr/kbn-action) tool can be used to send HTTP requests to the Actions plugin. For instance, to create a Slack action from the `.slack` Action Type, use the following command: + +```console +$ kbn-action create .slack "post to slack" '{"webhookUrl": "https://hooks.slack.com/services/T0000/B0000/XXXX"}' +{ + "type": "action", + "id": "d6f1e228-1806-4a72-83ac-e06f3d5c2fbe", + "attributes": { + "actionTypeId": ".slack", + "name": "post to slack", + "config": {} + }, + "references": [], + "updated_at": "2019-06-26T17:55:42.728Z", + "version": "WzMsMV0=" +} +``` \ No newline at end of file diff --git a/x-pack/plugins/actions/common/index.ts b/x-pack/plugins/actions/common/index.ts new file mode 100644 index 00000000000000..9f4141dbcae7df --- /dev/null +++ b/x-pack/plugins/actions/common/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './types'; diff --git a/x-pack/plugins/actions/common/types.ts b/x-pack/plugins/actions/common/types.ts new file mode 100644 index 00000000000000..784125b83859d4 --- /dev/null +++ b/x-pack/plugins/actions/common/types.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export interface ActionType { + id: string; + name: string; + enabled: boolean; +} diff --git a/x-pack/plugins/actions/kibana.json b/x-pack/plugins/actions/kibana.json new file mode 100644 index 00000000000000..ff7f22af6261d1 --- /dev/null +++ b/x-pack/plugins/actions/kibana.json @@ -0,0 +1,10 @@ +{ + "id": "actions", + "server": true, + "version": "8.0.0", + "kibanaVersion": "kibana", + "configPath": ["xpack", "actions"], + "requiredPlugins": ["licensing", "taskManager", "encryptedSavedObjects", "event_log"], + "optionalPlugins": ["spaces"], + "ui": false +} diff --git a/x-pack/legacy/plugins/actions/server/action_type_registry.mock.ts b/x-pack/plugins/actions/server/action_type_registry.mock.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/action_type_registry.mock.ts rename to x-pack/plugins/actions/server/action_type_registry.mock.ts diff --git a/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts b/x-pack/plugins/actions/server/action_type_registry.test.ts similarity index 98% rename from x-pack/legacy/plugins/actions/server/action_type_registry.test.ts rename to x-pack/plugins/actions/server/action_type_registry.test.ts index 63f1b545179c73..79c9a449010797 100644 --- a/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts +++ b/x-pack/plugins/actions/server/action_type_registry.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { taskManagerMock } from '../../../../plugins/task_manager/server/task_manager.mock'; +import { taskManagerMock } from '../../task_manager/server/task_manager.mock'; import { ActionTypeRegistry } from './action_type_registry'; import { ExecutorType } from './types'; import { ActionExecutor, ExecutorError, TaskRunnerFactory } from './lib'; diff --git a/x-pack/legacy/plugins/actions/server/action_type_registry.ts b/x-pack/plugins/actions/server/action_type_registry.ts similarity index 94% rename from x-pack/legacy/plugins/actions/server/action_type_registry.ts rename to x-pack/plugins/actions/server/action_type_registry.ts index 351c1add7b4513..42e0ee9f523e1f 100644 --- a/x-pack/legacy/plugins/actions/server/action_type_registry.ts +++ b/x-pack/plugins/actions/server/action_type_registry.ts @@ -6,9 +6,10 @@ import Boom from 'boom'; import { i18n } from '@kbn/i18n'; -import { RunContext, TaskManagerSetupContract } from '../../../../plugins/task_manager/server'; +import { RunContext, TaskManagerSetupContract } from '../../task_manager/server'; import { ExecutorError, TaskRunnerFactory } from './lib'; import { ActionType } from './types'; +import { ActionType as CommonActionType } from '../common'; import { ActionsConfigurationUtilities } from './actions_config'; interface ConstructorOptions { @@ -98,7 +99,7 @@ export class ActionTypeRegistry { /** * Returns a list of registered action types [{ id, name, enabled }] */ - public list() { + public list(): CommonActionType[] { return Array.from(this.actionTypes).map(([actionTypeId, actionType]) => ({ id: actionTypeId, name: actionType.name, diff --git a/x-pack/legacy/plugins/actions/server/actions_client.mock.ts b/x-pack/plugins/actions/server/actions_client.mock.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/actions_client.mock.ts rename to x-pack/plugins/actions/server/actions_client.mock.ts diff --git a/x-pack/legacy/plugins/actions/server/actions_client.test.ts b/x-pack/plugins/actions/server/actions_client.test.ts similarity index 98% rename from x-pack/legacy/plugins/actions/server/actions_client.test.ts rename to x-pack/plugins/actions/server/actions_client.test.ts index dfbd2db4b68423..feca08fad922c0 100644 --- a/x-pack/legacy/plugins/actions/server/actions_client.test.ts +++ b/x-pack/plugins/actions/server/actions_client.test.ts @@ -10,14 +10,14 @@ import { ActionTypeRegistry } from './action_type_registry'; import { ActionsClient } from './actions_client'; import { ExecutorType } from './types'; import { ActionExecutor, TaskRunnerFactory } from './lib'; -import { taskManagerMock } from '../../../../plugins/task_manager/server/task_manager.mock'; +import { taskManagerMock } from '../../task_manager/server/task_manager.mock'; import { configUtilsMock } from './actions_config.mock'; import { getActionsConfigurationUtilities } from './actions_config'; import { elasticsearchServiceMock, savedObjectsClientMock, -} from '../../../../../src/core/server/mocks'; +} from '../../../../src/core/server/mocks'; const defaultKibanaIndex = '.kibana'; const savedObjectsClient = savedObjectsClientMock.create(); diff --git a/x-pack/legacy/plugins/actions/server/actions_client.ts b/x-pack/plugins/actions/server/actions_client.ts similarity index 99% rename from x-pack/legacy/plugins/actions/server/actions_client.ts rename to x-pack/plugins/actions/server/actions_client.ts index 104439ca4401fe..7ac8ea24b5218f 100644 --- a/x-pack/legacy/plugins/actions/server/actions_client.ts +++ b/x-pack/plugins/actions/server/actions_client.ts @@ -10,7 +10,7 @@ import { SavedObjectsClientContract, SavedObjectAttributes, SavedObject, -} from 'src/core/server'; +} from '../../../../src/core/server'; import { ActionTypeRegistry } from './action_type_registry'; import { validateConfig, validateSecrets } from './lib'; diff --git a/x-pack/legacy/plugins/actions/server/actions_config.mock.ts b/x-pack/plugins/actions/server/actions_config.mock.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/actions_config.mock.ts rename to x-pack/plugins/actions/server/actions_config.mock.ts diff --git a/x-pack/legacy/plugins/actions/server/actions_config.test.ts b/x-pack/plugins/actions/server/actions_config.test.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/actions_config.test.ts rename to x-pack/plugins/actions/server/actions_config.test.ts diff --git a/x-pack/legacy/plugins/actions/server/actions_config.ts b/x-pack/plugins/actions/server/actions_config.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/actions_config.ts rename to x-pack/plugins/actions/server/actions_config.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts b/x-pack/plugins/actions/server/builtin_action_types/email.test.ts similarity index 98% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/email.test.ts index 74263c603c11e9..4ad4fe96f34475 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/email.test.ts @@ -8,8 +8,8 @@ jest.mock('./lib/send_email', () => ({ sendEmail: jest.fn(), })); -import { Logger } from '../../../../../../src/core/server'; -import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { Logger } from '../../../../../src/core/server'; +import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; import { ActionType, ActionTypeExecutorOptions } from '../types'; import { configUtilsMock } from '../actions_config.mock'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts b/x-pack/plugins/actions/server/builtin_action_types/email.ts similarity index 99% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts rename to x-pack/plugins/actions/server/builtin_action_types/email.ts index 94d7852e76fad7..b209e7bbca6f7b 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/email.ts @@ -12,7 +12,7 @@ import nodemailerGetService from 'nodemailer/lib/well-known'; import { sendEmail, JSON_TRANSPORT_SERVICE } from './lib/send_email'; import { nullableType } from './lib/nullable'; import { portSchema } from './lib/schemas'; -import { Logger } from '../../../../../../src/core/server'; +import { Logger } from '../../../../../src/core/server'; import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types'; import { ActionsConfigurationUtilities } from '../actions_config'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts b/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts similarity index 99% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts index dbac84ef681f19..a305f85650b9c7 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts @@ -10,7 +10,7 @@ jest.mock('./lib/send_email', () => ({ import { ActionType, ActionTypeExecutorOptions } from '../types'; import { validateConfig, validateParams } from '../lib'; -import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; import { createActionTypeRegistry } from './index.test'; import { ActionParamsType, ActionTypeConfigType } from './es_index'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts b/x-pack/plugins/actions/server/builtin_action_types/es_index.ts similarity index 98% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts rename to x-pack/plugins/actions/server/builtin_action_types/es_index.ts index ddf33ba63f71af..f8217046b2ea58 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/es_index.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import { nullableType } from './lib/nullable'; -import { Logger } from '../../../../../../src/core/server'; +import { Logger } from '../../../../../src/core/server'; import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types'; // config definition diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/index.test.ts b/x-pack/plugins/actions/server/builtin_action_types/index.test.ts similarity index 86% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/index.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/index.test.ts index 5fcf39c2e8fdd0..ff732f58d6c94c 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/index.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/index.test.ts @@ -6,10 +6,10 @@ import { ActionExecutor, TaskRunnerFactory } from '../lib'; import { ActionTypeRegistry } from '../action_type_registry'; -import { taskManagerMock } from '../../../../../plugins/task_manager/server/task_manager.mock'; +import { taskManagerMock } from '../../../task_manager/server/task_manager.mock'; import { registerBuiltInActionTypes } from './index'; -import { Logger } from '../../../../../../src/core/server'; -import { loggingServiceMock } from '../../../../../../src/core/server/mocks'; +import { Logger } from '../../../../../src/core/server'; +import { loggingServiceMock } from '../../../../../src/core/server/mocks'; import { configUtilsMock } from '../actions_config.mock'; const ACTION_TYPE_IDS = ['.index', '.email', '.pagerduty', '.server-log', '.slack', '.webhook']; diff --git a/x-pack/plugins/actions/server/builtin_action_types/index.ts b/x-pack/plugins/actions/server/builtin_action_types/index.ts new file mode 100644 index 00000000000000..a92a279d084399 --- /dev/null +++ b/x-pack/plugins/actions/server/builtin_action_types/index.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ActionTypeRegistry } from '../action_type_registry'; +import { ActionsConfigurationUtilities } from '../actions_config'; +import { Logger } from '../../../../../src/core/server'; + +import { getActionType as getEmailActionType } from './email'; +import { getActionType as getIndexActionType } from './es_index'; +import { getActionType as getPagerDutyActionType } from './pagerduty'; +import { getActionType as getServerLogActionType } from './server_log'; +import { getActionType as getServiceNowActionType } from './servicenow'; +import { getActionType as getSlackActionType } from './slack'; +import { getActionType as getWebhookActionType } from './webhook'; + +export function registerBuiltInActionTypes({ + actionsConfigUtils: configurationUtilities, + actionTypeRegistry, + logger, +}: { + actionsConfigUtils: ActionsConfigurationUtilities; + actionTypeRegistry: ActionTypeRegistry; + logger: Logger; +}) { + actionTypeRegistry.register(getEmailActionType({ logger, configurationUtilities })); + actionTypeRegistry.register(getIndexActionType({ logger })); + actionTypeRegistry.register(getPagerDutyActionType({ logger, configurationUtilities })); + actionTypeRegistry.register(getServerLogActionType({ logger })); + actionTypeRegistry.register(getServiceNowActionType({ configurationUtilities })); + actionTypeRegistry.register(getSlackActionType({ configurationUtilities })); + actionTypeRegistry.register(getWebhookActionType({ logger, configurationUtilities })); +} diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/http_rersponse_retry_header.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/http_rersponse_retry_header.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/http_rersponse_retry_header.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/http_rersponse_retry_header.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/nullable.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/nullable.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/nullable.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/nullable.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/post_pagerduty.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/post_pagerduty.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/post_pagerduty.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/post_pagerduty.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/post_servicenow.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/post_servicenow.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/post_servicenow.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/post_servicenow.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/result_type.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/result_type.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/result_type.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/result_type.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/schemas.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/schemas.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/schemas.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/schemas.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/send_email.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts similarity index 97% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/send_email.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts index ab949dbe2722da..74eead0708545f 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/send_email.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts @@ -9,7 +9,7 @@ import nodemailer from 'nodemailer'; import { default as MarkdownIt } from 'markdown-it'; -import { Logger } from '../../../../../../../src/core/server'; +import { Logger } from '../../../../../../src/core/server'; // an email "service" which doesn't actually send, just returns what it would send export const JSON_TRANSPORT_SERVICE = '__json'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/string_utils.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/string_utils.test.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/string_utils.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/string_utils.test.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/lib/string_utils.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/string_utils.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/lib/string_utils.ts rename to x-pack/plugins/actions/server/builtin_action_types/lib/string_utils.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts b/x-pack/plugins/actions/server/builtin_action_types/pagerduty.test.ts similarity index 99% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/pagerduty.test.ts index f60fdf7fef95e1..ab860e4c3bbba8 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/pagerduty.test.ts @@ -11,10 +11,10 @@ jest.mock('./lib/post_pagerduty', () => ({ import { getActionType } from './pagerduty'; import { ActionType, Services, ActionTypeExecutorOptions } from '../types'; import { validateConfig, validateSecrets, validateParams } from '../lib'; -import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; import { postPagerduty } from './lib/post_pagerduty'; import { createActionTypeRegistry } from './index.test'; -import { Logger } from '../../../../../../src/core/server'; +import { Logger } from '../../../../../src/core/server'; import { configUtilsMock } from '../actions_config.mock'; const postPagerdutyMock = postPagerduty as jest.Mock; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts b/x-pack/plugins/actions/server/builtin_action_types/pagerduty.ts similarity index 99% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts rename to x-pack/plugins/actions/server/builtin_action_types/pagerduty.ts index b26621702cf5be..62f46d3d62503c 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/pagerduty.ts @@ -8,7 +8,7 @@ import { curry } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import { postPagerduty } from './lib/post_pagerduty'; -import { Logger } from '../../../../../../src/core/server'; +import { Logger } from '../../../../../src/core/server'; import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types'; import { ActionsConfigurationUtilities } from '../actions_config'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts b/x-pack/plugins/actions/server/builtin_action_types/server_log.test.ts similarity index 96% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/server_log.test.ts index 8f28b9e8f51254..6a4482f362c2b5 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/server_log.test.ts @@ -6,8 +6,8 @@ import { ActionType } from '../types'; import { validateParams } from '../lib'; -import { Logger } from '../../../../../../src/core/server'; -import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { Logger } from '../../../../../src/core/server'; +import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; import { createActionTypeRegistry } from './index.test'; const ACTION_TYPE_ID = '.server-log'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts b/x-pack/plugins/actions/server/builtin_action_types/server_log.ts similarity index 97% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts rename to x-pack/plugins/actions/server/builtin_action_types/server_log.ts index 34b8602eeba368..62406cfaf66e19 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/server_log.ts @@ -8,7 +8,7 @@ import { curry } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; -import { Logger } from '../../../../../../src/core/server'; +import { Logger } from '../../../../../src/core/server'; import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types'; import { withoutControlCharacters } from './lib/string_utils'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/servicenow.test.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow.test.ts similarity index 99% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/servicenow.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/servicenow.test.ts index a445c6afde4d50..a6c43f48fa8031 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/servicenow.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow.test.ts @@ -11,7 +11,7 @@ jest.mock('./lib/post_servicenow', () => ({ import { getActionType } from './servicenow'; import { ActionType, Services, ActionTypeExecutorOptions } from '../types'; import { validateConfig, validateSecrets, validateParams } from '../lib'; -import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; import { postServiceNow } from './lib/post_servicenow'; import { createActionTypeRegistry } from './index.test'; import { configUtilsMock } from '../actions_config.mock'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/servicenow.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/servicenow.ts rename to x-pack/plugins/actions/server/builtin_action_types/servicenow.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts similarity index 98% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/slack.test.ts index aebc9c49935997..d33574666cebda 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts @@ -5,7 +5,7 @@ */ import { ActionType, Services, ActionTypeExecutorOptions } from '../types'; -import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; import { validateParams, validateSecrets } from '../lib'; import { getActionType } from './slack'; import { configUtilsMock } from '../actions_config.mock'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts rename to x-pack/plugins/actions/server/builtin_action_types/slack.ts diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.test.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts similarity index 99% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.test.ts rename to x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts index b95fef97ac7b9a..ae1d8c3fddc8b8 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts @@ -9,7 +9,7 @@ import { validateConfig, validateSecrets, validateParams } from '../lib'; import { configUtilsMock } from '../actions_config.mock'; import { ActionType } from '../types'; import { createActionTypeRegistry } from './index.test'; -import { Logger } from '../../../../../../src/core/server'; +import { Logger } from '../../../../../src/core/server'; const ACTION_TYPE_ID = '.webhook'; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts similarity index 99% rename from x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts rename to x-pack/plugins/actions/server/builtin_action_types/webhook.ts index fa88d3c72c1631..f7efb3b1e746cb 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts @@ -14,7 +14,7 @@ import { nullableType } from './lib/nullable'; import { isOk, promiseResult, Result } from './lib/result_type'; import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types'; import { ActionsConfigurationUtilities } from '../actions_config'; -import { Logger } from '../../../../../../src/core/server'; +import { Logger } from '../../../../../src/core/server'; // config definition enum WebhookMethods { diff --git a/x-pack/plugins/actions/server/config.test.ts b/x-pack/plugins/actions/server/config.test.ts new file mode 100644 index 00000000000000..67b7553c4a7361 --- /dev/null +++ b/x-pack/plugins/actions/server/config.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { configSchema } from './config'; + +describe('config validation', () => { + test('action defaults', () => { + const config: Record = {}; + expect(configSchema.validate(config)).toMatchInlineSnapshot(` + Object { + "enabled": true, + "enabledActionTypes": Array [ + "*", + ], + "whitelistedHosts": Array [ + "*", + ], + } + `); + }); +}); diff --git a/x-pack/plugins/actions/server/config.ts b/x-pack/plugins/actions/server/config.ts new file mode 100644 index 00000000000000..9e4795be6c2082 --- /dev/null +++ b/x-pack/plugins/actions/server/config.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { WhitelistedHosts, EnabledActionTypes } from './actions_config'; + +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), + whitelistedHosts: schema.arrayOf( + schema.oneOf([schema.string({ hostname: true }), schema.literal(WhitelistedHosts.Any)]), + { + defaultValue: [WhitelistedHosts.Any], + } + ), + enabledActionTypes: schema.arrayOf( + schema.oneOf([schema.string(), schema.literal(EnabledActionTypes.Any)]), + { + defaultValue: [WhitelistedHosts.Any], + } + ), +}); + +export type ActionsConfig = TypeOf; diff --git a/x-pack/plugins/actions/server/constants/plugin.ts b/x-pack/plugins/actions/server/constants/plugin.ts new file mode 100644 index 00000000000000..68082ccaa13992 --- /dev/null +++ b/x-pack/plugins/actions/server/constants/plugin.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { LICENSE_TYPE_BASIC, LicenseType } from '../../../../legacy/common/constants'; + +export const PLUGIN = { + ID: 'actions', + MINIMUM_LICENSE_REQUIRED: LICENSE_TYPE_BASIC as LicenseType, // TODO: supposed to be changed up on requirements + getI18nName: (i18n: any): string => + i18n.translate('xpack.actions.appName', { + defaultMessage: 'Actions', + }), +}; diff --git a/x-pack/legacy/plugins/actions/server/create_execute_function.test.ts b/x-pack/plugins/actions/server/create_execute_function.test.ts similarity index 96% rename from x-pack/legacy/plugins/actions/server/create_execute_function.test.ts rename to x-pack/plugins/actions/server/create_execute_function.test.ts index 7dbcfce5ee3359..258efb1500ab25 100644 --- a/x-pack/legacy/plugins/actions/server/create_execute_function.test.ts +++ b/x-pack/plugins/actions/server/create_execute_function.test.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { taskManagerMock } from '../../../../plugins/task_manager/server/task_manager.mock'; +import { taskManagerMock } from '../../task_manager/server/task_manager.mock'; import { createExecuteFunction } from './create_execute_function'; -import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../src/core/server/mocks'; const mockTaskManager = taskManagerMock.start(); const savedObjectsClient = savedObjectsClientMock.create(); diff --git a/x-pack/legacy/plugins/actions/server/create_execute_function.ts b/x-pack/plugins/actions/server/create_execute_function.ts similarity index 93% rename from x-pack/legacy/plugins/actions/server/create_execute_function.ts rename to x-pack/plugins/actions/server/create_execute_function.ts index ddd8b1df2327b2..42db37bbe89f45 100644 --- a/x-pack/legacy/plugins/actions/server/create_execute_function.ts +++ b/x-pack/plugins/actions/server/create_execute_function.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedObjectsClientContract } from 'src/core/server'; -import { TaskManagerStartContract } from '../../../../plugins/task_manager/server'; +import { SavedObjectsClientContract } from '../../../../src/core/server'; +import { TaskManagerStartContract } from '../../task_manager/server'; import { GetBasePathFunction } from './types'; interface CreateExecuteFunctionOptions { diff --git a/x-pack/plugins/actions/server/index.ts b/x-pack/plugins/actions/server/index.ts new file mode 100644 index 00000000000000..27098bc5417906 --- /dev/null +++ b/x-pack/plugins/actions/server/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginInitializerContext } from '../../../../src/core/server'; +import { ActionsPlugin } from './plugin'; +import { configSchema } from './config'; + +export { ActionsPlugin, ActionResult, ActionTypeExecutorOptions, ActionType } from './types'; +export { ActionsClient } from './actions_client'; +export { PluginSetupContract, PluginStartContract } from './plugin'; + +export const plugin = (initContext: PluginInitializerContext) => new ActionsPlugin(initContext); + +export const config = { + schema: configSchema, +}; diff --git a/x-pack/legacy/plugins/actions/server/lib/action_executor.mock.ts b/x-pack/plugins/actions/server/lib/action_executor.mock.ts similarity index 87% rename from x-pack/legacy/plugins/actions/server/lib/action_executor.mock.ts rename to x-pack/plugins/actions/server/lib/action_executor.mock.ts index 73e5e96ab24edb..b4419cd761bbe4 100644 --- a/x-pack/legacy/plugins/actions/server/lib/action_executor.mock.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.mock.ts @@ -9,7 +9,7 @@ import { ActionExecutorContract } from './action_executor'; const createActionExecutorMock = () => { const mocked: jest.Mocked = { initialize: jest.fn(), - execute: jest.fn(), + execute: jest.fn().mockResolvedValue({ status: 'ok', actionId: '' }), }; return mocked; }; diff --git a/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts similarity index 91% rename from x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts rename to x-pack/plugins/actions/server/lib/action_executor.test.ts index 7d9bf20e22aceb..7d4233db0f8d94 100644 --- a/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -4,15 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import Hapi from 'hapi'; +import { KibanaRequest } from '../../../../../src/core/server'; import { schema } from '@kbn/config-schema'; import { ActionExecutor } from './action_executor'; import { actionTypeRegistryMock } from '../action_type_registry.mock'; -import { encryptedSavedObjectsMock } from '../../../../../plugins/encrypted_saved_objects/server/mocks'; -import { - savedObjectsClientMock, - loggingServiceMock, -} from '../../../../../../src/core/server/mocks'; +import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks'; +import { savedObjectsClientMock, loggingServiceMock } from '../../../../../src/core/server/mocks'; +import { createEventLoggerMock } from '../../../event_log/server/event_logger.mock'; const actionExecutor = new ActionExecutor(); const savedObjectsClient = savedObjectsClientMock.create(); @@ -32,32 +30,18 @@ const executeParams = { params: { foo: true, }, - request: { - headers: {}, - getBasePath: () => '', - path: '/', - route: { settings: {} }, - url: { - href: '/', - }, - raw: { - req: { - url: '/', - }, - }, - } as Hapi.Request, + request: {} as KibanaRequest, }; actionExecutor.initialize({ logger: loggingServiceMock.create().get(), - spaces() { - return { - getSpaceId: () => 'some-namespace', - } as any; - }, + spaces: { + getSpaceId: () => 'some-namespace', + } as any, getServices, actionTypeRegistry, encryptedSavedObjectsPlugin, + eventLogger: createEventLoggerMock(), }); beforeEach(() => jest.resetAllMocks()); diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts new file mode 100644 index 00000000000000..be6916a74fe88d --- /dev/null +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -0,0 +1,169 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Logger, KibanaRequest } from '../../../../../src/core/server'; +import { validateParams, validateConfig, validateSecrets } from './validate_with_schema'; +import { + ActionTypeExecutorResult, + ActionTypeRegistryContract, + GetServicesFunction, + RawAction, +} from '../types'; +import { PluginStartContract as EncryptedSavedObjectsStartContract } from '../../../encrypted_saved_objects/server'; +import { SpacesServiceSetup } from '../../../spaces/server'; +import { EVENT_LOG_ACTIONS } from '../plugin'; +import { IEvent, IEventLogger } from '../../../event_log/server'; + +export interface ActionExecutorContext { + logger: Logger; + spaces?: SpacesServiceSetup; + getServices: GetServicesFunction; + encryptedSavedObjectsPlugin: EncryptedSavedObjectsStartContract; + actionTypeRegistry: ActionTypeRegistryContract; + eventLogger: IEventLogger; +} + +export interface ExecuteOptions { + actionId: string; + request: KibanaRequest; + params: Record; +} + +export type ActionExecutorContract = PublicMethodsOf; + +export class ActionExecutor { + private isInitialized = false; + private actionExecutorContext?: ActionExecutorContext; + + public initialize(actionExecutorContext: ActionExecutorContext) { + if (this.isInitialized) { + throw new Error('ActionExecutor already initialized'); + } + this.isInitialized = true; + this.actionExecutorContext = actionExecutorContext; + } + + public async execute({ + actionId, + params, + request, + }: ExecuteOptions): Promise { + if (!this.isInitialized) { + throw new Error('ActionExecutor not initialized'); + } + + const { + spaces, + getServices, + encryptedSavedObjectsPlugin, + actionTypeRegistry, + eventLogger, + } = this.actionExecutorContext!; + + const services = getServices(request); + const namespace = spaces && spaces.getSpaceId(request); + + // Ensure user can read the action before processing + const { + attributes: { actionTypeId, config, name }, + } = await services.savedObjectsClient.get('action', actionId); + + try { + actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); + } catch (err) { + return { status: 'error', actionId, message: err.message, retry: false }; + } + + // Only get encrypted attributes here, the remaining attributes can be fetched in + // the savedObjectsClient call + const { + attributes: { secrets }, + } = await encryptedSavedObjectsPlugin.getDecryptedAsInternalUser( + 'action', + actionId, + { + namespace: namespace === 'default' ? undefined : namespace, + } + ); + const actionType = actionTypeRegistry.get(actionTypeId); + + let validatedParams: Record; + let validatedConfig: Record; + let validatedSecrets: Record; + + try { + validatedParams = validateParams(actionType, params); + validatedConfig = validateConfig(actionType, config); + validatedSecrets = validateSecrets(actionType, secrets); + } catch (err) { + return { status: 'error', actionId, message: err.message, retry: false }; + } + + const actionLabel = `${actionTypeId}:${actionId}: ${name}`; + const event: IEvent = { + event: { action: EVENT_LOG_ACTIONS.execute }, + kibana: { namespace, saved_objects: [{ type: 'action', id: actionId }] }, + }; + + eventLogger.startTiming(event); + let rawResult: ActionTypeExecutorResult | null | undefined | void; + try { + rawResult = await actionType.executor({ + actionId, + services, + params: validatedParams, + config: validatedConfig, + secrets: validatedSecrets, + }); + } catch (err) { + rawResult = { + actionId, + status: 'error', + message: 'an error occurred while running the action executor', + serviceMessage: err.message, + retry: false, + }; + } + eventLogger.stopTiming(event); + + // allow null-ish return to indicate success + const result = rawResult || { + actionId, + status: 'ok', + }; + + if (result.status === 'ok') { + event.message = `action executed: ${actionLabel}`; + } else if (result.status === 'error') { + event.message = `action execution failure: ${actionLabel}`; + event.error = event.error || {}; + event.error.message = actionErrorToMessage(result); + } else { + event.message = `action execution returned unexpected result: ${actionLabel}`; + event.error = event.error || {}; + event.error.message = 'action execution returned unexpected result'; + } + + eventLogger.logEvent(event); + return result; + } +} + +function actionErrorToMessage(result: ActionTypeExecutorResult): string { + let message = result.message || 'unknown error running action'; + + if (result.serviceMessage) { + message = `${message}: ${result.serviceMessage}`; + } + + if (result.retry instanceof Date) { + message = `${message}; retry at ${result.retry.toISOString()}`; + } else if (result.retry) { + message = `${message}; retry: ${JSON.stringify(result.retry)}`; + } + + return message; +} diff --git a/x-pack/legacy/plugins/actions/server/lib/executor_error.ts b/x-pack/plugins/actions/server/lib/executor_error.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/lib/executor_error.ts rename to x-pack/plugins/actions/server/lib/executor_error.ts diff --git a/x-pack/legacy/plugins/actions/server/lib/index.ts b/x-pack/plugins/actions/server/lib/index.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/lib/index.ts rename to x-pack/plugins/actions/server/lib/index.ts diff --git a/x-pack/plugins/actions/server/lib/license_api_access.ts b/x-pack/plugins/actions/server/lib/license_api_access.ts new file mode 100644 index 00000000000000..2e650ebf5eb170 --- /dev/null +++ b/x-pack/plugins/actions/server/lib/license_api_access.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import Boom from 'boom'; +import { LicenseState } from './license_state'; + +export function verifyApiAccess(licenseState: LicenseState) { + const licenseCheckResults = licenseState.getLicenseInformation(); + + if (licenseCheckResults.showAppLink && licenseCheckResults.enableAppLink) { + return null; + } + + throw Boom.forbidden(licenseCheckResults.message); +} diff --git a/x-pack/plugins/actions/server/lib/license_state.mock.ts b/x-pack/plugins/actions/server/lib/license_state.mock.ts new file mode 100644 index 00000000000000..f36f3a9eaeadee --- /dev/null +++ b/x-pack/plugins/actions/server/lib/license_state.mock.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { of } from 'rxjs'; +import { LicenseState } from './license_state'; +import { LICENSE_CHECK_STATE, ILicense } from '../../../licensing/server'; + +export const mockLicenseState = () => { + const license: ILicense = { + uid: '123', + status: 'active', + isActive: true, + signature: 'sig', + isAvailable: true, + toJSON: () => ({ + signature: 'sig', + }), + getUnavailableReason: () => undefined, + hasAtLeast() { + return true; + }, + check() { + return { + state: LICENSE_CHECK_STATE.Valid, + }; + }, + getFeature() { + return { + isAvailable: true, + isEnabled: true, + }; + }, + }; + return new LicenseState(of(license)); +}; diff --git a/x-pack/legacy/plugins/actions/server/lib/license_state.test.ts b/x-pack/plugins/actions/server/lib/license_state.test.ts similarity index 91% rename from x-pack/legacy/plugins/actions/server/lib/license_state.test.ts rename to x-pack/plugins/actions/server/lib/license_state.test.ts index e58c52f63c8cb0..dbb70857dad5c5 100644 --- a/x-pack/legacy/plugins/actions/server/lib/license_state.test.ts +++ b/x-pack/plugins/actions/server/lib/license_state.test.ts @@ -6,8 +6,8 @@ import expect from '@kbn/expect'; import { LicenseState } from './license_state'; -import { licensingMock } from '../../../../../plugins/licensing/server/mocks'; -import { LICENSE_CHECK_STATE } from '../../../../../plugins/licensing/server'; +import { licensingMock } from '../../../licensing/server/mocks'; +import { LICENSE_CHECK_STATE } from '../../../licensing/server'; describe('license_state', () => { let getRawLicense: any; diff --git a/x-pack/legacy/plugins/actions/server/lib/license_state.ts b/x-pack/plugins/actions/server/lib/license_state.ts similarity index 80% rename from x-pack/legacy/plugins/actions/server/lib/license_state.ts rename to x-pack/plugins/actions/server/lib/license_state.ts index b4de23ef0a949d..7b25e55ac0ba10 100644 --- a/x-pack/legacy/plugins/actions/server/lib/license_state.ts +++ b/x-pack/plugins/actions/server/lib/license_state.ts @@ -4,11 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import Boom from 'boom'; import { i18n } from '@kbn/i18n'; import { Observable, Subscription } from 'rxjs'; -import { ILicense, LICENSE_CHECK_STATE } from '../../../../../plugins/licensing/common/types'; -import { assertNever } from '../../../../../../src/core/utils'; +import { assertNever } from '../../../../../src/core/utils'; +import { ILicense, LICENSE_CHECK_STATE } from '../../../licensing/common/types'; import { PLUGIN } from '../constants/plugin'; export interface ActionsLicenseInformation { @@ -79,16 +78,3 @@ export class LicenseState { } } } - -export function verifyApiAccessFactory(licenseState: LicenseState) { - function verifyApiAccess() { - const licenseCheckResults = licenseState.getLicenseInformation(); - - if (licenseCheckResults.showAppLink && licenseCheckResults.enableAppLink) { - return null; - } - - throw Boom.forbidden(licenseCheckResults.message); - } - return verifyApiAccess; -} diff --git a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts similarity index 75% rename from x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts rename to x-pack/plugins/actions/server/lib/task_runner_factory.test.ts index ad2b74da0d7d44..8890de2483290c 100644 --- a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts +++ b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts @@ -7,15 +7,13 @@ import sinon from 'sinon'; import { ExecutorError } from './executor_error'; import { ActionExecutor } from './action_executor'; -import { ConcreteTaskInstance, TaskStatus } from '../../../../../plugins/task_manager/server'; +import { ConcreteTaskInstance, TaskStatus } from '../../../task_manager/server'; import { TaskRunnerFactory } from './task_runner_factory'; import { actionTypeRegistryMock } from '../action_type_registry.mock'; import { actionExecutorMock } from './action_executor.mock'; -import { encryptedSavedObjectsMock } from '../../../../../plugins/encrypted_saved_objects/server/mocks'; -import { - savedObjectsClientMock, - loggingServiceMock, -} from '../../../../../../src/core/server/mocks'; +import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks'; +import { savedObjectsClientMock, loggingServiceMock } from 'src/core/server/mocks'; +import { createEventLoggerMock } from '../../../event_log/server/event_logger.mock'; const spaceIdToNamespace = jest.fn(); const actionTypeRegistry = actionTypeRegistryMock.create(); @@ -60,18 +58,23 @@ const actionExecutorInitializerParams = { logger: loggingServiceMock.create().get(), getServices: jest.fn().mockReturnValue(services), actionTypeRegistry, - spaces: () => undefined, encryptedSavedObjectsPlugin: mockedEncryptedSavedObjectsPlugin, + eventLogger: createEventLoggerMock(), }; const taskRunnerFactoryInitializerParams = { spaceIdToNamespace, + logger: loggingServiceMock.create().get(), encryptedSavedObjectsPlugin: mockedEncryptedSavedObjectsPlugin, getBasePath: jest.fn().mockReturnValue(undefined), + getScopedSavedObjectsClient: jest.fn().mockReturnValue(services.savedObjectsClient), }; beforeEach(() => { jest.resetAllMocks(); actionExecutorInitializerParams.getServices.mockReturnValue(services); + taskRunnerFactoryInitializerParams.getScopedSavedObjectsClient.mockReturnValue( + services.savedObjectsClient + ); }); test(`throws an error if factory isn't initialized`, () => { @@ -137,6 +140,56 @@ test('executes the task by calling the executor with proper parameters', async ( }); }); +test('cleans up action_task_params object', async () => { + const taskRunner = taskRunnerFactory.create({ + taskInstance: mockedTaskInstance, + }); + + mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok', actionId: '2' }); + spaceIdToNamespace.mockReturnValueOnce('namespace-test'); + mockedEncryptedSavedObjectsPlugin.getDecryptedAsInternalUser.mockResolvedValueOnce({ + id: '3', + type: 'action_task_params', + attributes: { + actionId: '2', + params: { baz: true }, + apiKey: Buffer.from('123:abc').toString('base64'), + }, + references: [], + }); + + await taskRunner.run(); + + expect(services.savedObjectsClient.delete).toHaveBeenCalledWith('action_task_params', '3'); +}); + +test('runs successfully when cleanup fails and logs the error', async () => { + const taskRunner = taskRunnerFactory.create({ + taskInstance: mockedTaskInstance, + }); + + mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok', actionId: '2' }); + spaceIdToNamespace.mockReturnValueOnce('namespace-test'); + mockedEncryptedSavedObjectsPlugin.getDecryptedAsInternalUser.mockResolvedValueOnce({ + id: '3', + type: 'action_task_params', + attributes: { + actionId: '2', + params: { baz: true }, + apiKey: Buffer.from('123:abc').toString('base64'), + }, + references: [], + }); + services.savedObjectsClient.delete.mockRejectedValueOnce(new Error('Fail')); + + await taskRunner.run(); + + expect(services.savedObjectsClient.delete).toHaveBeenCalledWith('action_task_params', '3'); + expect(taskRunnerFactoryInitializerParams.logger.error).toHaveBeenCalledWith( + 'Failed to cleanup action_task_params object [id="3"]: Fail' + ); +}); + test('throws an error with suggested retry logic when return status is error', async () => { const taskRunner = taskRunnerFactory.create({ taskInstance: mockedTaskInstance, diff --git a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.ts b/x-pack/plugins/actions/server/lib/task_runner_factory.ts similarity index 78% rename from x-pack/legacy/plugins/actions/server/lib/task_runner_factory.ts rename to x-pack/plugins/actions/server/lib/task_runner_factory.ts index 2dc3d1161399e6..c3e89e0c16efcc 100644 --- a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.ts +++ b/x-pack/plugins/actions/server/lib/task_runner_factory.ts @@ -6,14 +6,17 @@ import { ActionExecutorContract } from './action_executor'; import { ExecutorError } from './executor_error'; -import { RunContext } from '../../../../../plugins/task_manager/server'; -import { PluginStartContract as EncryptedSavedObjectsStartContract } from '../../../../../plugins/encrypted_saved_objects/server'; +import { Logger, CoreStart } from '../../../../../src/core/server'; +import { RunContext } from '../../../task_manager/server'; +import { PluginStartContract as EncryptedSavedObjectsStartContract } from '../../../encrypted_saved_objects/server'; import { ActionTaskParams, GetBasePathFunction, SpaceIdToNamespaceFunction } from '../types'; export interface TaskRunnerContext { + logger: Logger; encryptedSavedObjectsPlugin: EncryptedSavedObjectsStartContract; spaceIdToNamespace: SpaceIdToNamespaceFunction; getBasePath: GetBasePathFunction; + getScopedSavedObjectsClient: CoreStart['savedObjects']['getScopedClient']; } export class TaskRunnerFactory { @@ -40,9 +43,11 @@ export class TaskRunnerFactory { const { actionExecutor } = this; const { + logger, encryptedSavedObjectsPlugin, spaceIdToNamespace, getBasePath, + getScopedSavedObjectsClient, } = this.taskRunnerContext!; return { @@ -85,6 +90,7 @@ export class TaskRunnerFactory { actionId, request: fakeRequest, }); + if (executorResult.status === 'error') { // Task manager error handler only kicks in when an error thrown (at this time) // So what we have to do is throw when the return status is `error`. @@ -94,6 +100,17 @@ export class TaskRunnerFactory { executorResult.retry == null ? false : executorResult.retry ); } + + // Cleanup action_task_params object now that we're done with it + try { + const savedObjectsClient = getScopedSavedObjectsClient(fakeRequest); + await savedObjectsClient.delete('action_task_params', actionTaskParamsId); + } catch (e) { + // Log error only, we shouldn't fail the task because of an error here (if ever there's retry logic) + logger.error( + `Failed to cleanup action_task_params object [id="${actionTaskParamsId}"]: ${e.message}` + ); + } }, }; } diff --git a/x-pack/legacy/plugins/actions/server/lib/validate_with_schema.test.ts b/x-pack/plugins/actions/server/lib/validate_with_schema.test.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/lib/validate_with_schema.test.ts rename to x-pack/plugins/actions/server/lib/validate_with_schema.test.ts diff --git a/x-pack/legacy/plugins/actions/server/lib/validate_with_schema.ts b/x-pack/plugins/actions/server/lib/validate_with_schema.ts similarity index 100% rename from x-pack/legacy/plugins/actions/server/lib/validate_with_schema.ts rename to x-pack/plugins/actions/server/lib/validate_with_schema.ts diff --git a/x-pack/plugins/actions/server/mocks.ts b/x-pack/plugins/actions/server/mocks.ts new file mode 100644 index 00000000000000..4e000160aa4773 --- /dev/null +++ b/x-pack/plugins/actions/server/mocks.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { actionsClientMock } from './actions_client.mock'; diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts new file mode 100644 index 00000000000000..cb0e3347541fd7 --- /dev/null +++ b/x-pack/plugins/actions/server/plugin.ts @@ -0,0 +1,261 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { first, map } from 'rxjs/operators'; +import { + PluginInitializerContext, + Plugin, + CoreSetup, + CoreStart, + IClusterClient, + KibanaRequest, + Logger, + SharedGlobalConfig, + RequestHandler, + IContextProvider, + SavedObjectsServiceStart, +} from '../../../../src/core/server'; + +import { + PluginSetupContract as EncryptedSavedObjectsSetupContract, + PluginStartContract as EncryptedSavedObjectsStartContract, +} from '../../encrypted_saved_objects/server'; +import { TaskManagerSetupContract, TaskManagerStartContract } from '../../task_manager/server'; +import { LicensingPluginSetup } from '../../licensing/server'; +import { SpacesPluginSetup, SpacesServiceSetup } from '../../spaces/server'; + +import { ActionsConfig } from './config'; +import { Services } from './types'; +import { ActionExecutor, TaskRunnerFactory } from './lib'; +import { ActionsClient } from './actions_client'; +import { ActionTypeRegistry } from './action_type_registry'; +import { ExecuteOptions } from './create_execute_function'; +import { createExecuteFunction } from './create_execute_function'; +import { registerBuiltInActionTypes } from './builtin_action_types'; + +import { getActionsConfigurationUtilities } from './actions_config'; + +import { + createActionRoute, + deleteActionRoute, + findActionRoute, + getActionRoute, + updateActionRoute, + listActionTypesRoute, + executeActionRoute, +} from './routes'; +import { LicenseState } from './lib/license_state'; +import { IEventLogger, IEventLogService } from '../../event_log/server'; + +const EVENT_LOG_PROVIDER = 'actions'; +export const EVENT_LOG_ACTIONS = { + execute: 'execute', + executeViaHttp: 'execute-via-http', +}; + +export interface PluginSetupContract { + registerType: ActionTypeRegistry['register']; +} + +export interface PluginStartContract { + execute(options: ExecuteOptions): Promise; + getActionsClientWithRequest(request: KibanaRequest): Promise; +} + +export interface ActionsPluginsSetup { + taskManager: TaskManagerSetupContract; + encryptedSavedObjects: EncryptedSavedObjectsSetupContract; + licensing: LicensingPluginSetup; + spaces?: SpacesPluginSetup; + event_log: IEventLogService; +} +export interface ActionsPluginsStart { + encryptedSavedObjects: EncryptedSavedObjectsStartContract; + taskManager: TaskManagerStartContract; +} + +export class ActionsPlugin implements Plugin, PluginStartContract> { + private readonly kibanaIndex: Promise; + private readonly config: Promise; + + private readonly logger: Logger; + private serverBasePath?: string; + private adminClient?: IClusterClient; + private taskRunnerFactory?: TaskRunnerFactory; + private actionTypeRegistry?: ActionTypeRegistry; + private actionExecutor?: ActionExecutor; + private licenseState: LicenseState | null = null; + private spaces?: SpacesServiceSetup; + private eventLogger?: IEventLogger; + + constructor(initContext: PluginInitializerContext) { + this.config = initContext.config + .create() + .pipe(first()) + .toPromise(); + + this.kibanaIndex = initContext.config.legacy.globalConfig$ + .pipe( + first(), + map((config: SharedGlobalConfig) => config.kibana.index) + ) + .toPromise(); + + this.logger = initContext.logger.get('actions'); + } + + public async setup(core: CoreSetup, plugins: ActionsPluginsSetup): Promise { + // Encrypted attributes + // - `secrets` properties will be encrypted + // - `config` will be included in AAD + // - everything else excluded from AAD + plugins.encryptedSavedObjects.registerType({ + type: 'action', + attributesToEncrypt: new Set(['secrets']), + attributesToExcludeFromAAD: new Set(['name']), + }); + plugins.encryptedSavedObjects.registerType({ + type: 'action_task_params', + attributesToEncrypt: new Set(['apiKey']), + }); + + plugins.event_log.registerProviderActions(EVENT_LOG_PROVIDER, Object.values(EVENT_LOG_ACTIONS)); + this.eventLogger = plugins.event_log.getLogger({ + event: { provider: EVENT_LOG_PROVIDER }, + }); + + const actionExecutor = new ActionExecutor(); + const taskRunnerFactory = new TaskRunnerFactory(actionExecutor); + const actionsConfigUtils = getActionsConfigurationUtilities( + (await this.config) as ActionsConfig + ); + const actionTypeRegistry = new ActionTypeRegistry({ + taskRunnerFactory, + taskManager: plugins.taskManager, + actionsConfigUtils, + }); + this.taskRunnerFactory = taskRunnerFactory; + this.actionTypeRegistry = actionTypeRegistry; + this.serverBasePath = core.http.basePath.serverBasePath; + this.actionExecutor = actionExecutor; + this.adminClient = core.elasticsearch.adminClient; + this.spaces = plugins.spaces?.spacesService; + + registerBuiltInActionTypes({ + logger: this.logger, + actionTypeRegistry, + actionsConfigUtils, + }); + + core.http.registerRouteHandlerContext( + 'actions', + this.createRouteHandlerContext(await this.kibanaIndex) + ); + + // Routes + this.licenseState = new LicenseState(plugins.licensing.license$); + const router = core.http.createRouter(); + createActionRoute(router, this.licenseState); + deleteActionRoute(router, this.licenseState); + getActionRoute(router, this.licenseState); + findActionRoute(router, this.licenseState); + updateActionRoute(router, this.licenseState); + listActionTypesRoute(router, this.licenseState); + executeActionRoute(router, this.licenseState, actionExecutor); + + return { + registerType: actionTypeRegistry.register.bind(actionTypeRegistry), + }; + } + + public start(core: CoreStart, plugins: ActionsPluginsStart): PluginStartContract { + const { + logger, + actionExecutor, + actionTypeRegistry, + taskRunnerFactory, + kibanaIndex, + adminClient, + } = this; + + actionExecutor!.initialize({ + logger, + eventLogger: this.eventLogger!, + spaces: this.spaces, + getServices: this.getServicesFactory(core.savedObjects), + encryptedSavedObjectsPlugin: plugins.encryptedSavedObjects, + actionTypeRegistry: actionTypeRegistry!, + }); + + taskRunnerFactory!.initialize({ + logger, + encryptedSavedObjectsPlugin: plugins.encryptedSavedObjects, + getBasePath: this.getBasePath, + spaceIdToNamespace: this.spaceIdToNamespace, + getScopedSavedObjectsClient: core.savedObjects.getScopedClient, + }); + + return { + execute: createExecuteFunction({ + taskManager: plugins.taskManager, + getScopedSavedObjectsClient: core.savedObjects.getScopedClient, + getBasePath: this.getBasePath, + }), + // Ability to get an actions client from legacy code + async getActionsClientWithRequest(request: KibanaRequest) { + return new ActionsClient({ + savedObjectsClient: core.savedObjects.getScopedClient(request), + actionTypeRegistry: actionTypeRegistry!, + defaultKibanaIndex: await kibanaIndex, + scopedClusterClient: adminClient!.asScoped(request), + }); + }, + }; + } + + private getServicesFactory( + savedObjects: SavedObjectsServiceStart + ): (request: KibanaRequest) => Services { + const { adminClient } = this; + return request => ({ + callCluster: adminClient!.asScoped(request).callAsCurrentUser, + savedObjectsClient: savedObjects.getScopedClient(request), + }); + } + + private createRouteHandlerContext = ( + defaultKibanaIndex: string + ): IContextProvider, 'actions'> => { + const { actionTypeRegistry, adminClient } = this; + return async function actionsRouteHandlerContext(context, request) { + return { + getActionsClient: () => { + return new ActionsClient({ + savedObjectsClient: context.core!.savedObjects.client, + actionTypeRegistry: actionTypeRegistry!, + defaultKibanaIndex, + scopedClusterClient: adminClient!.asScoped(request), + }); + }, + listTypes: actionTypeRegistry!.list.bind(actionTypeRegistry!), + }; + }; + }; + + private spaceIdToNamespace = (spaceId?: string): string | undefined => { + return this.spaces && spaceId ? this.spaces.spaceIdToNamespace(spaceId) : undefined; + }; + + private getBasePath = (spaceId?: string): string => { + return this.spaces && spaceId ? this.spaces.getBasePath(spaceId) : this.serverBasePath!; + }; + + public stop() { + if (this.licenseState) { + this.licenseState.clean(); + } + } +} diff --git a/x-pack/plugins/actions/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/actions/server/routes/_mock_handler_arguments.ts new file mode 100644 index 00000000000000..ec525adb8eab6c --- /dev/null +++ b/x-pack/plugins/actions/server/routes/_mock_handler_arguments.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { RequestHandlerContext, KibanaRequest, KibanaResponseFactory } from 'kibana/server'; +import { identity } from 'lodash'; +import { httpServerMock } from '../../../../../src/core/server/mocks'; + +export function mockHandlerArguments( + { actionsClient, listTypes: listTypesRes = [] }: any, + req: any, + res?: Array> +): [RequestHandlerContext, KibanaRequest, KibanaResponseFactory] { + const listTypes = jest.fn(() => listTypesRes); + return [ + ({ + actions: { + listTypes, + getActionsClient() { + return ( + actionsClient || { + get: jest.fn(), + delete: jest.fn(), + update: jest.fn(), + find: jest.fn(), + create: jest.fn(), + } + ); + }, + }, + } as unknown) as RequestHandlerContext, + req as KibanaRequest, + mockResponseFactory(res), + ]; +} + +export const mockResponseFactory = (resToMock: Array> = []) => { + const factory: jest.Mocked = httpServerMock.createResponseFactory(); + resToMock.forEach((key: string) => { + if (key in factory) { + Object.defineProperty(factory, key, { + value: jest.fn(identity), + }); + } + }); + return (factory as unknown) as KibanaResponseFactory; +}; diff --git a/x-pack/plugins/actions/server/routes/create.test.ts b/x-pack/plugins/actions/server/routes/create.test.ts new file mode 100644 index 00000000000000..6f7ebf2735edda --- /dev/null +++ b/x-pack/plugins/actions/server/routes/create.test.ts @@ -0,0 +1,135 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { createActionRoute } from './create'; +import { mockRouter, RouterMock } from '../../../../../src/core/server/http/router/router.mock'; +import { mockLicenseState } from '../lib/license_state.mock'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { mockHandlerArguments } from './_mock_handler_arguments'; + +jest.mock('../lib/license_api_access.ts', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('createActionRoute', () => { + it('creates an action with proper parameters', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + createActionRoute(router, licenseState); + + const [config, handler] = router.post.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-all", + ], + } + `); + + const createResult = { + id: '1', + name: 'My name', + actionTypeId: 'abc', + config: { foo: true }, + }; + const actionsClient = { + create: jest.fn().mockResolvedValueOnce(createResult), + }; + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + body: { + name: 'My name', + actionTypeId: 'abc', + config: { foo: true }, + secrets: {}, + }, + }, + ['ok'] + ); + + expect(await handler(context, req, res)).toEqual({ body: createResult }); + + expect(actionsClient.create).toHaveBeenCalledTimes(1); + expect(actionsClient.create.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "action": Object { + "actionTypeId": "abc", + "config": Object { + "foo": true, + }, + "name": "My name", + "secrets": Object {}, + }, + }, + ] + `); + + expect(res.ok).toHaveBeenCalledWith({ + body: createResult, + }); + }); + + it('ensures the license allows creating actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + createActionRoute(router, licenseState); + + const [, handler] = router.post.mock.calls[0]; + + const actionsClient = { + create: jest.fn().mockResolvedValueOnce({ + id: '1', + name: 'My name', + actionTypeId: 'abc', + config: { foo: true }, + }), + }; + + const [context, req, res] = mockHandlerArguments(actionsClient, {}); + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); + + it('ensures the license check prevents creating actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + (verifyApiAccess as jest.Mock).mockImplementation(() => { + throw new Error('OMG'); + }); + + createActionRoute(router, licenseState); + + const [, handler] = router.post.mock.calls[0]; + + const actionsClient = { + create: jest.fn().mockResolvedValueOnce({ + id: '1', + name: 'My name', + actionTypeId: 'abc', + config: { foo: true }, + }), + }; + + const [context, req, res] = mockHandlerArguments(actionsClient, {}); + + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); +}); diff --git a/x-pack/plugins/actions/server/routes/create.ts b/x-pack/plugins/actions/server/routes/create.ts new file mode 100644 index 00000000000000..f8f9aff9323a02 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/create.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { + IRouter, + RequestHandlerContext, + KibanaRequest, + IKibanaResponse, + KibanaResponseFactory, +} from 'kibana/server'; +import { ActionResult } from '../types'; +import { LicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; + +export const bodySchema = schema.object({ + name: schema.string(), + actionTypeId: schema.string(), + config: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), + secrets: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), +}); + +export const createActionRoute = (router: IRouter, licenseState: LicenseState) => { + router.post( + { + path: `/api/action`, + validate: { + body: bodySchema, + }, + options: { + tags: ['access:actions-all'], + }, + }, + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + + const actionsClient = context.actions.getActionsClient(); + const action = req.body; + const actionRes: ActionResult = await actionsClient.create({ action }); + return res.ok({ + body: actionRes, + }); + }) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/delete.test.ts b/x-pack/plugins/actions/server/routes/delete.test.ts new file mode 100644 index 00000000000000..e44f3254134281 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/delete.test.ts @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { deleteActionRoute } from './delete'; +import { mockRouter, RouterMock } from '../../../../../src/core/server/http/router/router.mock'; +import { mockLicenseState } from '../lib/license_state.mock'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { mockHandlerArguments } from './_mock_handler_arguments'; + +jest.mock('../lib/license_api_access.ts', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('deleteActionRoute', () => { + it('deletes an action with proper parameters', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + deleteActionRoute(router, licenseState); + + const [config, handler] = router.delete.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action/{id}"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-all", + ], + } + `); + + const actionsClient = { + delete: jest.fn().mockResolvedValueOnce({}), + }; + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + params: { + id: '1', + }, + }, + ['noContent'] + ); + + expect(await handler(context, req, res)).toEqual(undefined); + + expect(actionsClient.delete).toHaveBeenCalledTimes(1); + expect(actionsClient.delete.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "id": "1", + }, + ] + `); + + expect(res.noContent).toHaveBeenCalled(); + }); + + it('ensures the license allows deleting actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + deleteActionRoute(router, licenseState); + + const [, handler] = router.delete.mock.calls[0]; + + const actionsClient = { + delete: jest.fn().mockResolvedValueOnce({}), + }; + + const [context, req, res] = mockHandlerArguments(actionsClient, { + params: { id: '1' }, + }); + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); + + it('ensures the license check prevents deleting actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + (verifyApiAccess as jest.Mock).mockImplementation(() => { + throw new Error('OMG'); + }); + + deleteActionRoute(router, licenseState); + + const [, handler] = router.delete.mock.calls[0]; + + const actionsClient = { + delete: jest.fn().mockResolvedValueOnce({}), + }; + + const [context, req, res] = mockHandlerArguments(actionsClient, { + id: '1', + }); + + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); +}); diff --git a/x-pack/plugins/actions/server/routes/delete.ts b/x-pack/plugins/actions/server/routes/delete.ts new file mode 100644 index 00000000000000..d96523997ad349 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/delete.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { + IRouter, + RequestHandlerContext, + KibanaRequest, + IKibanaResponse, + KibanaResponseFactory, +} from 'kibana/server'; +import { LicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const deleteActionRoute = (router: IRouter, licenseState: LicenseState) => { + router.delete( + { + path: `/api/action/{id}`, + validate: { + params: paramSchema, + }, + options: { + tags: ['access:actions-all'], + }, + }, + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any, any, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + const actionsClient = context.actions.getActionsClient(); + const { id } = req.params; + await actionsClient.delete({ id }); + return res.noContent(); + }) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/execute.test.ts b/x-pack/plugins/actions/server/routes/execute.test.ts new file mode 100644 index 00000000000000..d8b57b2fb849a7 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/execute.test.ts @@ -0,0 +1,184 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { executeActionRoute } from './execute'; +import { mockRouter, RouterMock } from '../../../../../src/core/server/http/router/router.mock'; +import { mockLicenseState } from '../lib/license_state.mock'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { mockHandlerArguments } from './_mock_handler_arguments'; +import { ActionExecutorContract } from '../lib'; + +jest.mock('../lib/license_api_access.ts', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('executeActionRoute', () => { + it('executes an action with proper parameters', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + const [context, req, res] = mockHandlerArguments( + {}, + { + body: { + params: { + someData: 'data', + }, + }, + params: { + id: '1', + }, + }, + ['ok'] + ); + + const executeResult = { + actionId: '1', + status: 'ok', + }; + const actionExecutor = { + initialize: jest.fn(), + execute: jest.fn(async ({ params, request, actionId }) => { + return executeResult; + }), + } as jest.Mocked; + + executeActionRoute(router, licenseState, actionExecutor); + + const [config, handler] = router.post.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action/{id}/_execute"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-read", + ], + } + `); + + expect(await handler(context, req, res)).toEqual({ body: executeResult }); + + expect(actionExecutor.execute).toHaveBeenCalledWith({ + actionId: '1', + params: { + someData: 'data', + }, + request: req, + }); + + expect(res.ok).toHaveBeenCalled(); + }); + + it('returns a "204 NO CONTENT" when the executor returns a nullish value', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + const [context, req, res] = mockHandlerArguments( + {}, + { + body: { + params: {}, + }, + params: { + id: '1', + }, + }, + ['noContent'] + ); + + const actionExecutor = { + initialize: jest.fn(), + execute: jest.fn(), + } as jest.Mocked; + + executeActionRoute(router, licenseState, actionExecutor); + + const [, handler] = router.post.mock.calls[0]; + + expect(await handler(context, req, res)).toEqual(undefined); + + expect(actionExecutor.execute).toHaveBeenCalledWith({ + actionId: '1', + params: {}, + request: req, + }); + + expect(res.ok).not.toHaveBeenCalled(); + expect(res.noContent).toHaveBeenCalled(); + }); + + it('ensures the license allows action execution', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + const [context, req, res] = mockHandlerArguments( + {}, + { + body: {}, + params: {}, + }, + ['ok'] + ); + + const actionExecutor = { + initialize: jest.fn(), + execute: jest.fn(async ({ params, request, actionId }) => { + return { + actionId: '1', + status: 'ok', + }; + }), + } as jest.Mocked; + + executeActionRoute(router, licenseState, actionExecutor); + + const [, handler] = router.post.mock.calls[0]; + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); + + it('ensures the license check prevents action execution', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + (verifyApiAccess as jest.Mock).mockImplementation(() => { + throw new Error('OMG'); + }); + + const [context, req, res] = mockHandlerArguments( + {}, + { + body: {}, + params: {}, + }, + ['ok'] + ); + + const actionExecutor = { + initialize: jest.fn(), + execute: jest.fn(async ({ params, request, actionId }) => { + return { + actionId: '1', + status: 'ok', + }; + }), + } as jest.Mocked; + + executeActionRoute(router, licenseState, actionExecutor); + + const [, handler] = router.post.mock.calls[0]; + + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); +}); diff --git a/x-pack/plugins/actions/server/routes/execute.ts b/x-pack/plugins/actions/server/routes/execute.ts new file mode 100644 index 00000000000000..afccee3b5e70e8 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/execute.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; + * you may not use this file except in compliance with the Elastic License. + */ +import { schema, TypeOf } from '@kbn/config-schema'; +import { + IRouter, + RequestHandlerContext, + KibanaRequest, + IKibanaResponse, + KibanaResponseFactory, +} from 'kibana/server'; +import { LicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; + +import { ActionExecutorContract } from '../lib'; +import { ActionTypeExecutorResult } from '../types'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +const bodySchema = schema.object({ + params: schema.recordOf(schema.string(), schema.any()), +}); + +export const executeActionRoute = ( + router: IRouter, + licenseState: LicenseState, + actionExecutor: ActionExecutorContract +) => { + router.post( + { + path: '/api/action/{id}/_execute', + validate: { + body: bodySchema, + params: paramSchema, + }, + options: { + tags: ['access:actions-read'], + }, + }, + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any, TypeOf, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + const { params } = req.body; + const { id } = req.params; + const body: ActionTypeExecutorResult = await actionExecutor.execute({ + params, + request: req, + actionId: id, + }); + return body + ? res.ok({ + body, + }) + : res.noContent(); + }) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/find.test.ts b/x-pack/plugins/actions/server/routes/find.test.ts new file mode 100644 index 00000000000000..862e26132fdc35 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/find.test.ts @@ -0,0 +1,151 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { findActionRoute } from './find'; +import { mockRouter, RouterMock } from '../../../../../src/core/server/http/router/router.mock'; +import { mockLicenseState } from '../lib/license_state.mock'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { mockHandlerArguments } from './_mock_handler_arguments'; + +jest.mock('../lib/license_api_access.ts', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('findActionRoute', () => { + it('finds actions with proper parameters', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + findActionRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action/_find"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-read", + ], + } + `); + + const findResult = { + page: 1, + perPage: 1, + total: 0, + data: [], + }; + const actionsClient = { + find: jest.fn().mockResolvedValueOnce(findResult), + }; + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', + }, + }, + ['ok'] + ); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "data": Array [], + "page": 1, + "perPage": 1, + "total": 0, + }, + } + `); + + expect(actionsClient.find).toHaveBeenCalledTimes(1); + expect(actionsClient.find.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "options": Object { + "defaultSearchOperator": "OR", + "fields": undefined, + "filter": undefined, + "page": 1, + "perPage": 1, + "search": undefined, + "sortField": undefined, + }, + }, + ] + `); + + expect(res.ok).toHaveBeenCalledWith({ + body: findResult, + }); + }); + + it('ensures the license allows finding actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + findActionRoute(router, licenseState); + + const [, handler] = router.get.mock.calls[0]; + + const actionsClient = { + find: jest.fn().mockResolvedValueOnce({ + page: 1, + perPage: 1, + total: 0, + data: [], + }), + }; + + const [context, req, res] = mockHandlerArguments(actionsClient, { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', + }, + }); + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); + + it('ensures the license check prevents finding actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + (verifyApiAccess as jest.Mock).mockImplementation(() => { + throw new Error('OMG'); + }); + + findActionRoute(router, licenseState); + + const [, handler] = router.get.mock.calls[0]; + + const [context, req, res] = mockHandlerArguments( + {}, + { + query: { + per_page: 1, + page: 1, + default_search_operator: 'OR', + }, + }, + ['ok'] + ); + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); +}); diff --git a/x-pack/plugins/actions/server/routes/find.ts b/x-pack/plugins/actions/server/routes/find.ts new file mode 100644 index 00000000000000..04656d19bfeb4d --- /dev/null +++ b/x-pack/plugins/actions/server/routes/find.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { + IRouter, + RequestHandlerContext, + KibanaRequest, + IKibanaResponse, + KibanaResponseFactory, +} from 'kibana/server'; +import { FindOptions } from '../../../../legacy/plugins/alerting/server/alerts_client'; +import { LicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; + +// config definition +const querySchema = schema.object({ + per_page: schema.number({ defaultValue: 20, min: 0 }), + page: schema.number({ defaultValue: 1, min: 1 }), + search: schema.maybe(schema.string()), + default_search_operator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { + defaultValue: 'OR', + }), + search_fields: schema.maybe(schema.oneOf([schema.arrayOf(schema.string()), schema.string()])), + sort_field: schema.maybe(schema.string()), + has_reference: schema.maybe( + // use nullable as maybe is currently broken + // in config-schema + schema.nullable( + schema.object({ + type: schema.string(), + id: schema.string(), + }) + ) + ), + fields: schema.maybe(schema.arrayOf(schema.string())), + filter: schema.maybe(schema.string()), +}); + +export const findActionRoute = (router: IRouter, licenseState: LicenseState) => { + router.get( + { + path: `/api/action/_find`, + validate: { + query: querySchema, + }, + options: { + tags: ['access:actions-read'], + }, + }, + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + const actionsClient = context.actions.getActionsClient(); + const query = req.query; + const options: FindOptions['options'] = { + perPage: query.per_page, + page: query.page, + search: query.search, + defaultSearchOperator: query.default_search_operator, + sortField: query.sort_field, + fields: query.fields, + filter: query.filter, + }; + + if (query.search_fields) { + options.searchFields = Array.isArray(query.search_fields) + ? query.search_fields + : [query.search_fields]; + } + + if (query.has_reference) { + options.hasReference = query.has_reference; + } + + const findResult = await actionsClient.find({ + options, + }); + return res.ok({ + body: findResult, + }); + }) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/get.test.ts b/x-pack/plugins/actions/server/routes/get.test.ts new file mode 100644 index 00000000000000..8762a68b192f2b --- /dev/null +++ b/x-pack/plugins/actions/server/routes/get.test.ts @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getActionRoute } from './get'; +import { mockRouter, RouterMock } from '../../../../../src/core/server/http/router/router.mock'; +import { mockLicenseState } from '../lib/license_state.mock'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { mockHandlerArguments } from './_mock_handler_arguments'; + +jest.mock('../lib/license_api_access.ts', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('getActionRoute', () => { + it('gets an action with proper parameters', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + getActionRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action/{id}"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-read", + ], + } + `); + + const getResult = { + id: '1', + actionTypeId: '2', + name: 'action name', + config: {}, + }; + const actionsClient = { + get: jest.fn().mockResolvedValueOnce(getResult), + }; + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + params: { id: '1' }, + }, + ['ok'] + ); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "actionTypeId": "2", + "config": Object {}, + "id": "1", + "name": "action name", + }, + } + `); + + expect(actionsClient.get).toHaveBeenCalledTimes(1); + expect(actionsClient.get.mock.calls[0][0].id).toEqual('1'); + + expect(res.ok).toHaveBeenCalledWith({ + body: getResult, + }); + }); + + it('ensures the license allows getting actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + getActionRoute(router, licenseState); + + const [, handler] = router.get.mock.calls[0]; + + const actionsClient = { + get: jest.fn().mockResolvedValueOnce({ + id: '1', + actionTypeId: '2', + name: 'action name', + config: {}, + }), + }; + + const [context, req, res] = mockHandlerArguments( + actionsClient, + { + params: { id: '1' }, + }, + ['ok'] + ); + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); + + it('ensures the license check prevents getting actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + (verifyApiAccess as jest.Mock).mockImplementation(() => { + throw new Error('OMG'); + }); + + getActionRoute(router, licenseState); + + const [, handler] = router.get.mock.calls[0]; + + const actionsClient = { + get: jest.fn().mockResolvedValueOnce({ + id: '1', + actionTypeId: '2', + name: 'action name', + config: {}, + }), + }; + + const [context, req, res] = mockHandlerArguments( + actionsClient, + { + params: { id: '1' }, + }, + ['ok'] + ); + + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); +}); diff --git a/x-pack/plugins/actions/server/routes/get.ts b/x-pack/plugins/actions/server/routes/get.ts new file mode 100644 index 00000000000000..26aa74da5d36b7 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/get.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { + IRouter, + RequestHandlerContext, + KibanaRequest, + IKibanaResponse, + KibanaResponseFactory, +} from 'kibana/server'; +import { LicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const getActionRoute = (router: IRouter, licenseState: LicenseState) => { + router.get( + { + path: `/api/action/{id}`, + validate: { + params: paramSchema, + }, + options: { + tags: ['access:actions-read'], + }, + }, + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any, any, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + const actionsClient = context.actions.getActionsClient(); + const { id } = req.params; + return res.ok({ + body: await actionsClient.get({ id }), + }); + }) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/index.ts b/x-pack/plugins/actions/server/routes/index.ts new file mode 100644 index 00000000000000..33191132bece55 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { createActionRoute } from './create'; +export { deleteActionRoute } from './delete'; +export { findActionRoute } from './find'; +export { getActionRoute } from './get'; +export { updateActionRoute } from './update'; +export { listActionTypesRoute } from './list_action_types'; +export { executeActionRoute } from './execute'; diff --git a/x-pack/plugins/actions/server/routes/list_action_types.test.ts b/x-pack/plugins/actions/server/routes/list_action_types.test.ts new file mode 100644 index 00000000000000..87cc4dfee5336f --- /dev/null +++ b/x-pack/plugins/actions/server/routes/list_action_types.test.ts @@ -0,0 +1,147 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { listActionTypesRoute } from './list_action_types'; +import { mockRouter, RouterMock } from '../../../../../src/core/server/http/router/router.mock'; +import { mockLicenseState } from '../lib/license_state.mock'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { mockHandlerArguments } from './_mock_handler_arguments'; + +jest.mock('../lib/license_api_access.ts', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('listActionTypesRoute', () => { + it('lists action types with proper parameters', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + listActionTypesRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action/types"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-read", + ], + } + `); + + const listTypes = [ + { + id: '1', + name: 'name', + enabled: true, + }, + ]; + + const [context, req, res] = mockHandlerArguments({ listTypes }, {}, ['ok']); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Array [ + Object { + "enabled": true, + "id": "1", + "name": "name", + }, + ], + } + `); + + expect(context.actions.listTypes).toHaveBeenCalledTimes(1); + + expect(res.ok).toHaveBeenCalledWith({ + body: listTypes, + }); + }); + + it('ensures the license allows listing action types', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + listActionTypesRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action/types"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-read", + ], + } + `); + + const listTypes = [ + { + id: '1', + name: 'name', + enabled: true, + }, + ]; + + const [context, req, res] = mockHandlerArguments( + { listTypes }, + { + params: { id: '1' }, + }, + ['ok'] + ); + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); + + it('ensures the license check prevents listing action types', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + (verifyApiAccess as jest.Mock).mockImplementation(() => { + throw new Error('OMG'); + }); + + listActionTypesRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action/types"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-read", + ], + } + `); + + const listTypes = [ + { + id: '1', + name: 'name', + enabled: true, + }, + ]; + + const [context, req, res] = mockHandlerArguments( + { listTypes }, + { + params: { id: '1' }, + }, + ['ok'] + ); + + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); +}); diff --git a/x-pack/plugins/actions/server/routes/list_action_types.ts b/x-pack/plugins/actions/server/routes/list_action_types.ts new file mode 100644 index 00000000000000..0b9791eedb39ca --- /dev/null +++ b/x-pack/plugins/actions/server/routes/list_action_types.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + IRouter, + RequestHandlerContext, + KibanaRequest, + IKibanaResponse, + KibanaResponseFactory, +} from 'kibana/server'; +import { LicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; + +export const listActionTypesRoute = (router: IRouter, licenseState: LicenseState) => { + router.get( + { + path: `/api/action/types`, + validate: {}, + options: { + tags: ['access:actions-read'], + }, + }, + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + return res.ok({ + body: context.actions.listTypes(), + }); + }) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/update.test.ts b/x-pack/plugins/actions/server/routes/update.test.ts new file mode 100644 index 00000000000000..10901937613950 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/update.test.ts @@ -0,0 +1,168 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { updateActionRoute } from './update'; +import { mockRouter, RouterMock } from '../../../../../src/core/server/http/router/router.mock'; +import { mockLicenseState } from '../lib/license_state.mock'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { mockHandlerArguments } from './_mock_handler_arguments'; + +jest.mock('../lib/license_api_access.ts', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('updateActionRoute', () => { + it('updates an action with proper parameters', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + updateActionRoute(router, licenseState); + + const [config, handler] = router.put.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/action/{id}"`); + expect(config.options).toMatchInlineSnapshot(` + Object { + "tags": Array [ + "access:actions-all", + ], + } + `); + + const updateResult = { + id: '1', + actionTypeId: 'my-action-type-id', + name: 'My name', + config: { foo: true }, + }; + + const actionsClient = { + update: jest.fn().mockResolvedValueOnce(updateResult), + }; + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + params: { + id: '1', + }, + body: { + name: 'My name', + config: { foo: true }, + secrets: { key: 'i8oh34yf9783y39' }, + }, + }, + ['ok'] + ); + + expect(await handler(context, req, res)).toEqual({ body: updateResult }); + + expect(actionsClient.update).toHaveBeenCalledTimes(1); + expect(actionsClient.update.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "action": Object { + "config": Object { + "foo": true, + }, + "name": "My name", + "secrets": Object { + "key": "i8oh34yf9783y39", + }, + }, + "id": "1", + }, + ] + `); + + expect(res.ok).toHaveBeenCalled(); + }); + + it('ensures the license allows deleting actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + updateActionRoute(router, licenseState); + + const [, handler] = router.put.mock.calls[0]; + + const updateResult = { + id: '1', + actionTypeId: 'my-action-type-id', + name: 'My name', + config: { foo: true }, + }; + + const actionsClient = { + update: jest.fn().mockResolvedValueOnce(updateResult), + }; + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + params: { + id: '1', + }, + body: { + name: 'My name', + config: { foo: true }, + secrets: { key: 'i8oh34yf9783y39' }, + }, + }, + ['ok'] + ); + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); + + it('ensures the license check prevents deleting actions', async () => { + const licenseState = mockLicenseState(); + const router: RouterMock = mockRouter.create(); + + (verifyApiAccess as jest.Mock).mockImplementation(() => { + throw new Error('OMG'); + }); + + updateActionRoute(router, licenseState); + + const [, handler] = router.put.mock.calls[0]; + + const updateResult = { + id: '1', + actionTypeId: 'my-action-type-id', + name: 'My name', + config: { foo: true }, + }; + + const actionsClient = { + update: jest.fn().mockResolvedValueOnce(updateResult), + }; + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + params: { + id: '1', + }, + body: { + name: 'My name', + config: { foo: true }, + secrets: { key: 'i8oh34yf9783y39' }, + }, + }, + ['ok'] + ); + + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + }); +}); diff --git a/x-pack/plugins/actions/server/routes/update.ts b/x-pack/plugins/actions/server/routes/update.ts new file mode 100644 index 00000000000000..9c5f32e8b91191 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/update.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { + IRouter, + RequestHandlerContext, + KibanaRequest, + IKibanaResponse, + KibanaResponseFactory, +} from 'kibana/server'; +import { LicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +const bodySchema = schema.object({ + name: schema.string(), + config: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), + secrets: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), +}); + +export const updateActionRoute = (router: IRouter, licenseState: LicenseState) => { + router.put( + { + path: `/api/action/{id}`, + validate: { + body: bodySchema, + params: paramSchema, + }, + options: { + tags: ['access:actions-all'], + }, + }, + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any, TypeOf, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + const actionsClient = context.actions.getActionsClient(); + const { id } = req.params; + const { name, config, secrets } = req.body; + return res.ok({ + body: await actionsClient.update({ + id, + action: { name, config, secrets }, + }), + }); + }) + ); +}; diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts new file mode 100644 index 00000000000000..2358f499c9f986 --- /dev/null +++ b/x-pack/plugins/actions/server/types.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SavedObjectsClientContract, SavedObjectAttributes } from '../../../../src/core/server'; +import { ActionTypeRegistry } from './action_type_registry'; +import { PluginSetupContract, PluginStartContract } from './plugin'; +import { ActionsClient } from './actions_client'; + +export type WithoutQueryAndParams = Pick>; +export type GetServicesFunction = (request: any) => Services; +export type ActionTypeRegistryContract = PublicMethodsOf; +export type GetBasePathFunction = (spaceId?: string) => string; +export type SpaceIdToNamespaceFunction = (spaceId?: string) => string | undefined; + +export interface Services { + callCluster(path: string, opts: any): Promise; + savedObjectsClient: SavedObjectsClientContract; +} + +declare module 'src/core/server' { + interface RequestHandlerContext { + actions: { + getActionsClient: () => ActionsClient; + listTypes: ActionTypeRegistry['list']; + }; + } +} + +export interface ActionsPlugin { + setup: PluginSetupContract; + start: PluginStartContract; +} + +export interface ActionsConfigType { + enabled: boolean; + whitelistedHosts: string[]; + enabledActionTypes: string[]; +} + +// the parameters passed to an action type executor function +export interface ActionTypeExecutorOptions { + actionId: string; + services: Services; + config: Record; + secrets: Record; + params: Record; +} + +export interface ActionResult { + id: string; + actionTypeId: string; + name: string; + config: Record; +} + +export interface FindActionResult extends ActionResult { + referencedByCount: number; +} + +// the result returned from an action type executor function +export interface ActionTypeExecutorResult { + actionId: string; + status: 'ok' | 'error'; + message?: string; + serviceMessage?: string; + data?: any; + retry?: null | boolean | Date; +} + +// signature of the action type executor function +export type ExecutorType = ( + options: ActionTypeExecutorOptions +) => Promise; + +interface ValidatorType { + validate(value: any): any; +} + +export type ActionTypeCreator = (config?: ActionsConfigType) => ActionType; +export interface ActionType { + id: string; + name: string; + maxAttempts?: number; + validate?: { + params?: ValidatorType; + config?: ValidatorType; + secrets?: ValidatorType; + }; + executor: ExecutorType; +} + +export interface RawAction extends SavedObjectAttributes { + actionTypeId: string; + name: string; + config: SavedObjectAttributes; + secrets: SavedObjectAttributes; +} + +export interface ActionTaskParams extends SavedObjectAttributes { + actionId: string; + params: Record; + apiKey?: string; +} diff --git a/x-pack/plugins/apm/kibana.json b/x-pack/plugins/apm/kibana.json index 40fee07742cf60..d60846131da747 100644 --- a/x-pack/plugins/apm/kibana.json +++ b/x-pack/plugins/apm/kibana.json @@ -5,5 +5,6 @@ "kibanaVersion": "kibana", "configPath": ["xpack", "apm"], "ui": false, - "requiredPlugins": ["apm_oss", "data", "home"] + "requiredPlugins": ["apm_oss", "data", "home"], + "optionalPlugins": ["cloud"] } diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index 11d91efdf6b01d..83ece92aebe45b 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -18,6 +18,9 @@ import { createApmAgentConfigurationIndex } from '../../../legacy/plugins/apm/se import { createApmApi } from '../../../legacy/plugins/apm/server/routes/create_apm_api'; import { getApmIndices } from '../../../legacy/plugins/apm/server/lib/settings/apm_indices/get_apm_indices'; import { APMConfig, mergeConfigs, APMXPackConfig } from '.'; +import { HomeServerPluginSetup } from '../../../../src/plugins/home/server'; +import { tutorialProvider } from './tutorial'; +import { CloudSetup } from '../../cloud/server'; export interface LegacySetup { server: Server; @@ -44,6 +47,8 @@ export class APMPlugin implements Plugin { core: CoreSetup, plugins: { apm_oss: APMOSSPlugin extends Plugin ? TSetup : never; + home: HomeServerPluginSetup; + cloud?: CloudSetup; } ) { const config$ = this.initContext.config.create(); @@ -68,6 +73,21 @@ export class APMPlugin implements Plugin { }); }); + plugins.home.tutorials.registerTutorial( + tutorialProvider({ + isEnabled: this.currentConfig['xpack.apm.ui.enabled'], + indexPatternTitle: this.currentConfig['apm_oss.indexPattern'], + cloud: plugins.cloud, + indices: { + errorIndices: this.currentConfig['apm_oss.errorIndices'], + metricsIndices: this.currentConfig['apm_oss.metricsIndices'], + onboardingIndices: this.currentConfig['apm_oss.onboardingIndices'], + sourcemapIndices: this.currentConfig['apm_oss.sourcemapIndices'], + transactionIndices: this.currentConfig['apm_oss.transactionIndices'], + }, + }) + ); + return { config$: mergedConfig$, registerLegacyAPI: once((__LEGACY: LegacySetup) => { diff --git a/x-pack/plugins/apm/server/tutorial/envs/elastic_cloud.ts b/x-pack/plugins/apm/server/tutorial/envs/elastic_cloud.ts new file mode 100644 index 00000000000000..9c66dd299b2a5c --- /dev/null +++ b/x-pack/plugins/apm/server/tutorial/envs/elastic_cloud.ts @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { INSTRUCTION_VARIANT } from '../../../../../../src/plugins/home/server'; + +import { + createNodeAgentInstructions, + createDjangoAgentInstructions, + createFlaskAgentInstructions, + createRailsAgentInstructions, + createRackAgentInstructions, + createJsAgentInstructions, + createGoAgentInstructions, + createJavaAgentInstructions, + createDotNetAgentInstructions, +} from '../instructions/apm_agent_instructions'; +import { CloudSetup } from '../../../../cloud/server'; + +export function createElasticCloudInstructions(cloudSetup?: CloudSetup) { + const apmServerUrl = cloudSetup?.apm.url; + const instructionSets = []; + + if (!apmServerUrl) { + instructionSets.push(getApmServerInstructionSet(cloudSetup)); + } + + instructionSets.push(getApmAgentInstructionSet(cloudSetup)); + + return { + instructionSets, + }; +} + +function getApmServerInstructionSet(cloudSetup?: CloudSetup) { + const cloudId = cloudSetup?.cloudId; + return { + title: i18n.translate('xpack.apm.tutorial.apmServer.title', { + defaultMessage: 'APM Server', + }), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.ESC, + instructions: [ + { + title: 'Enable the APM Server in the ESS console', + textPre: i18n.translate('xpack.apm.tutorial.elasticCloud.textPre', { + defaultMessage: + 'To enable the APM Server go to [the Elastic Cloud console](https://cloud.elastic.co/deployments?q={cloudId}) and enable APM in the deployment settings. Once enabled, refresh this page.', + values: { cloudId }, + }), + }, + ], + }, + ], + }; +} + +function getApmAgentInstructionSet(cloudSetup?: CloudSetup) { + const apmServerUrl = cloudSetup?.apm.url; + const secretToken = cloudSetup?.apm.secretToken; + + return { + title: i18n.translate('xpack.apm.tutorial.elasticCloudInstructions.title', { + defaultMessage: 'APM Agents', + }), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.NODE, + instructions: createNodeAgentInstructions(apmServerUrl, secretToken), + }, + { + id: INSTRUCTION_VARIANT.DJANGO, + instructions: createDjangoAgentInstructions(apmServerUrl, secretToken), + }, + { + id: INSTRUCTION_VARIANT.FLASK, + instructions: createFlaskAgentInstructions(apmServerUrl, secretToken), + }, + { + id: INSTRUCTION_VARIANT.RAILS, + instructions: createRailsAgentInstructions(apmServerUrl, secretToken), + }, + { + id: INSTRUCTION_VARIANT.RACK, + instructions: createRackAgentInstructions(apmServerUrl, secretToken), + }, + { + id: INSTRUCTION_VARIANT.JS, + instructions: createJsAgentInstructions(apmServerUrl), + }, + { + id: INSTRUCTION_VARIANT.GO, + instructions: createGoAgentInstructions(apmServerUrl, secretToken), + }, + { + id: INSTRUCTION_VARIANT.JAVA, + instructions: createJavaAgentInstructions(apmServerUrl, secretToken), + }, + { + id: INSTRUCTION_VARIANT.DOTNET, + instructions: createDotNetAgentInstructions(apmServerUrl, secretToken), + }, + ], + }; +} diff --git a/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts b/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts new file mode 100644 index 00000000000000..03cd21119b30b5 --- /dev/null +++ b/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts @@ -0,0 +1,186 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { INSTRUCTION_VARIANT } from '../../../../../../src/plugins/home/server'; +import { + createWindowsServerInstructions, + createEditConfig, + createStartServerUnixSysv, + createStartServerUnix, + createDownloadServerRpm, + createDownloadServerDeb, + createDownloadServerOsx, +} from '../instructions/apm_server_instructions'; +import { + createNodeAgentInstructions, + createDjangoAgentInstructions, + createFlaskAgentInstructions, + createRailsAgentInstructions, + createRackAgentInstructions, + createJsAgentInstructions, + createGoAgentInstructions, + createJavaAgentInstructions, + createDotNetAgentInstructions, +} from '../instructions/apm_agent_instructions'; + +export function onPremInstructions({ + errorIndices, + transactionIndices, + metricsIndices, + sourcemapIndices, + onboardingIndices, +}: { + errorIndices: string; + transactionIndices: string; + metricsIndices: string; + sourcemapIndices: string; + onboardingIndices: string; +}) { + const EDIT_CONFIG = createEditConfig(); + const START_SERVER_UNIX = createStartServerUnix(); + const START_SERVER_UNIX_SYSV = createStartServerUnixSysv(); + + return { + instructionSets: [ + { + title: i18n.translate('xpack.apm.tutorial.apmServer.title', { + defaultMessage: 'APM Server', + }), + callOut: { + title: i18n.translate('xpack.apm.tutorial.apmServer.callOut.title', { + defaultMessage: 'Important: Updating to 7.0 or higher', + }), + message: i18n.translate('xpack.apm.tutorial.apmServer.callOut.message', { + defaultMessage: `Please make sure your APM Server is updated to 7.0 or higher. \ + You can also migrate your 6.x data with the migration assistant found in Kibana's management section.`, + }), + iconType: 'alert', + }, + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [createDownloadServerOsx(), EDIT_CONFIG, START_SERVER_UNIX], + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [createDownloadServerDeb(), EDIT_CONFIG, START_SERVER_UNIX_SYSV], + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [createDownloadServerRpm(), EDIT_CONFIG, START_SERVER_UNIX_SYSV], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: createWindowsServerInstructions(), + }, + ], + statusCheck: { + title: i18n.translate('xpack.apm.tutorial.apmServer.statusCheck.title', { + defaultMessage: 'APM Server status', + }), + text: i18n.translate('xpack.apm.tutorial.apmServer.statusCheck.text', { + defaultMessage: + 'Make sure APM Server is running before you start implementing the APM agents.', + }), + btnLabel: i18n.translate('xpack.apm.tutorial.apmServer.statusCheck.btnLabel', { + defaultMessage: 'Check APM Server status', + }), + success: i18n.translate('xpack.apm.tutorial.apmServer.statusCheck.successMessage', { + defaultMessage: 'You have correctly setup APM Server', + }), + error: i18n.translate('xpack.apm.tutorial.apmServer.statusCheck.errorMessage', { + defaultMessage: + 'No APM Server detected. Please make sure it is running and you have updated to 7.0 or higher.', + }), + esHitsCheck: { + index: onboardingIndices, + query: { + bool: { + filter: [ + { term: { 'processor.event': 'onboarding' } }, + { range: { 'observer.version_major': { gte: 7 } } }, + ], + }, + }, + }, + }, + }, + { + title: i18n.translate('xpack.apm.tutorial.apmAgents.title', { + defaultMessage: 'APM Agents', + }), + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.JAVA, + instructions: createJavaAgentInstructions(), + }, + { + id: INSTRUCTION_VARIANT.JS, + instructions: createJsAgentInstructions(), + }, + { + id: INSTRUCTION_VARIANT.NODE, + instructions: createNodeAgentInstructions(), + }, + { + id: INSTRUCTION_VARIANT.DJANGO, + instructions: createDjangoAgentInstructions(), + }, + { + id: INSTRUCTION_VARIANT.FLASK, + instructions: createFlaskAgentInstructions(), + }, + { + id: INSTRUCTION_VARIANT.RAILS, + instructions: createRailsAgentInstructions(), + }, + { + id: INSTRUCTION_VARIANT.RACK, + instructions: createRackAgentInstructions(), + }, + { + id: INSTRUCTION_VARIANT.GO, + instructions: createGoAgentInstructions(), + }, + { + id: INSTRUCTION_VARIANT.DOTNET, + instructions: createDotNetAgentInstructions(), + }, + ], + statusCheck: { + title: i18n.translate('xpack.apm.tutorial.apmAgents.statusCheck.title', { + defaultMessage: 'Agent status', + }), + text: i18n.translate('xpack.apm.tutorial.apmAgents.statusCheck.text', { + defaultMessage: + 'Make sure your application is running and the agents are sending data.', + }), + btnLabel: i18n.translate('xpack.apm.tutorial.apmAgents.statusCheck.btnLabel', { + defaultMessage: 'Check agent status', + }), + success: i18n.translate('xpack.apm.tutorial.apmAgents.statusCheck.successMessage', { + defaultMessage: 'Data successfully received from one or more agents', + }), + error: i18n.translate('xpack.apm.tutorial.apmAgents.statusCheck.errorMessage', { + defaultMessage: 'No data has been received from agents yet', + }), + esHitsCheck: { + index: [errorIndices, transactionIndices, metricsIndices, sourcemapIndices], + query: { + bool: { + filter: [ + { terms: { 'processor.event': ['error', 'transaction', 'metric', 'sourcemap'] } }, + { range: { 'observer.version_major': { gte: 7 } } }, + ], + }, + }, + }, + }, + }, + ], + }; +} diff --git a/x-pack/plugins/apm/server/tutorial/index.ts b/x-pack/plugins/apm/server/tutorial/index.ts new file mode 100644 index 00000000000000..bb5d553b26b364 --- /dev/null +++ b/x-pack/plugins/apm/server/tutorial/index.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { onPremInstructions } from './envs/on_prem'; +import { createElasticCloudInstructions } from './envs/elastic_cloud'; +import apmIndexPattern from './index_pattern.json'; +import { CloudSetup } from '../../../cloud/server'; +import { ArtifactsSchema, TutorialsCategory } from '../../../../../src/plugins/home/server'; + +const apmIntro = i18n.translate('xpack.apm.tutorial.introduction', { + defaultMessage: 'Collect in-depth performance metrics and errors from inside your applications.', +}); + +export const tutorialProvider = ({ + isEnabled, + indexPatternTitle, + cloud, + indices, +}: { + isEnabled: boolean; + indexPatternTitle: string; + cloud?: CloudSetup; + indices: { + errorIndices: string; + transactionIndices: string; + metricsIndices: string; + sourcemapIndices: string; + onboardingIndices: string; + }; +}) => () => { + const savedObjects = [ + { + ...apmIndexPattern, + attributes: { + ...apmIndexPattern.attributes, + title: indexPatternTitle, + }, + }, + ]; + + const artifacts: ArtifactsSchema = { + dashboards: [ + { + id: '8d3ed660-7828-11e7-8c47-65b845b5cfb3', + linkLabel: i18n.translate( + 'xpack.apm.tutorial.specProvider.artifacts.dashboards.linkLabel', + { + defaultMessage: 'APM dashboard', + } + ), + isOverview: true, + }, + ], + }; + + if (isEnabled) { + artifacts.application = { + path: '/app/apm', + label: i18n.translate('xpack.apm.tutorial.specProvider.artifacts.application.label', { + defaultMessage: 'Launch APM', + }), + }; + } + + return { + id: 'apm', + name: i18n.translate('xpack.apm.tutorial.specProvider.name', { + defaultMessage: 'APM', + }), + category: TutorialsCategory.OTHER, + shortDescription: apmIntro, + longDescription: i18n.translate('xpack.apm.tutorial.specProvider.longDescription', { + defaultMessage: + 'Application Performance Monitoring (APM) collects in-depth \ +performance metrics and errors from inside your application. \ +It allows you to monitor the performance of thousands of applications in real time. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: + '{config.docs.base_url}guide/en/apm/get-started/{config.docs.version}/index.html', + }, + }), + euiIconType: 'logoAPM', + artifacts, + onPrem: onPremInstructions(indices), + elasticCloud: createElasticCloudInstructions(cloud), + previewImagePath: '/plugins/kibana/home/tutorial_resources/apm/apm.png', + savedObjects, + savedObjectsInstallMsg: i18n.translate( + 'xpack.apm.tutorial.specProvider.savedObjectsInstallMsg', + { + defaultMessage: 'An APM index pattern is required for some features in the APM UI.', + } + ), + }; +}; diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json b/x-pack/plugins/apm/server/tutorial/index_pattern.json similarity index 100% rename from src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json rename to x-pack/plugins/apm/server/tutorial/index_pattern.json diff --git a/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts b/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts new file mode 100644 index 00000000000000..d1ef92df20f6fe --- /dev/null +++ b/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts @@ -0,0 +1,659 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const createNodeAgentInstructions = (apmServerUrl = '', secretToken = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.nodeClient.install.title', { + defaultMessage: 'Install the APM agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.nodeClient.install.textPre', { + defaultMessage: 'Install the APM agent for Node.js as a dependency to your application.', + }), + commands: ['npm install elastic-apm-node --save'], + }, + { + title: i18n.translate('xpack.apm.tutorial.nodeClient.configure.title', { + defaultMessage: 'Configure the agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.nodeClient.configure.textPre', { + defaultMessage: + 'Agents are libraries that run inside of your application process. \ +APM services are created programmatically based on the `serviceName`. \ +This agent supports a vararity of frameworks but can also be used with your custom stack.', + }), + commands: `// ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.addThisToTheFileTopComment', + { + defaultMessage: 'Add this to the VERY top of the first file loaded in your app', + } + )} +var apm = require('elastic-apm-node').start({curlyOpen} + // ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.setRequiredServiceNameComment', + { + defaultMessage: 'Override service name from package.json', + } + )} + // ${i18n.translate('xpack.apm.tutorial.nodeClient.configure.commands.allowedCharactersComment', { + defaultMessage: 'Allowed characters: a-z, A-Z, 0-9, -, _, and space', + })} + serviceName: '', + + // ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.useIfApmRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a token', + } + )} + secretToken: '${secretToken}', + + // ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomApmServerUrlComment', + { + defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } + )} + serverUrl: '${apmServerUrl}' +{curlyClose})`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.nodeClient.configure.textPost', { + defaultMessage: + 'See [the documentation]({documentationLink}) for advanced usage, including how to use with \ +[Babel/ES Modules]({babelEsModulesLink}).', + values: { + documentationLink: '{config.docs.base_url}guide/en/apm/agent/nodejs/current/index.html', + babelEsModulesLink: + '{config.docs.base_url}guide/en/apm/agent/nodejs/current/advanced-setup.html#es-modules', + }, + }), + }, +]; + +export const createDjangoAgentInstructions = (apmServerUrl = '', secretToken = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.djangoClient.install.title', { + defaultMessage: 'Install the APM agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.djangoClient.install.textPre', { + defaultMessage: 'Install the APM agent for Python as a dependency.', + }), + commands: ['$ pip install elastic-apm'], + }, + { + title: i18n.translate('xpack.apm.tutorial.djangoClient.configure.title', { + defaultMessage: 'Configure the agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.djangoClient.configure.textPre', { + defaultMessage: + 'Agents are libraries that run inside of your application process. \ +APM services are created programmatically based on the `SERVICE_NAME`.', + }), + commands: `# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.addAgentComment', + { + defaultMessage: 'Add the agent to the installed apps', + } + )} +INSTALLED_APPS = ( + 'elasticapm.contrib.django', + # ... +) + +ELASTIC_APM = {curlyOpen} + # ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment', + { + defaultMessage: 'Set required service name. Allowed characters:', + } + )} + # ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.allowedCharactersComment', + { + defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', + } + )} + 'SERVICE_NAME': '', + + # ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a token', + } + )} + 'SECRET_TOKEN': '${secretToken}', + + # ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment', + { + defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } + )} + 'SERVER_URL': '${apmServerUrl}', +{curlyClose} + +# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.addTracingMiddlewareComment', + { + defaultMessage: 'To send performance metrics, add our tracing middleware:', + } + )} +MIDDLEWARE = ( + 'elasticapm.contrib.django.middleware.TracingMiddleware', + #... +)`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.djangoClient.configure.textPost', { + defaultMessage: 'See the [documentation]({documentationLink}) for advanced usage.', + values: { + documentationLink: + '{config.docs.base_url}guide/en/apm/agent/python/current/django-support.html', + }, + }), + }, +]; + +export const createFlaskAgentInstructions = (apmServerUrl = '', secretToken = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.flaskClient.install.title', { + defaultMessage: 'Install the APM agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.flaskClient.install.textPre', { + defaultMessage: 'Install the APM agent for Python as a dependency.', + }), + commands: ['$ pip install elastic-apm[flask]'], + }, + { + title: i18n.translate('xpack.apm.tutorial.flaskClient.configure.title', { + defaultMessage: 'Configure the agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.flaskClient.configure.textPre', { + defaultMessage: + 'Agents are libraries that run inside of your application process. \ +APM services are created programmatically based on the `SERVICE_NAME`.', + }), + commands: `# ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment', + { + defaultMessage: 'initialize using environment variables', + } + )} +from elasticapm.contrib.flask import ElasticAPM +app = Flask(__name__) +apm = ElasticAPM(app) + +# ${i18n.translate('xpack.apm.tutorial.flaskClient.configure.commands.configureElasticApmComment', { + defaultMessage: "or configure to use ELASTIC_APM in your application's settings", + })} +from elasticapm.contrib.flask import ElasticAPM +app.config['ELASTIC_APM'] = {curlyOpen} + # ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment', + { + defaultMessage: 'Set required service name. Allowed characters:', + } + )} + # ${i18n.translate('xpack.apm.tutorial.flaskClient.configure.commands.allowedCharactersComment', { + defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', + })} + 'SERVICE_NAME': '', + + # ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a token', + } + )} + 'SECRET_TOKEN': '${secretToken}', + + # ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment', + { + defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } + )} + 'SERVER_URL': '${apmServerUrl}', +{curlyClose} + +apm = ElasticAPM(app)`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.flaskClient.configure.textPost', { + defaultMessage: 'See the [documentation]({documentationLink}) for advanced usage.', + values: { + documentationLink: + '{config.docs.base_url}guide/en/apm/agent/python/current/flask-support.html', + }, + }), + }, +]; + +export const createRailsAgentInstructions = (apmServerUrl = '', secretToken = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.railsClient.install.title', { + defaultMessage: 'Install the APM agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.railsClient.install.textPre', { + defaultMessage: 'Add the agent to your Gemfile.', + }), + commands: [`gem 'elastic-apm'`], + }, + { + title: i18n.translate('xpack.apm.tutorial.railsClient.configure.title', { + defaultMessage: 'Configure the agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.railsClient.configure.textPre', { + defaultMessage: + 'APM is automatically started when your app boots. Configure the agent, by creating the config file {configFile}', + values: { configFile: '`config/elastic_apm.yml`' }, + }), + commands: `# config/elastic_apm.yml: + +# Set service name - allowed characters: a-z, A-Z, 0-9, -, _ and space +# Defaults to the name of your Rails app +# service_name: 'my-service' + +# Use if APM Server requires a token +# secret_token: '${secretToken}' + +# Set custom APM Server URL (default: http://localhost:8200) +# server_url: '${apmServerUrl || 'http://localhost:8200'}'`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.railsClient.configure.textPost', { + defaultMessage: + 'See the [documentation]({documentationLink}) for configuration options and advanced usage.\n\n', + values: { + documentationLink: '{config.docs.base_url}guide/en/apm/agent/ruby/current/index.html', + }, + }), + }, +]; + +export const createRackAgentInstructions = (apmServerUrl = '', secretToken = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.rackClient.install.title', { + defaultMessage: 'Install the APM agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.rackClient.install.textPre', { + defaultMessage: 'Add the agent to your Gemfile.', + }), + commands: [`gem 'elastic-apm'`], + }, + { + title: i18n.translate('xpack.apm.tutorial.rackClient.configure.title', { + defaultMessage: 'Configure the agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.rackClient.configure.textPre', { + defaultMessage: + 'For Rack or a compatible framework (e.g. Sinatra), include the middleware in your app and start the agent.', + }), + commands: `# config.ru + require 'sinatra/base' + + class MySinatraApp < Sinatra::Base + use ElasticAPM::Middleware + + # ... + end + + ElasticAPM.start( + app: MySinatraApp, # ${i18n.translate( + 'xpack.apm.tutorial.rackClient.configure.commands.requiredComment', + { + defaultMessage: 'required', + } + )} + config_file: '' # ${i18n.translate( + 'xpack.apm.tutorial.rackClient.configure.commands.optionalComment', + { + defaultMessage: 'optional, defaults to config/elastic_apm.yml', + } + )} + ) + + run MySinatraApp + + at_exit {curlyOpen} ElasticAPM.stop {curlyClose}`.split('\n'), + }, + { + title: i18n.translate('xpack.apm.tutorial.rackClient.createConfig.title', { + defaultMessage: 'Create config file', + }), + textPre: i18n.translate('xpack.apm.tutorial.rackClient.createConfig.textPre', { + defaultMessage: 'Create a config file {configFile}:', + values: { configFile: '`config/elastic_apm.yml`' }, + }), + commands: `# config/elastic_apm.yml: + +# ${i18n.translate('xpack.apm.tutorial.rackClient.createConfig.commands.setServiceNameComment', { + defaultMessage: 'Set service name - allowed characters: a-z, A-Z, 0-9, -, _ and space', + })} +# ${i18n.translate( + 'xpack.apm.tutorial.rackClient.createConfig.commands.defaultsToTheNameOfRackAppClassComment', + { + defaultMessage: "Defaults to the name of your Rack app's class.", + } + )} +# service_name: 'my-service' + +# ${i18n.translate( + 'xpack.apm.tutorial.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a token', + } + )} +# secret_token: '${secretToken}' + +# ${i18n.translate( + 'xpack.apm.tutorial.rackClient.createConfig.commands.setCustomApmServerComment', + { + defaultMessage: 'Set custom APM Server URL (default: {defaultServerUrl})', + values: { defaultServerUrl: 'http://localhost:8200' }, + } + )} +# server_url: '${apmServerUrl || 'http://localhost:8200'}'`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.rackClient.createConfig.textPost', { + defaultMessage: + 'See the [documentation]({documentationLink}) for configuration options and advanced usage.\n\n', + values: { + documentationLink: '{config.docs.base_url}guide/en/apm/agent/ruby/current/index.html', + }, + }), + }, +]; + +export const createJsAgentInstructions = (apmServerUrl = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.jsClient.enableRealUserMonitoring.title', { + defaultMessage: 'Enable Real User Monitoring support in APM server', + }), + textPre: i18n.translate('xpack.apm.tutorial.jsClient.enableRealUserMonitoring.textPre', { + defaultMessage: + 'APM Server disables RUM support by default. See the [documentation]({documentationLink}) \ +for details on how to enable RUM support.', + values: { + documentationLink: + '{config.docs.base_url}guide/en/apm/server/{config.docs.version}/configuration-rum.html', + }, + }), + }, + { + title: i18n.translate('xpack.apm.tutorial.jsClient.installDependency.title', { + defaultMessage: 'Set up the Agent as a dependency', + }), + textPre: i18n.translate('xpack.apm.tutorial.jsClient.installDependency.textPre', { + defaultMessage: + 'You can install the Agent as a dependency to your application with \ +`npm install @elastic/apm-rum --save`.\n\n\ +The Agent can then be initialized and configured in your application like this:', + }), + commands: `import {curlyOpen} init as initApm {curlyClose} from '@elastic/apm-rum' +var apm = initApm({curlyOpen} + + // ${i18n.translate( + 'xpack.apm.tutorial.jsClient.installDependency.commands.setRequiredServiceNameComment', + { + defaultMessage: + 'Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)', + } + )} + serviceName: 'your-app-name', + + // ${i18n.translate( + 'xpack.apm.tutorial.jsClient.installDependency.commands.setCustomApmServerUrlComment', + { + defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } + )} + serverUrl: '${apmServerUrl}', + + // ${i18n.translate( + 'xpack.apm.tutorial.jsClient.installDependency.commands.setServiceVersionComment', + { + defaultMessage: 'Set service version (required for source map feature)', + } + )} + serviceVersion: '' +{curlyClose})`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.jsClient.installDependency.textPost', { + defaultMessage: + 'Framework integrations, like React or Angular, have custom dependencies. \ +See the [integration documentation]({docLink}) for more information.', + values: { + docLink: + '{config.docs.base_url}guide/en/apm/agent/rum-js/{config.docs.version}/framework-integrations.html', + }, + }), + }, + { + title: i18n.translate('xpack.apm.tutorial.jsClient.scriptTags.title', { + defaultMessage: 'Set up the Agent with Script Tags', + }), + textPre: i18n.translate('xpack.apm.tutorial.jsClient.scriptTags.textPre', { + defaultMessage: + "Alternatively, you can use Script tags to set up and configure the Agent. \ +Add a ` + +`.split('\n'), + }, +]; + +export const createGoAgentInstructions = (apmServerUrl = '', secretToken = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.goClient.install.title', { + defaultMessage: 'Install the APM agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.goClient.install.textPre', { + defaultMessage: 'Install the APM agent packages for Go.', + }), + commands: ['go get go.elastic.co/apm'], + }, + { + title: i18n.translate('xpack.apm.tutorial.goClient.configure.title', { + defaultMessage: 'Configure the agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.goClient.configure.textPre', { + defaultMessage: + 'Agents are libraries that run inside of your application process. \ +APM services are created programmatically based on the executable \ +file name, or the `ELASTIC_APM_SERVICE_NAME` environment variable.', + }), + commands: `# ${i18n.translate( + 'xpack.apm.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment', + { + defaultMessage: 'Initialize using environment variables:', + } + )} + +# ${i18n.translate('xpack.apm.tutorial.goClient.configure.commands.setServiceNameComment', { + defaultMessage: 'Set the service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space.', + })} +# ${i18n.translate('xpack.apm.tutorial.goClient.configure.commands.usedExecutableNameComment', { + defaultMessage: + 'If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used.', + })} +export ELASTIC_APM_SERVICE_NAME= + +# ${i18n.translate('xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment', { + defaultMessage: 'Set custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + })} +export ELASTIC_APM_SERVER_URL=${apmServerUrl} + +# ${i18n.translate('xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment', { + defaultMessage: 'Use if APM Server requires a token', + })} +export ELASTIC_APM_SECRET_TOKEN=${secretToken} +`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.goClient.configure.textPost', { + defaultMessage: 'See the [documentation]({documentationLink}) for advanced configuration.', + values: { + documentationLink: '{config.docs.base_url}guide/en/apm/agent/go/current/configuration.html', + }, + }), + }, + { + title: i18n.translate('xpack.apm.tutorial.goClient.instrument.title', { + defaultMessage: 'Instrument your application', + }), + textPre: i18n.translate('xpack.apm.tutorial.goClient.instrument.textPre', { + defaultMessage: + 'Instrument your Go application by using one of the provided instrumentation modules or \ +by using the tracer API directly.', + }), + commands: `\ +import ( + "net/http" + + "go.elastic.co/apm/module/apmhttp" +) + +func main() {curlyOpen} + mux := http.NewServeMux() + ... + http.ListenAndServe(":8080", apmhttp.Wrap(mux)) +{curlyClose} +`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.goClient.instrument.textPost', { + defaultMessage: + 'See the [documentation]({documentationLink}) for a detailed \ +guide to instrumenting Go source code.', + values: { + documentationLink: + '{config.docs.base_url}guide/en/apm/agent/go/current/instrumenting-source.html', + }, + }), + }, +]; + +export const createJavaAgentInstructions = (apmServerUrl = '', secretToken = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.javaClient.download.title', { + defaultMessage: 'Download the APM agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.javaClient.download.textPre', { + defaultMessage: + 'Download the agent jar from [Maven Central]({mavenCentralLink}). \ +Do **not** add the agent as a dependency to your application.', + values: { + mavenCentralLink: 'http://search.maven.org/#search%7Cga%7C1%7Ca%3Aelastic-apm-agent', + }, + }), + }, + { + title: i18n.translate('xpack.apm.tutorial.javaClient.startApplication.title', { + defaultMessage: 'Start your application with the javaagent flag', + }), + textPre: i18n.translate('xpack.apm.tutorial.javaClient.startApplication.textPre', { + defaultMessage: + 'Add the `-javaagent` flag and configure the agent with system properties.\n\n \ +* Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)\n \ +* Set custom APM Server URL (default: {customApmServerUrl})\n \ +* Set the base package of your application', + values: { customApmServerUrl: 'http://localhost:8200' }, + }), + commands: `java -javaagent:/path/to/elastic-apm-agent-.jar \\ + -Delastic.apm.service_name=my-application \\ + -Delastic.apm.server_url=${apmServerUrl || 'http://localhost:8200'} \\ + -Delastic.apm.secret_token=${secretToken} \\ + -Delastic.apm.application_packages=org.example \\ + -jar my-application.jar`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.javaClient.startApplication.textPost', { + defaultMessage: + 'See the [documentation]({documentationLink}) for configuration options and advanced \ +usage.', + values: { + documentationLink: '{config.docs.base_url}guide/en/apm/agent/java/current/index.html', + }, + }), + }, +]; + +export const createDotNetAgentInstructions = (apmServerUrl = '', secretToken = '') => [ + { + title: i18n.translate('xpack.apm.tutorial.dotNetClient.download.title', { + defaultMessage: 'Download the APM agent', + }), + textPre: i18n.translate('xpack.apm.tutorial.dotNetClient.download.textPre', { + defaultMessage: + 'Add the the agent package(s) from [NuGet]({allNuGetPackagesLink}) to your .NET application. There are multiple \ + NuGet packages available for different use cases. \n\nFor an ASP.NET Core application with Entity Framework \ + Core download the [Elastic.Apm.NetCoreAll]({netCoreAllApmPackageLink}) package. This package will automatically add every \ + agent component to your application. \n\n In case you would like to to minimize the dependencies, you can use the \ + [Elastic.Apm.AspNetCore]({aspNetCorePackageLink}) package for just \ + ASP.NET Core monitoring or the [Elastic.Apm.EfCore]({efCorePackageLink}) package for just Entity Framework Core monitoring. \n\n \ + In case you only want to use the public Agent API for manual instrumentation use the [Elastic.Apm]({elasticApmPackageLink}) package.', + values: { + allNuGetPackagesLink: 'https://www.nuget.org/packages?q=Elastic.apm', + netCoreAllApmPackageLink: 'https://www.nuget.org/packages/Elastic.Apm.NetCoreAll', + aspNetCorePackageLink: 'https://www.nuget.org/packages/Elastic.Apm.AspNetCore', + efCorePackageLink: 'https://www.nuget.org/packages/Elastic.Apm.EntityFrameworkCore', + elasticApmPackageLink: 'https://www.nuget.org/packages/Elastic.Apm', + }, + }), + }, + { + title: i18n.translate('xpack.apm.tutorial.dotNetClient.configureApplication.title', { + defaultMessage: 'Add the agent to the application', + }), + textPre: i18n.translate('xpack.apm.tutorial.dotNetClient.configureApplication.textPre', { + defaultMessage: + 'In case of ASP.NET Core with the `Elastic.Apm.NetCoreAll` package, call the `UseAllElasticApm` \ + method in the `Configure` method within the `Startup.cs` file.', + }), + commands: `public class Startup +{curlyOpen} + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + {curlyOpen} + app.UseAllElasticApm(Configuration); + //…rest of the method + {curlyClose} + //…rest of the class +{curlyClose}`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.dotNetClient.configureApplication.textPost', { + defaultMessage: + 'Passing an `IConfiguration` instance is optional and by doing so, the agent will read config settings through this \ + `IConfiguration` instance (e.g. from the `appsettings.json` file).', + }), + }, + { + title: i18n.translate('xpack.apm.tutorial.dotNetClient.configureAgent.title', { + defaultMessage: 'Sample appsettings.json file:', + }), + commands: `{curlyOpen} + "ElasticApm": {curlyOpen} + "SecretToken": "${secretToken}", + "ServerUrls": "${apmServerUrl || + 'http://localhost:8200'}", //Set custom APM Server URL (default: http://localhost:8200) + "ServiceName" : "MyApp", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application + {curlyClose} +{curlyClose}`.split('\n'), + textPost: i18n.translate('xpack.apm.tutorial.dotNetClient.configureAgent.textPost', { + defaultMessage: + 'In case you don’t pass an `IConfiguration` instance to the agent (e.g. in case of non ASP.NET Core applications) \ + you can also configure the agent through environment variables. \n \ + See [the documentation]({documentationLink}) for advanced usage.', + values: { + documentationLink: + '{config.docs.base_url}guide/en/apm/agent/dotnet/current/configuration.html', + }, + }), + }, +]; diff --git a/x-pack/plugins/apm/server/tutorial/instructions/apm_server_instructions.ts b/x-pack/plugins/apm/server/tutorial/instructions/apm_server_instructions.ts new file mode 100644 index 00000000000000..991c37c9759a92 --- /dev/null +++ b/x-pack/plugins/apm/server/tutorial/instructions/apm_server_instructions.ts @@ -0,0 +1,134 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const createEditConfig = () => ({ + title: i18n.translate('xpack.apm.tutorial.editConfig.title', { + defaultMessage: 'Edit the configuration', + }), + textPre: i18n.translate('xpack.apm.tutorial.editConfig.textPre', { + defaultMessage: + "If you're using an X-Pack secured version of Elastic Stack, you must specify \ +credentials in the `apm-server.yml` config file.", + }), + commands: [ + 'output.elasticsearch:', + ' hosts: [""]', + ' username: ', + ' password: ', + ], +}); + +const createStartServer = () => ({ + title: i18n.translate('xpack.apm.tutorial.startServer.title', { + defaultMessage: 'Start APM Server', + }), + textPre: i18n.translate('xpack.apm.tutorial.startServer.textPre', { + defaultMessage: + 'The server processes and stores application performance metrics in Elasticsearch.', + }), +}); + +export function createStartServerUnixSysv() { + const START_SERVER = createStartServer(); + + return { + title: START_SERVER.title, + textPre: START_SERVER.textPre, + commands: ['service apm-server start'], + }; +} + +export function createStartServerUnix() { + const START_SERVER = createStartServer(); + + return { + title: START_SERVER.title, + textPre: START_SERVER.textPre, + commands: ['./apm-server -e'], + }; +} + +const createDownloadServerTitle = () => + i18n.translate('xpack.apm.tutorial.downloadServer.title', { + defaultMessage: 'Download and unpack APM Server', + }); + +export const createDownloadServerOsx = () => ({ + title: createDownloadServerTitle(), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-{config.kibana.version}-darwin-x86_64.tar.gz', + 'tar xzvf apm-server-{config.kibana.version}-darwin-x86_64.tar.gz', + 'cd apm-server-{config.kibana.version}-darwin-x86_64/', + ], +}); + +export const createDownloadServerDeb = () => ({ + title: createDownloadServerTitle(), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-{config.kibana.version}-amd64.deb', + 'sudo dpkg -i apm-server-{config.kibana.version}-amd64.deb', + ], + textPost: i18n.translate('xpack.apm.tutorial.downloadServerTitle', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({downloadPageLink}).', + values: { downloadPageLink: '{config.docs.base_url}downloads/apm/apm-server' }, + }), +}); + +export const createDownloadServerRpm = () => ({ + title: createDownloadServerTitle(), + commands: [ + 'curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-{config.kibana.version}-x86_64.rpm', + 'sudo rpm -vi apm-server-{config.kibana.version}-x86_64.rpm', + ], + textPost: i18n.translate('xpack.apm.tutorial.downloadServerRpm', { + defaultMessage: 'Looking for the 32-bit packages? See the [Download page]({downloadPageLink}).', + values: { downloadPageLink: '{config.docs.base_url}downloads/apm/apm-server' }, + }), +}); + +export function createWindowsServerInstructions() { + const START_SERVER = createStartServer(); + + return [ + { + title: createDownloadServerTitle(), + textPre: i18n.translate('xpack.apm.tutorial.windowsServerInstructions.textPre', { + defaultMessage: + '1. Download the APM Server Windows zip file from the \ +[Download page]({downloadPageLink}).\n2. Extract the contents of \ +the zip file into {zipFileExtractFolder}.\n3. Rename the {apmServerDirectory} \ +directory to `APM-Server`.\n4. Open a PowerShell prompt as an Administrator \ +(right-click the PowerShell icon and select \ +**Run As Administrator**). If you are running Windows XP, you might need to download and install \ +PowerShell.\n5. From the PowerShell prompt, run the following commands to install APM Server as a Windows service:', + values: { + downloadPageLink: 'https://www.elastic.co/downloads/apm/apm-server', + zipFileExtractFolder: '`C:\\Program Files`', + apmServerDirectory: '`apm-server-{config.kibana.version}-windows`', + }, + }), + commands: [`cd 'C:\\Program Files\\APM-Server'`, `.\\install-service-apm-server.ps1`], + textPost: i18n.translate('xpack.apm.tutorial.windowsServerInstructions.textPost', { + defaultMessage: + 'Note: If script execution is disabled on your system, \ +you need to set the execution policy for the current session \ +to allow the script to run. For example: {command}.', + values: { + command: + '`PowerShell.exe -ExecutionPolicy UnRestricted -File .\\install-service-apm-server.ps1`', + }, + }), + }, + createEditConfig(), + { + title: START_SERVER.title, + textPre: START_SERVER.textPre, + commands: ['Start-Service apm-server'], + }, + ]; +} diff --git a/x-pack/plugins/encrypted_saved_objects/server/plugin.ts b/x-pack/plugins/encrypted_saved_objects/server/plugin.ts index 39da4c7d2d3531..ecd917ff90d003 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/plugin.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/plugin.ts @@ -71,7 +71,11 @@ export class Plugin { ) ); - this.savedObjectsSetup = setupSavedObjects({ service, savedObjects: core.savedObjects }); + this.savedObjectsSetup = setupSavedObjects({ + service, + savedObjects: core.savedObjects, + getStartServices: core.getStartServices, + }); return { registerType: (typeRegistration: EncryptedSavedObjectTypeRegistration) => diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts index c967c92deb6ffb..80bd2ab7b5171b 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts @@ -16,6 +16,7 @@ import { EncryptedSavedObjectsClientWrapper } from './encrypted_saved_objects_cl interface SetupSavedObjectsParams { service: PublicMethodsOf; savedObjects: CoreSetup['savedObjects']; + getStartServices: CoreSetup['getStartServices']; } export interface SavedObjectsSetup { @@ -29,6 +30,7 @@ export interface SavedObjectsSetup { export function setupSavedObjects({ service, savedObjects, + getStartServices, }: SetupSavedObjectsParams): SavedObjectsSetup { // Register custom saved object client that will encrypt, decrypt and strip saved object // attributes where appropriate for any saved object repository request. We choose max possible @@ -41,13 +43,16 @@ export function setupSavedObjects({ ({ client: baseClient }) => new EncryptedSavedObjectsClientWrapper({ baseClient, service }) ); - const internalRepository = savedObjects.createInternalRepository(); + const internalRepositoryPromise = getStartServices().then(([core]) => + core.savedObjects.createInternalRepository() + ); return { getDecryptedAsInternalUser: async ( type: string, id: string, options?: SavedObjectsBaseOptions ): Promise> => { + const internalRepository = await internalRepositoryPromise; const savedObject = await internalRepository.get(type, id, options); return { ...savedObject, diff --git a/x-pack/plugins/endpoint/common/types.ts b/x-pack/plugins/endpoint/common/types.ts new file mode 100644 index 00000000000000..1a1402671aa013 --- /dev/null +++ b/x-pack/plugins/endpoint/common/types.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export class EndpointAppConstants { + static ENDPOINT_INDEX_NAME = 'endpoint-agent*'; +} + +export interface EndpointResultList { + // the endpoint restricted by the page size + endpoints: EndpointMetadata[]; + // the total number of unique endpoints in the index + total: number; + // the page size requested + request_page_size: number; + // the index requested + request_page_index: number; +} + +export interface EndpointMetadata { + event: { + created: Date; + }; + endpoint: { + policy: { + id: string; + }; + }; + agent: { + version: string; + id: string; + }; + host: { + id: string; + hostname: string; + ip: string[]; + mac: string[]; + os: { + name: string; + full: string; + version: string; + }; + }; +} diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx index d69e068bdea3ad..7598141bdea659 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx @@ -19,12 +19,13 @@ import { appStoreFactory } from './store'; export function renderApp(coreStart: CoreStart, { appBasePath, element }: AppMountParameters) { coreStart.http.get('/api/endpoint/hello-world'); - const store = appStoreFactory(coreStart); + const [store, stopSagas] = appStoreFactory(coreStart); ReactDOM.render(, element); return () => { ReactDOM.unmountComponentAtNode(element); + stopSagas(); }; } diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.test.ts index 0387eac0e7c7fa..7c06681184085c 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.test.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.test.ts @@ -3,18 +3,21 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { createSagaMiddleware, SagaContext } from './index'; -import { applyMiddleware, createStore, Reducer } from 'redux'; + +import { createSagaMiddleware, SagaContext, SagaMiddleware } from './index'; +import { applyMiddleware, createStore, Reducer, Store } from 'redux'; describe('saga', () => { const INCREMENT_COUNTER = 'INCREMENT'; const DELAYED_INCREMENT_COUNTER = 'DELAYED INCREMENT COUNTER'; const STOP_SAGA_PROCESSING = 'BREAK ASYNC ITERATOR'; - const sleep = (ms = 1000) => new Promise(resolve => setTimeout(resolve, ms)); + const sleep = (ms = 100) => new Promise(resolve => setTimeout(resolve, ms)); + let store: Store; let reducerA: Reducer; let sideAffect: (a: unknown, s: unknown) => void; let sagaExe: (sagaContext: SagaContext) => Promise; + let sagaExeReduxMiddleware: SagaMiddleware; beforeEach(() => { reducerA = jest.fn((prevState = { count: 0 }, { type }) => { @@ -47,53 +50,63 @@ describe('saga', () => { } } }); + + sagaExeReduxMiddleware = createSagaMiddleware(sagaExe); + store = createStore(reducerA, applyMiddleware(sagaExeReduxMiddleware)); }); - test('it returns Redux Middleware from createSagaMiddleware()', () => { - const sagaMiddleware = createSagaMiddleware(async () => {}); - expect(sagaMiddleware).toBeInstanceOf(Function); + afterEach(() => { + sagaExeReduxMiddleware.stop(); }); + test('it does nothing if saga is not started', () => { - const store = createStore(reducerA, applyMiddleware(createSagaMiddleware(sagaExe))); - expect(store.getState().count).toEqual(0); - expect(reducerA).toHaveBeenCalled(); - expect(sagaExe).toHaveBeenCalled(); - expect(sideAffect).not.toHaveBeenCalled(); - expect(store.getState()).toEqual({ count: 0 }); + expect(sagaExe).not.toHaveBeenCalled(); }); - test('it updates store once running', async () => { - const sagaMiddleware = createSagaMiddleware(sagaExe); - const store = createStore(reducerA, applyMiddleware(sagaMiddleware)); + test('it can dispatch store actions once running', async () => { + sagaExeReduxMiddleware.start(); expect(store.getState()).toEqual({ count: 0 }); expect(sagaExe).toHaveBeenCalled(); store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); expect(store.getState()).toEqual({ count: 0 }); - await sleep(100); + await sleep(); expect(sideAffect).toHaveBeenCalled(); expect(store.getState()).toEqual({ count: 1 }); }); - test('it stops processing if break out of loop', async () => { - const sagaMiddleware = createSagaMiddleware(sagaExe); - const store = createStore(reducerA, applyMiddleware(sagaMiddleware)); + test('it stops processing if break out of loop', async () => { + sagaExeReduxMiddleware.start(); store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); - await sleep(100); + await sleep(); expect(store.getState()).toEqual({ count: 1 }); expect(sideAffect).toHaveBeenCalledTimes(2); store.dispatch({ type: STOP_SAGA_PROCESSING }); - await sleep(100); + await sleep(); + + store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); + await sleep(); + + expect(store.getState()).toEqual({ count: 1 }); + expect(sideAffect).toHaveBeenCalledTimes(2); + }); + + test('it stops saga middleware when stop() is called', async () => { + sagaExeReduxMiddleware.start(); + store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); + await sleep(); expect(store.getState()).toEqual({ count: 1 }); expect(sideAffect).toHaveBeenCalledTimes(2); + sagaExeReduxMiddleware.stop(); + store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); - await sleep(100); + await sleep(); expect(store.getState()).toEqual({ count: 1 }); expect(sideAffect).toHaveBeenCalledTimes(2); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.ts b/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.ts index b93360ec6b5aa7..bca6aa6563fe52 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.ts @@ -35,7 +35,20 @@ export interface SagaContext { dispatch: Dispatch; } +export interface SagaMiddleware extends Middleware { + /** + * Start the saga. Should be called after the `store` has been created + */ + start: () => void; + + /** + * Stop the saga by exiting the internal generator `for await...of` loop. + */ + stop: () => void; +} + const noop = () => {}; +const STOP = Symbol('STOP'); /** * Creates Saga Middleware for use with Redux. @@ -43,7 +56,7 @@ const noop = () => {}; * @param {Saga} saga The `saga` should initialize a long-running `for await...of` loop against * the return value of the `actionsAndState()` method provided by the `SagaContext`. * - * @return {Middleware} + * @return {SagaMiddleware} * * @example * @@ -64,22 +77,31 @@ const noop = () => {}; * //.... * const store = createStore(reducers, [ endpointsSagaMiddleware ]); */ -export function createSagaMiddleware(saga: Saga): Middleware { +export function createSagaMiddleware(saga: Saga): SagaMiddleware { const iteratorInstances = new Set(); let runSaga: () => void = noop; + let stopSaga: () => void = noop; + let runningPromise: Promise; async function* getActionsAndStateIterator(): StoreActionsAndState { const instance: IteratorInstance = { queue: [], nextResolve: null }; iteratorInstances.add(instance); + try { while (true) { - yield await nextActionAndState(); + const actionAndState = await Promise.race([nextActionAndState(), runningPromise]); + + if (actionAndState === STOP) { + break; + } + + yield actionAndState as QueuedAction; } } finally { // If the consumer stops consuming this (e.g. `break` or `return` is called in the `for await` // then this `finally` block will run and unregister this instance and reset `runSaga` iteratorInstances.delete(instance); - runSaga = noop; + runSaga = stopSaga = noop; } function nextActionAndState() { @@ -109,7 +131,6 @@ export function createSagaMiddleware(saga: Saga): Middleware { actionsAndState: getActionsAndStateIterator, dispatch, }); - runSaga(); } return (next: Dispatch) => (action: AnyAction) => { // Call the next dispatch method in the middleware chain. @@ -125,5 +146,14 @@ export function createSagaMiddleware(saga: Saga): Middleware { }; } + middleware.start = () => { + runningPromise = new Promise(resolve => (stopSaga = () => resolve(STOP))); + runSaga(); + }; + + middleware.stop = () => { + stopSaga(); + }; + return middleware; } diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/endpoint_list/saga.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/endpoint_list/saga.test.ts index 92bf3b7fd92dd8..6bf946873e1797 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/endpoint_list/saga.test.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/endpoint_list/saga.test.ts @@ -24,6 +24,7 @@ describe('endpoint list saga', () => { let fakeHttpServices: jest.Mocked; let store: Store; let dispatch: Dispatch; + let stopSagas: () => void; // TODO: consolidate the below ++ helpers in `index.test.ts` into a `test_helpers.ts`?? const generateEndpoint = (): EndpointData => { @@ -89,13 +90,19 @@ describe('endpoint list saga', () => { beforeEach(() => { fakeCoreStart = coreMock.createStart({ basePath: '/mock' }); fakeHttpServices = fakeCoreStart.http as jest.Mocked; - store = createStore( - endpointListReducer, - applyMiddleware(createSagaMiddleware(endpointListSagaFactory())) - ); + + const sagaMiddleware = createSagaMiddleware(endpointListSagaFactory()); + store = createStore(endpointListReducer, applyMiddleware(sagaMiddleware)); + + sagaMiddleware.start(); + stopSagas = sagaMiddleware.stop; dispatch = store.dispatch; }); + afterEach(() => { + stopSagas(); + }); + test('it handles `userEnteredEndpointListPage`', async () => { const apiResponse = getEndpointListApiResponse(); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/index.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/index.ts index d0dc002031ce2f..bfa1385b9f0ac0 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/index.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createStore, compose, applyMiddleware } from 'redux'; +import { createStore, compose, applyMiddleware, Store } from 'redux'; import { CoreStart } from 'kibana/public'; import { appSagaFactory } from './saga'; import { appReducer } from './reducer'; @@ -15,10 +15,13 @@ const composeWithReduxDevTools = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMP ? (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ name: 'EndpointApp' }) : compose; -export const appStoreFactory = (coreStart: CoreStart) => { +export const appStoreFactory = (coreStart: CoreStart): [Store, () => void] => { + const sagaReduxMiddleware = appSagaFactory(coreStart); const store = createStore( appReducer, - composeWithReduxDevTools(applyMiddleware(appSagaFactory(coreStart))) + composeWithReduxDevTools(applyMiddleware(sagaReduxMiddleware)) ); - return store; + + sagaReduxMiddleware.start(); + return [store, sagaReduxMiddleware.stop]; }; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/action.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/action.ts index 090d5de901318e..4153070ab04e7e 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/action.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/action.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Vector2 } from '../../types'; +import { Vector2, PanDirection } from '../../types'; interface UserSetZoomLevel { readonly type: 'userSetZoomLevel'; @@ -14,6 +14,14 @@ interface UserSetZoomLevel { readonly payload: number; } +interface UserClickedZoomOut { + readonly type: 'userClickedZoomOut'; +} + +interface UserClickedZoomIn { + readonly type: 'userClickedZoomIn'; +} + interface UserZoomed { readonly type: 'userZoomed'; /** @@ -56,6 +64,14 @@ interface UserStoppedPanning { readonly type: 'userStoppedPanning'; } +interface UserClickedPanControl { + readonly type: 'userClickedPanControl'; + /** + * String that represents the direction in which Resolver can be panned + */ + readonly payload: PanDirection; +} + interface UserMovedPointer { readonly type: 'userMovedPointer'; /** @@ -72,4 +88,7 @@ export type CameraAction = | UserStartedPanning | UserStoppedPanning | UserZoomed - | UserMovedPointer; + | UserMovedPointer + | UserClickedZoomOut + | UserClickedZoomIn + | UserClickedPanControl; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/panning.test.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/panning.test.ts index c09320182e3be0..17401a63b5ae8f 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/panning.test.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/panning.test.ts @@ -58,4 +58,66 @@ describe('panning interaction', () => { }); }); }); + describe('panning controls', () => { + describe('when user clicks on pan north button', () => { + beforeEach(() => { + const action: CameraAction = { type: 'userClickedPanControl', payload: 'north' }; + store.dispatch(action); + }); + it('moves the camera south so that objects appear closer to the bottom of the screen', () => { + const actual = translation(store.getState()); + expect(actual).toMatchInlineSnapshot(` + Array [ + 0, + -32.49906769231164, + ] + `); + }); + }); + describe('when user clicks on pan south button', () => { + beforeEach(() => { + const action: CameraAction = { type: 'userClickedPanControl', payload: 'south' }; + store.dispatch(action); + }); + it('moves the camera north so that objects appear closer to the top of the screen', () => { + const actual = translation(store.getState()); + expect(actual).toMatchInlineSnapshot(` + Array [ + 0, + 32.49906769231164, + ] + `); + }); + }); + describe('when user clicks on pan east button', () => { + beforeEach(() => { + const action: CameraAction = { type: 'userClickedPanControl', payload: 'east' }; + store.dispatch(action); + }); + it('moves the camera west so that objects appear closer to the left of the screen', () => { + const actual = translation(store.getState()); + expect(actual).toMatchInlineSnapshot(` + Array [ + -32.49906769231164, + 0, + ] + `); + }); + }); + describe('when user clicks on pan west button', () => { + beforeEach(() => { + const action: CameraAction = { type: 'userClickedPanControl', payload: 'west' }; + store.dispatch(action); + }); + it('moves the camera east so that objects appear closer to the right of the screen', () => { + const actual = translation(store.getState()); + expect(actual).toMatchInlineSnapshot(` + Array [ + 32.49906769231164, + 0, + ] + `); + }); + }); + }); }); diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/reducer.ts index b7229240684f15..7c4678a4f1dc13 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/reducer.ts @@ -9,7 +9,7 @@ import { applyMatrix3, subtract } from '../../lib/vector2'; import { userIsPanning, translation, projectionMatrix, inverseProjectionMatrix } from './selectors'; import { clamp } from '../../lib/math'; -import { CameraState, ResolverAction } from '../../types'; +import { CameraState, ResolverAction, Vector2 } from '../../types'; import { scaleToZoom } from './scale_to_zoom'; function initialState(): CameraState { @@ -34,6 +34,16 @@ export const cameraReducer: Reducer = ( ...state, scalingFactor: clamp(action.payload, 0, 1), }; + } else if (action.type === 'userClickedZoomIn') { + return { + ...state, + scalingFactor: clamp(state.scalingFactor + 0.1, 0, 1), + }; + } else if (action.type === 'userClickedZoomOut') { + return { + ...state, + scalingFactor: clamp(state.scalingFactor - 0.1, 0, 1), + }; } else if (action.type === 'userZoomed') { const stateWithNewScaling: CameraState = { ...state, @@ -100,6 +110,32 @@ export const cameraReducer: Reducer = ( } else { return state; } + } else if (action.type === 'userClickedPanControl') { + const panDirection = action.payload; + /** + * Delta amount will be in the range of 20 -> 40 depending on the scalingFactor + */ + const deltaAmount = (1 + state.scalingFactor) * 20; + let delta: Vector2; + if (panDirection === 'north') { + delta = [0, -deltaAmount]; + } else if (panDirection === 'south') { + delta = [0, deltaAmount]; + } else if (panDirection === 'east') { + delta = [-deltaAmount, 0]; + } else if (panDirection === 'west') { + delta = [deltaAmount, 0]; + } else { + delta = [0, 0]; + } + + return { + ...state, + translationNotCountingCurrentPanning: [ + state.translationNotCountingCurrentPanning[0] + delta[0], + state.translationNotCountingCurrentPanning[1] + delta[1], + ], + }; } else if (action.type === 'userSetRasterSize') { /** * Handle resizes of the Resolver component. We need to know the size in order to convert between screen diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/selectors.ts index a7b0bbf66052d0..53ffe6dd073fa6 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/selectors.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/selectors.ts @@ -182,6 +182,13 @@ export const scale = (state: CameraState): Vector2 => { return [value, value]; }; +/** + * Scales the coordinate system, used for zooming. Should always be between 0 and 1 + */ +export const scalingFactor = (state: CameraState): CameraState['scalingFactor'] => { + return state.scalingFactor; +}; + /** * Whether or not the user is current panning the map. */ diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/zooming.test.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/zooming.test.ts index 4b0915282e86f2..abc113d5999ffe 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/zooming.test.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/camera/zooming.test.ts @@ -8,7 +8,7 @@ import { CameraAction } from './action'; import { cameraReducer } from './reducer'; import { createStore, Store } from 'redux'; import { CameraState, AABB } from '../../types'; -import { viewableBoundingBox, inverseProjectionMatrix } from './selectors'; +import { viewableBoundingBox, inverseProjectionMatrix, scalingFactor } from './selectors'; import { expectVectorsToBeClose } from './test_helpers'; import { scaleToZoom } from './scale_to_zoom'; import { applyMatrix3 } from '../../lib/vector2'; @@ -151,4 +151,29 @@ describe('zooming', () => { }); }); }); + describe('zoom controls', () => { + let previousScalingFactor: CameraState['scalingFactor']; + describe('when user clicks on zoom in button', () => { + beforeEach(() => { + previousScalingFactor = scalingFactor(store.getState()); + const action: CameraAction = { type: 'userClickedZoomIn' }; + store.dispatch(action); + }); + it('the scaling factor should increase by 0.1 units', () => { + const actual = scalingFactor(store.getState()); + expect(actual).toEqual(previousScalingFactor + 0.1); + }); + }); + describe('when user clicks on zoom out button', () => { + beforeEach(() => { + previousScalingFactor = scalingFactor(store.getState()); + const action: CameraAction = { type: 'userClickedZoomOut' }; + store.dispatch(action); + }); + it('the scaling factor should decrease by 0.1 units', () => { + const actual = scalingFactor(store.getState()); + expect(actual).toEqual(previousScalingFactor - 0.1); + }); + }); + }); }); diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts index 30adf172030969..eb1c1fec369957 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts @@ -31,6 +31,11 @@ export const inverseProjectionMatrix = composeSelectors( */ export const scale = composeSelectors(cameraStateSelector, cameraSelectors.scale); +/** + * Scales the coordinate system, used for zooming. Should always be between 0 and 1 + */ +export const scalingFactor = composeSelectors(cameraStateSelector, cameraSelectors.scalingFactor); + /** * Whether or not the user is current panning the map. */ diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts index eae9ebf9ee9a63..f2ae9785446f7a 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts @@ -182,3 +182,8 @@ export type ProcessWithWidthMetadata = { firstChildWidth: null; } ); + +/** + * String that represents the direction in which Resolver can be panned + */ +export type PanDirection = 'north' | 'south' | 'east' | 'west'; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/graph_controls.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/graph_controls.tsx new file mode 100644 index 00000000000000..3170f8bdf867ea --- /dev/null +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/graph_controls.tsx @@ -0,0 +1,148 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback } from 'react'; +import styled from 'styled-components'; +import { EuiRange, EuiPanel, EuiIcon } from '@elastic/eui'; +import { useSelector, useDispatch } from 'react-redux'; +import { ResolverAction, PanDirection } from '../types'; +import * as selectors from '../store/selectors'; + +/** + * Controls for zooming, panning, and centering in Resolver + */ +export const GraphControls = styled( + React.memo( + ({ + className, + }: { + /** + * A className string provided by `styled` + */ + className?: string; + }) => { + const dispatch: (action: ResolverAction) => unknown = useDispatch(); + const scalingFactor = useSelector(selectors.scalingFactor); + + const handleZoomAmountChange = useCallback( + (event: React.ChangeEvent | React.MouseEvent) => { + const valueAsNumber = parseFloat( + (event as React.ChangeEvent).target.value + ); + if (isNaN(valueAsNumber) === false) { + dispatch({ + type: 'userSetZoomLevel', + payload: valueAsNumber, + }); + } + }, + [dispatch] + ); + + const handleCenterClick = useCallback(() => { + dispatch({ + type: 'userSetPositionOfCamera', + payload: [0, 0], + }); + }, [dispatch]); + + const handleZoomOutClick = useCallback(() => { + dispatch({ + type: 'userClickedZoomOut', + }); + }, [dispatch]); + + const handleZoomInClick = useCallback(() => { + dispatch({ + type: 'userClickedZoomIn', + }); + }, [dispatch]); + + const handlePanClick = (panDirection: PanDirection) => { + return () => { + dispatch({ + type: 'userClickedPanControl', + payload: panDirection, + }); + }; + }; + + return ( +

    + +
    + +
    +
    + + + +
    +
    + +
    +
    + + + + + +
    + ); + } + ) +)` + position: absolute; + top: 5px; + left: 5px; + z-index: 1; + background-color: #d4d4d4; + color: #333333; + + .zoom-controls { + display: flex; + flex-direction: column; + align-items: center; + padding: 5px 0px; + + .zoom-slider { + width: 20px; + height: 150px; + margin: 5px 0px 2px 0px; + + input[type='range'] { + width: 150px; + height: 20px; + transform-origin: 75px 75px; + transform: rotate(-90deg); + } + } + } + .panning-controls { + text-align: center; + } +`; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx index d252988d0cdcc0..a69504e3a5db12 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx @@ -14,6 +14,7 @@ import { useAutoUpdatingClientRect } from './use_autoupdating_client_rect'; import { useNonPassiveWheelHandler } from './use_nonpassive_wheel_handler'; import { ProcessEventDot } from './process_event_dot'; import { EdgeLine } from './edge_line'; +import { GraphControls } from './graph_controls'; export const AppRoot = React.memo(({ store }: { store: Store }) => { return ( @@ -138,18 +139,16 @@ const Resolver = styled( useNonPassiveWheelHandler(handleWheel, ref); return ( -
    - {Array.from(processNodePositions).map(([processEvent, position], index) => ( - - ))} - {edgeLineSegments.map(([startPosition, endPosition], index) => ( - - ))} +
    + +
    + {Array.from(processNodePositions).map(([processEvent, position], index) => ( + + ))} + {edgeLineSegments.map(([startPosition, endPosition], index) => ( + + ))} +
    ); }) @@ -167,4 +166,9 @@ const Resolver = styled( * Prevent partially visible components from showing up outside the bounds of Resolver. */ overflow: hidden; + + .resolver-graph { + display: flex; + flex-grow: 1; + } `; diff --git a/x-pack/plugins/endpoint/server/plugin.ts b/x-pack/plugins/endpoint/server/plugin.ts index 7ed116ba211407..b1ae2adbdbb357 100644 --- a/x-pack/plugins/endpoint/server/plugin.ts +++ b/x-pack/plugins/endpoint/server/plugin.ts @@ -8,8 +8,8 @@ import { first } from 'rxjs/operators'; import { addRoutes } from './routes'; import { PluginSetupContract as FeaturesPluginSetupContract } from '../../features/server'; import { createConfig$, EndpointConfigType } from './config'; -import { EndpointAppContext } from './types'; import { registerEndpointRoutes } from './routes/endpoints'; +import { EndpointAppContext } from './types'; export type EndpointPluginStart = void; export type EndpointPluginSetup = void; diff --git a/x-pack/plugins/endpoint/server/routes/endpoints.test.ts b/x-pack/plugins/endpoint/server/routes/endpoints.test.ts index 60433f86b6f7ed..04a38972401ed9 100644 --- a/x-pack/plugins/endpoint/server/routes/endpoints.test.ts +++ b/x-pack/plugins/endpoint/server/routes/endpoints.test.ts @@ -18,9 +18,9 @@ import { httpServiceMock, loggingServiceMock, } from '../../../../../src/core/server/mocks'; -import { EndpointData } from '../types'; +import { EndpointMetadata, EndpointResultList } from '../../common/types'; import { SearchResponse } from 'elasticsearch'; -import { EndpointResultList, registerEndpointRoutes } from './endpoints'; +import { registerEndpointRoutes } from './endpoints'; import { EndpointConfigSchema } from '../config'; import * as data from '../test_data/all_endpoints_data.json'; @@ -49,8 +49,8 @@ describe('test endpoint route', () => { it('test find the latest of all endpoints', async () => { const mockRequest = httpServerMock.createKibanaRequest({}); - const response: SearchResponse = (data as unknown) as SearchResponse< - EndpointData + const response: SearchResponse = (data as unknown) as SearchResponse< + EndpointMetadata >; mockScopedClient.callAsCurrentUser.mockImplementationOnce(() => Promise.resolve(response)); [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => @@ -73,9 +73,9 @@ describe('test endpoint route', () => { expect(routeConfig.options).toEqual({ authRequired: true }); expect(mockResponse.ok).toBeCalled(); const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as EndpointResultList; - expect(endpointResultList.endpoints.length).toEqual(3); - expect(endpointResultList.total).toEqual(3); - expect(endpointResultList.request_index).toEqual(0); + expect(endpointResultList.endpoints.length).toEqual(2); + expect(endpointResultList.total).toEqual(2); + expect(endpointResultList.request_page_index).toEqual(0); expect(endpointResultList.request_page_size).toEqual(10); }); @@ -93,7 +93,7 @@ describe('test endpoint route', () => { }, }); mockScopedClient.callAsCurrentUser.mockImplementationOnce(() => - Promise.resolve((data as unknown) as SearchResponse) + Promise.resolve((data as unknown) as SearchResponse) ); [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => path.startsWith('/api/endpoint/endpoints') @@ -115,9 +115,9 @@ describe('test endpoint route', () => { expect(routeConfig.options).toEqual({ authRequired: true }); expect(mockResponse.ok).toBeCalled(); const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as EndpointResultList; - expect(endpointResultList.endpoints.length).toEqual(3); - expect(endpointResultList.total).toEqual(3); - expect(endpointResultList.request_index).toEqual(10); + expect(endpointResultList.endpoints.length).toEqual(2); + expect(endpointResultList.total).toEqual(2); + expect(endpointResultList.request_page_index).toEqual(10); expect(endpointResultList.request_page_size).toEqual(10); }); }); diff --git a/x-pack/plugins/endpoint/server/routes/endpoints.ts b/x-pack/plugins/endpoint/server/routes/endpoints.ts index 9d2babc61f11f9..4fc3e653f94265 100644 --- a/x-pack/plugins/endpoint/server/routes/endpoints.ts +++ b/x-pack/plugins/endpoint/server/routes/endpoints.ts @@ -7,22 +7,13 @@ import { IRouter } from 'kibana/server'; import { SearchResponse } from 'elasticsearch'; import { schema } from '@kbn/config-schema'; -import { EndpointAppContext, EndpointData } from '../types'; + import { kibanaRequestToEndpointListQuery } from '../services/endpoint/endpoint_query_builders'; +import { EndpointMetadata, EndpointResultList } from '../../common/types'; +import { EndpointAppContext } from '../types'; interface HitSource { - _source: EndpointData; -} - -export interface EndpointResultList { - // the endpoint restricted by the page size - endpoints: EndpointData[]; - // the total number of unique endpoints in the index - total: number; - // the page size requested - request_page_size: number; - // the index requested - request_index: number; + _source: EndpointMetadata; } export function registerEndpointRoutes(router: IRouter, endpointAppContext: EndpointAppContext) { @@ -53,7 +44,7 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp const response = (await context.core.elasticsearch.dataClient.callAsCurrentUser( 'search', queryParams - )) as SearchResponse; + )) as SearchResponse; return res.ok({ body: mapToEndpointResultList(queryParams, response) }); } catch (err) { return res.internalError({ body: err }); @@ -64,13 +55,13 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp function mapToEndpointResultList( queryParams: Record, - searchResponse: SearchResponse + searchResponse: SearchResponse ): EndpointResultList { const totalNumberOfEndpoints = searchResponse?.aggregations?.total?.value || 0; if (searchResponse.hits.hits.length > 0) { return { request_page_size: queryParams.size, - request_index: queryParams.from, + request_page_index: queryParams.from, endpoints: searchResponse.hits.hits .map(response => response.inner_hits.most_recent.hits.hits) .flatMap(data => data as HitSource) @@ -80,7 +71,7 @@ function mapToEndpointResultList( } else { return { request_page_size: queryParams.size, - request_index: queryParams.from, + request_page_index: queryParams.from, total: totalNumberOfEndpoints, endpoints: [], }; diff --git a/x-pack/plugins/endpoint/server/services/endpoint/endpoint_query_builders.test.ts b/x-pack/plugins/endpoint/server/services/endpoint/endpoint_query_builders.test.ts index 2a8cecec16526b..3c931a251d6977 100644 --- a/x-pack/plugins/endpoint/server/services/endpoint/endpoint_query_builders.test.ts +++ b/x-pack/plugins/endpoint/server/services/endpoint/endpoint_query_builders.test.ts @@ -23,23 +23,23 @@ describe('test query builder', () => { match_all: {}, }, collapse: { - field: 'machine_id', + field: 'host.id.keyword', inner_hits: { name: 'most_recent', size: 1, - sort: [{ created_at: 'desc' }], + sort: [{ 'event.created': 'desc' }], }, }, aggs: { total: { cardinality: { - field: 'machine_id', + field: 'host.id.keyword', }, }, }, sort: [ { - created_at: { + 'event.created': { order: 'desc', }, }, diff --git a/x-pack/plugins/endpoint/server/services/endpoint/endpoint_query_builders.ts b/x-pack/plugins/endpoint/server/services/endpoint/endpoint_query_builders.ts index 7430ba97216083..102c268cf9ec4c 100644 --- a/x-pack/plugins/endpoint/server/services/endpoint/endpoint_query_builders.ts +++ b/x-pack/plugins/endpoint/server/services/endpoint/endpoint_query_builders.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { KibanaRequest } from 'kibana/server'; -import { EndpointAppConstants, EndpointAppContext } from '../../types'; +import { EndpointAppConstants } from '../../../common/types'; +import { EndpointAppContext } from '../../types'; export const kibanaRequestToEndpointListQuery = async ( request: KibanaRequest, @@ -17,23 +18,23 @@ export const kibanaRequestToEndpointListQuery = async ( match_all: {}, }, collapse: { - field: 'machine_id', + field: 'host.id.keyword', inner_hits: { name: 'most_recent', size: 1, - sort: [{ created_at: 'desc' }], + sort: [{ 'event.created': 'desc' }], }, }, aggs: { total: { cardinality: { - field: 'machine_id', + field: 'host.id.keyword', }, }, }, sort: [ { - created_at: { + 'event.created': { order: 'desc', }, }, diff --git a/x-pack/plugins/endpoint/server/test_data/all_endpoints_data.json b/x-pack/plugins/endpoint/server/test_data/all_endpoints_data.json index d505b2c929828c..f1ad5190c55ff8 100644 --- a/x-pack/plugins/endpoint/server/test_data/all_endpoints_data.json +++ b/x-pack/plugins/endpoint/server/test_data/all_endpoints_data.json @@ -1,228 +1,100 @@ { - "took": 3, - "timed_out": false, - "_shards": { - "total": 1, - "successful": 1, - "skipped": 0, - "failed": 0 + "took" : 343, + "timed_out" : false, + "_shards" : { + "total" : 1, + "successful" : 1, + "skipped" : 0, + "failed" : 0 }, - "hits": { - "total": { - "value": 9, - "relation": "eq" + "hits" : { + "total" : { + "value" : 4, + "relation" : "eq" }, - "max_score": null, - "hits": [ + "max_score" : null, + "hits" : [ { - "_index": "endpoint-agent", - "_id": "UV_6SG8B9c_DH2QsbOZd", - "_score": null, - "_source": { - "machine_id": "606267a9-2e51-42b4-956e-6cc7812e3447", - "created_at": "2019-12-27T20:09:28.377Z", - "host": { - "name": "natalee-2", - "hostname": "natalee-2.example.com", - "ip": "10.5.220.127", - "mac_address": "17-5f-c9-f8-ca-d6", - "os": { - "name": "windows 6.3", - "full": "Windows Server 2012R2" - } + "_index" : "endpoint-agent", + "_id" : "WqVo1G8BYQH1gtPUgYkC", + "_score" : null, + "_source" : { + "@timestamp" : 1579816615336, + "event" : { + "created" : "2020-01-23T21:56:55.336Z" }, - "endpoint": { - "domain": "example.com", - "is_base_image": false, - "active_directory_distinguished_name": "CN=natalee-2,DC=example,DC=com", - "active_directory_hostname": "natalee-2.example.com", - "upgrade": { - "status": null, - "updated_at": null - }, - "isolation": { - "status": false, - "request_status": null, - "updated_at": null - }, - "policy": { - "name": "With Eventing", - "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" - }, - "sensor": { - "persistence": true, - "status": {} - } - } - }, - "fields": { - "machine_id": [ - "606267a9-2e51-42b4-956e-6cc7812e3447" - ] - }, - "sort": [ - 1577477368377 - ], - "inner_hits": { - "most_recent": { - "hits": { - "total": { - "value": 3, - "relation": "eq" - }, - "max_score": null, - "hits": [ - { - "_index": "endpoint-agent", - "_id": "UV_6SG8B9c_DH2QsbOZd", - "_score": null, - "_source": { - "machine_id": "606267a9-2e51-42b4-956e-6cc7812e3447", - "created_at": "2019-12-27T20:09:28.377Z", - "host": { - "name": "natalee-2", - "hostname": "natalee-2.example.com", - "ip": "10.5.220.127", - "mac_address": "17-5f-c9-f8-ca-d6", - "os": { - "name": "windows 6.3", - "full": "Windows Server 2012R2" - } - }, - "endpoint": { - "domain": "example.com", - "is_base_image": false, - "active_directory_distinguished_name": "CN=natalee-2,DC=example,DC=com", - "active_directory_hostname": "natalee-2.example.com", - "upgrade": { - "status": null, - "updated_at": null - }, - "isolation": { - "status": false, - "request_status": null, - "updated_at": null - }, - "policy": { - "name": "With Eventing", - "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" - }, - "sensor": { - "persistence": true, - "status": {} - } - } - }, - "sort": [ - 1577477368377 - ] - } - ] - } - } - } - }, - { - "_index": "endpoint-agent", - "_id": "Ul_6SG8B9c_DH2QsbOZd", - "_score": null, - "_source": { - "machine_id": "8ec625e1-a80c-4c9f-bdfd-496060aa6310", - "created_at": "2019-12-27T20:09:28.377Z", - "host": { - "name": "luttrell-2", - "hostname": "luttrell-2.example.com", - "ip": "10.246.84.193", - "mac_address": "dc-d-88-14-c3-c6", - "os": { - "name": "windows 6.3", - "full": "Windows Server 2012R2" + "endpoint" : { + "policy" : { + "id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" } }, - "endpoint": { - "domain": "example.com", - "is_base_image": false, - "active_directory_distinguished_name": "CN=luttrell-2,DC=example,DC=com", - "active_directory_hostname": "luttrell-2.example.com", - "upgrade": { - "status": null, - "updated_at": null - }, - "isolation": { - "status": false, - "request_status": null, - "updated_at": null - }, - "policy": { - "name": "Default", - "id": "00000000-0000-0000-0000-000000000000" - }, - "sensor": { - "persistence": true, - "status": {} + "agent" : { + "version" : "6.8.3", + "id" : "56a75650-3c8a-4e4f-ac17-6dd729c650e2" + }, + "host" : { + "id" : "7141a48b-e19f-4ae3-89a0-6e7179a84265", + "hostname" : "larimer-0.example.com", + "ip" : "10.21.48.136", + "mac" : "77-be-30-f0-e8-d6", + "architecture" : "x86_64", + "os" : { + "name" : "windows 6.2", + "full" : "Windows Server 2012", + "version" : "6.2" } } }, - "fields": { - "machine_id": [ - "8ec625e1-a80c-4c9f-bdfd-496060aa6310" + "fields" : { + "host.id.keyword" : [ + "7141a48b-e19f-4ae3-89a0-6e7179a84265" ] }, - "sort": [ - 1577477368377 + "sort" : [ + 1579816615336 ], - "inner_hits": { - "most_recent": { - "hits": { - "total": { - "value": 3, - "relation": "eq" + "inner_hits" : { + "most_recent" : { + "hits" : { + "total" : { + "value" : 2, + "relation" : "eq" }, - "max_score": null, - "hits": [ + "max_score" : null, + "hits" : [ { - "_index": "endpoint-agent", - "_id": "Ul_6SG8B9c_DH2QsbOZd", - "_score": null, - "_source": { - "machine_id": "8ec625e1-a80c-4c9f-bdfd-496060aa6310", - "created_at": "2019-12-27T20:09:28.377Z", - "host": { - "name": "luttrell-2", - "hostname": "luttrell-2.example.com", - "ip": "10.246.84.193", - "mac_address": "dc-d-88-14-c3-c6", - "os": { - "name": "windows 6.3", - "full": "Windows Server 2012R2" + "_index" : "endpoint-agent", + "_id" : "WqVo1G8BYQH1gtPUgYkC", + "_score" : null, + "_source" : { + "@timestamp" : 1579816615336, + "event" : { + "created" : "2020-01-23T21:56:55.336Z" + }, + "endpoint" : { + "policy" : { + "id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" } }, - "endpoint": { - "domain": "example.com", - "is_base_image": false, - "active_directory_distinguished_name": "CN=luttrell-2,DC=example,DC=com", - "active_directory_hostname": "luttrell-2.example.com", - "upgrade": { - "status": null, - "updated_at": null - }, - "isolation": { - "status": false, - "request_status": null, - "updated_at": null - }, - "policy": { - "name": "Default", - "id": "00000000-0000-0000-0000-000000000000" - }, - "sensor": { - "persistence": true, - "status": {} + "agent" : { + "version" : "6.8.3", + "id" : "56a75650-3c8a-4e4f-ac17-6dd729c650e2" + }, + "host" : { + "id" : "7141a48b-e19f-4ae3-89a0-6e7179a84265", + "hostname" : "larimer-0.example.com", + "ip" : "10.21.48.136", + "mac" : "77-be-30-f0-e8-d6", + "architecture" : "x86_64", + "os" : { + "name" : "windows 6.2", + "full" : "Windows Server 2012", + "version" : "6.2" } } }, - "sort": [ - 1577477368377 + "sort" : [ + 1579816615336 ] } ] @@ -231,106 +103,86 @@ } }, { - "_index": "endpoint-agent", - "_id": "U1_6SG8B9c_DH2QsbOZd", - "_score": null, - "_source": { - "machine_id": "853a308c-6e6d-4b92-a32b-2f623b6c8cf4", - "created_at": "2019-12-27T20:09:28.377Z", - "host": { - "name": "akeylah-7", - "hostname": "akeylah-7.example.com", - "ip": "10.252.242.44", - "mac_address": "27-b9-51-21-31-a", - "os": { - "name": "windows 6.3", - "full": "Windows Server 2012R2" + "_index" : "endpoint-agent", + "_id" : "W6Vo1G8BYQH1gtPUgYkC", + "_score" : null, + "_source" : { + "@timestamp" : 1579816615336, + "event" : { + "created" : "2020-01-23T21:56:55.336Z" + }, + "endpoint" : { + "policy" : { + "id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" } }, - "endpoint": { - "domain": "example.com", - "is_base_image": false, - "active_directory_distinguished_name": "CN=akeylah-7,DC=example,DC=com", - "active_directory_hostname": "akeylah-7.example.com", - "upgrade": { - "status": null, - "updated_at": null - }, - "isolation": { - "status": false, - "request_status": null, - "updated_at": null - }, - "policy": { - "name": "With Eventing", - "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" - }, - "sensor": { - "persistence": true, - "status": {} + "agent" : { + "version" : "6.4.3", + "id" : "c2d84d8f-d355-40de-8b54-5d318d4d1312" + }, + "host" : { + "id" : "f35ec6c1-6562-45b1-818f-2f14c0854adf", + "hostname" : "hildebrandt-6.example.com", + "ip" : "10.53.92.84", + "mac" : "af-f1-8f-51-25-2a", + "architecture" : "x86_64", + "os" : { + "name" : "windows 10.0", + "full" : "Windows 10", + "version" : "10.0" } } }, - "fields": { - "machine_id": [ - "853a308c-6e6d-4b92-a32b-2f623b6c8cf4" + "fields" : { + "host.id.keyword" : [ + "f35ec6c1-6562-45b1-818f-2f14c0854adf" ] }, - "sort": [ - 1577477368377 + "sort" : [ + 1579816615336 ], - "inner_hits": { - "most_recent": { - "hits": { - "total": { - "value": 3, - "relation": "eq" + "inner_hits" : { + "most_recent" : { + "hits" : { + "total" : { + "value" : 2, + "relation" : "eq" }, - "max_score": null, - "hits": [ + "max_score" : null, + "hits" : [ { - "_index": "endpoint-agent", - "_id": "U1_6SG8B9c_DH2QsbOZd", - "_score": null, - "_source": { - "machine_id": "853a308c-6e6d-4b92-a32b-2f623b6c8cf4", - "created_at": "2019-12-27T20:09:28.377Z", - "host": { - "name": "akeylah-7", - "hostname": "akeylah-7.example.com", - "ip": "10.252.242.44", - "mac_address": "27-b9-51-21-31-a", - "os": { - "name": "windows 6.3", - "full": "Windows Server 2012R2" + "_index" : "endpoint-agent", + "_id" : "W6Vo1G8BYQH1gtPUgYkC", + "_score" : null, + "_source" : { + "@timestamp" : 1579816615336, + "event" : { + "created" : "2020-01-23T21:56:55.336Z" + }, + "endpoint" : { + "policy" : { + "id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" } }, - "endpoint": { - "domain": "example.com", - "is_base_image": false, - "active_directory_distinguished_name": "CN=akeylah-7,DC=example,DC=com", - "active_directory_hostname": "akeylah-7.example.com", - "upgrade": { - "status": null, - "updated_at": null - }, - "isolation": { - "status": false, - "request_status": null, - "updated_at": null - }, - "policy": { - "name": "With Eventing", - "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" - }, - "sensor": { - "persistence": true, - "status": {} + "agent" : { + "version" : "6.4.3", + "id" : "c2d84d8f-d355-40de-8b54-5d318d4d1312" + }, + "host" : { + "id" : "f35ec6c1-6562-45b1-818f-2f14c0854adf", + "hostname" : "hildebrandt-6.example.com", + "ip" : "10.53.92.84", + "mac" : "af-f1-8f-51-25-2a", + "architecture" : "x86_64", + "os" : { + "name" : "windows 10.0", + "full" : "Windows 10", + "version" : "10.0" } } }, - "sort": [ - 1577477368377 + "sort" : [ + 1579816615336 ] } ] @@ -340,9 +192,9 @@ } ] }, - "aggregations": { - "total": { - "value": 3 + "aggregations" : { + "total" : { + "value" : 2 } } } diff --git a/x-pack/plugins/endpoint/server/types.ts b/x-pack/plugins/endpoint/server/types.ts index c6d0e3dea70cf7..f06cc10f16709d 100644 --- a/x-pack/plugins/endpoint/server/types.ts +++ b/x-pack/plugins/endpoint/server/types.ts @@ -10,45 +10,3 @@ export interface EndpointAppContext { logFactory: LoggerFactory; config(): Promise; } - -export class EndpointAppConstants { - static ENDPOINT_INDEX_NAME = 'endpoint-agent*'; -} - -export interface EndpointData { - machine_id: string; - created_at: Date; - host: { - name: string; - hostname: string; - ip: string; - mac_address: string; - os: { - name: string; - full: string; - }; - }; - endpoint: { - domain: string; - is_base_image: boolean; - active_directory_distinguished_name: string; - active_directory_hostname: string; - upgrade: { - status?: string; - updated_at?: Date; - }; - isolation: { - status: boolean; - request_status?: string | boolean; - updated_at?: Date; - }; - policy: { - name: string; - id: string; - }; - sensor: { - persistence: boolean; - status: object; - }; - }; -} diff --git a/x-pack/plugins/endpoint/yarn.lock b/x-pack/plugins/endpoint/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/x-pack/plugins/endpoint/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/x-pack/plugins/event_log/README.md b/x-pack/plugins/event_log/README.md new file mode 100644 index 00000000000000..d2d67ffc27d947 --- /dev/null +++ b/x-pack/plugins/event_log/README.md @@ -0,0 +1,299 @@ +# Event Log + +## Overview + +The purpose of this plugin is to provide a way to persist a history of events +occuring in Kibana, initially just for the Make It Action project - alerts +and actions. + + +## Basic Usage - Logging Events + +Follow these steps to use `event_log` in your plugin: + +1. Declare `event_log` as a dependency in `kibana.json`: + +```json +{ + ... + "requiredPlugins": ["event_log"], + ... +} +``` + +2. Register provider / actions, and create your plugin's logger, using service +API provided in the `setup` stage: + +```typescript +... +import { IEventLogger, IEventLogService } from '../../event_log/server'; +interface PluginSetupDependencies { + event_log: IEventLogService; +} +... +public setup(core: CoreSetup, { event_log }: PluginSetupDependencies) { + ... + event_log.registerProviderActions('my-plugin', ['action-1, action-2']); + const eventLogger: IEventLogger = event_log.getLogger({ event: { provider: 'my-plugin' } }); + ... +} +... +``` + +4. To log an event, call `logEvent()` on the `eventLogger` object you created: + +```typescript +... + eventLogger.logEvent({ event: { action: 'action-1' }, tags: ['fe', 'fi', 'fo'] }); +... +``` + + +## Testing + +### Unit tests + +From `kibana-root-folder/x-pack`, run: +```bash +$ node node scripts/jest plugins/event_log +``` + +### API Integration tests + +None yet! + + +## Background + +For the Make It Action alerting / action plugins, we will need a way to +persist data regarding alerts and actions, for UI and investigative purposes. +We're referring to this persisted data as "events", and will be persisted to +a new elasticsearch index referred to as the "event log". + +Example events are actions firing, alerts running their scheduled functions, +alerts scheduling actions to run, etc. + +This functionality will be provided in a new NP plugin `event_log`, and will +provide server-side plugin APIs to write to the event log, and run limited +queries against it. For now, access via HTTP will not be available, due to +security concerns and lack of use cases. + +The current clients for the event log are the actions and alerting plugins, +however the event log currently has nothing specific to them, and is general +purpose, so can be used by any plugin to "log events". + +We currently assume that there may be many events logged, and that (some) customers +may not be interested in "old" events, and so to keep the event log from +consuming too much disk space, we'll set it up with ILM and some kind of +reasonable default policy that can be customized by the user. This implies +also the use of rollver, setting a write index alias upon rollover, and +that searches for events will be done via an ES index pattern / alias to search +across event log indices with a wildcard. + +The shape of the documents indexed into the event log index is a subset of ECS +properties with a few Kibana extensions. Over time the subset is of ECS and +Kibana extensions will likely grow. + +# Basic example + +When an action is executed, an event should be written to the event log. + +Here's a [`kbn-action` command](https://github.com/pmuellr/kbn-action) to +execute a "server log" action (writes a message to the Kibana log): + +```console +$ kbn-action execute 79b4c37e-ef42-4421-a0b0-b536840f930d '{level:info message:hallo}' +{ + "status": "ok" +} +``` + +Here's the event written to the event log index: + +```json +{ + "_index": ".kibana-event-log-000001", + "_type": "_doc", + "_id": "d2CXT20BPOpswQ8vgXp5", + "_score": 1, + "_source": { + "event": { + "provider": "actions", + "action": "execute", + "start": "2019-12-09T21:16:43.424Z", + "end": "2019-12-09T21:16:43.425Z", + "duration": 1000000 + }, + "kibana": { + "namespace": "default", + "saved_objects": [ + { + "type": "action", + "id": "79b4c37e-ef42-4421-a0b0-b536840f930d" + } + ] + }, + "message": "action executed successfully: 79b4c37e-ef42-4421-a0b0-b536840f930d - .server-log - server-log", + "@timestamp": "2019-12-09T21:16:43.425Z", + "ecs": { + "version": "1.3.1" + } + } +} +``` + +The shape of the document written to the index is a subset of [ECS][] with an +extended field of `kibana` with some Kibana-related properties contained within +it. + +The ES mappings for the ECS data, and the config-schema for the ECS data, are +generated by a script, and available here: + +- [`generated/mappings.json`](generated/mappings.json) +- [`generated/schemas.ts`](generated/schemas.ts) + +It's anticipated that these interfaces will grow over time, hopefully adding +more ECS fields but adding Kibana extensions as required. + +Since there are some security concerns with the data, we are currently +restricting access via known saved object ids. That is, you can only query +history records associated with specific saved object ids. + +[ECS]: https://www.elastic.co/guide/en/ecs/current/index.html + + +## API + +```typescript +// IEvent is a TS type generated from the subset of ECS supported + +// the NP plugin returns a service instance from setup() and start() +export interface IEventLogService { + registerProviderActions(provider: string, actions: string[]): void; + isProviderActionRegistered(provider: string, action: string): boolean; + getProviderActions(): Map>; + + getLogger(properties: IEvent): IEventLogger; +} + +export interface IEventLogger { + logEvent(properties: IEvent): void; + startTiming(event: IEvent): void; + stopTiming(event: IEvent): void; +} +``` + +The plugin exposes an `IEventLogService` object to plugins that pre-req it. +Those plugins need to call `registerProviderActions()` to indicate the values +of the `event.provider` and `event.action` values they will be using +when logging events. + +The pre-registration helps in two ways: + +- dealing with misspelled values +- preventing index explosion on those fields + +Once the values are registered, the plugin will get an `IEventLogger` instance +by passing in a set of default properties to be used for all it's logging, +to the `getLogger()` method. For instance, the `actions` plugin creates a +logger with `event.provider` set to `actions`, and provides `event.action` +values when writing actual entries. + +The `IEventLogger` object can be cached at the plugin level and accessed by +any code in the plugin. It has a single method to write an event log entry, +`logEvent()`, which is passed specific properties for the event. + +The final data written is a combination of the data passed to `getLogger()` when +creating the logger, and the data passed on the `logEvent()` call, and then +that result is validated to ensure it's complete and valid. Errors will be +logged to the server log. + +The `logEvent()` method returns no values, and is itself not asynchronous. +It's a "call and forget" kind of thing. The method itself will arrange +to have the ultimate document written to the index asynchronously. It's designed +this way because it's not clear what a client would do with a result from this +method, nor what it would do if the method threw an error. All the error +processing involved with getting the data into the index is handled internally, +and logged to the server log as appropriate. + +The `startTiming()` and `stopTiming()` methods can be used to set the timing +properties `start`, `end`, and `duration` in the event. For example: + +```typescript + const loggedEvent: IEvent = { event: { action: 'foo' } }; + + // sets event.start + eventLogger.startTiming(loggedEvent); + + longRunningFunction(); + + // sets event.end and event.duration + eventLogger.stopTiming(loggedEvent); + + eventLogger.logEvent(loggedEvent); + +``` + +It's anticipated that more "helper" methods like this will be provided in the +future. + + +## Stored data + +The elasticsearch index for the event log will have ILM and rollover support, +as customers may decide to only keep recent event documents, wanting indices +with older event documents deleted, turned cold, frozen, etc. We'll supply +some default values, but customers will be able to tweak these. + +The index template, mappings, config-schema types, etc for the index can +be found in the [generated directory](generated). These files are generated +from a script which takes as input the ECS properties to use, and the Kibana +extensions. + +See [ilm rollover action docs][] for more info on the `is_write_index`, and `index.lifecycle.*` properties. + +[ilm rollover action docs]: https://www.elastic.co/guide/en/elasticsearch/reference/current/_actions.html#ilm-rollover-action + +Of particular note in the `mappings`: + +- all "objects" are `dynamic: 'strict'` implies users can't add new fields +- all the `properties` are indexed + +We may change some of that before releasing. + + +## ILM setup + +We'll want to provide default ILM policy, this seems like a reasonable first +attempt: + +``` +PUT _ilm/policy/event_log_policy +{ + "policy": { + "phases": { + "hot": { + "actions": { + "rollover": { + "max_size": "5GB", + "max_age": "30d" + } + } + } + } + } +} +``` + +This means that ILM would "rollover" the current index, say +`.kibana-event-log-000001` by creating a new index `.kibana-event-log-000002`, +which would "inherit" everything from the index template, and then ILM will +set the write index of the the alias to the new index. This would happen +when the original index grew past 5 GB, or was created more than 30 days ago. + +For more relevant information on ILM, see: +[getting started with ILM doc][] and [write index alias behavior][]: + +[getting started with ILM doc]: https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-index-lifecycle-management.html +[write index alias behavior]: https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-rollover-index.html#indices-rollover-is-write-index + diff --git a/x-pack/plugins/event_log/generated/README.md b/x-pack/plugins/event_log/generated/README.md new file mode 100644 index 00000000000000..0361cb12882ab7 --- /dev/null +++ b/x-pack/plugins/event_log/generated/README.md @@ -0,0 +1,4 @@ +The files in this directory were generated by manually running the script +../scripts/create-schemas.js from the root directory of the repository. + +These files should not be edited by hand. diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json new file mode 100644 index 00000000000000..fc1fdb71b0c372 --- /dev/null +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -0,0 +1,96 @@ +{ + "dynamic": "strict", + "properties": { + "@timestamp": { + "type": "date" + }, + "tags": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "norms": false, + "type": "text" + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "dynamic": "strict" + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + } + }, + "dynamic": "strict" + }, + "error": { + "properties": { + "message": { + "norms": false, + "type": "text" + } + }, + "dynamic": "strict" + }, + "user": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "dynamic": "strict" + }, + "kibana": { + "properties": { + "server_uuid": { + "type": "keyword", + "ignore_above": 1024 + }, + "namespace": { + "type": "keyword", + "ignore_above": 1024 + }, + "saved_objects": { + "properties": { + "store": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + }, + "type": "nested", + "dynamic": "strict" + } + }, + "dynamic": "strict" + } + } +} \ No newline at end of file diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts new file mode 100644 index 00000000000000..a040ede891bfdc --- /dev/null +++ b/x-pack/plugins/event_log/generated/schemas.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// ---------------------------------- WARNING ---------------------------------- +// this file was generated, and should not be edited by hand +// ---------------------------------- WARNING ---------------------------------- + +// provides TypeScript and config-schema interfaces for ECS for use with +// the event log + +import { schema, TypeOf } from '@kbn/config-schema'; + +type DeepWriteable = { -readonly [P in keyof T]: DeepWriteable }; +type DeepPartial = { + [P in keyof T]?: T[P] extends Array ? Array> : DeepPartial; +}; + +export const ECS_VERSION = '1.3.1'; + +// types and config-schema describing the es structures +export type IValidatedEvent = TypeOf; +export type IEvent = DeepPartial>; + +export const EventSchema = schema.maybe( + schema.object({ + '@timestamp': ecsDate(), + tags: ecsStringMulti(), + message: ecsString(), + ecs: schema.maybe( + schema.object({ + version: ecsString(), + }) + ), + event: schema.maybe( + schema.object({ + action: ecsString(), + provider: ecsString(), + start: ecsDate(), + duration: ecsNumber(), + end: ecsDate(), + }) + ), + error: schema.maybe( + schema.object({ + message: ecsString(), + }) + ), + user: schema.maybe( + schema.object({ + name: ecsString(), + }) + ), + kibana: schema.maybe( + schema.object({ + server_uuid: ecsString(), + namespace: ecsString(), + saved_objects: schema.maybe( + schema.arrayOf( + schema.object({ + store: ecsString(), + id: ecsString(), + type: ecsString(), + }) + ) + ), + }) + ), + }) +); + +function ecsStringMulti() { + return schema.maybe(schema.arrayOf(schema.string())); +} + +function ecsString() { + return schema.maybe(schema.string()); +} + +function ecsNumber() { + return schema.maybe(schema.number()); +} + +function ecsDate() { + return schema.maybe(schema.string({ validate: validateDate })); +} + +const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/; + +function validateDate(isoDate: string) { + if (ISO_DATE_PATTERN.test(isoDate)) return; + return 'string is not a valid ISO date: ' + isoDate; +} diff --git a/x-pack/plugins/event_log/kibana.json b/x-pack/plugins/event_log/kibana.json new file mode 100644 index 00000000000000..52b68deeffce51 --- /dev/null +++ b/x-pack/plugins/event_log/kibana.json @@ -0,0 +1,8 @@ +{ + "id": "event_log", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["xpack", "event_log"], + "server": true, + "ui": false +} diff --git a/x-pack/plugins/event_log/scripts/create_schemas.js b/x-pack/plugins/event_log/scripts/create_schemas.js new file mode 100755 index 00000000000000..6e9ab00d04d1fc --- /dev/null +++ b/x-pack/plugins/event_log/scripts/create_schemas.js @@ -0,0 +1,322 @@ +#!/usr/bin/env node + +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +const fs = require('fs'); +const path = require('path'); +const lodash = require('lodash'); + +const LineWriter = require('./lib/line_writer'); +const mappings = require('./mappings'); + +const PLUGIN_DIR = path.resolve(path.join(__dirname, '..')); +const ECS_MAPPINGS_FILE = 'generated/elasticsearch/7/template.json'; +const EVENT_LOG_MAPPINGS_FILE = 'generated/mappings.json'; +const EVENT_LOG_CONFIG_SCHEMA_FILE = 'generated/schemas.ts'; + +function main() { + const ecsDir = getEcsDir(); + const ecsVersion = getEcsVersion(ecsDir); + + const ecsMappings = readEcsJSONFile(ecsDir, ECS_MAPPINGS_FILE); + + // add our custom fields + ecsMappings.mappings.properties.kibana = mappings.EcsKibanaExtensionsMappings; + + const exportedProperties = mappings.EcsEventLogProperties; + const multiValuedProperties = new Set(mappings.EcsEventLogMultiValuedProperties); + + const elMappings = getEventLogMappings(ecsMappings, exportedProperties); + + console.log(`generating files in ${PLUGIN_DIR}`); + writeEventLogMappings(elMappings); + writeEventLogConfigSchema(elMappings, ecsVersion, multiValuedProperties); +} + +// return a stripped down version of the ecs schema, with only exportedProperties +function getEventLogMappings(ecsSchema, exportedProperties) { + const result = { mappings: { properties: {} } }; + + // get full list of properties to copy + const leafProperties = exportedProperties.map(replaceDotWithProperties); + + // copy the leaf values of the properties + for (const prop of leafProperties) { + const value = lodash.get(ecsSchema.mappings.properties, prop); + lodash.set(result.mappings.properties, prop, value); + } + + // set the non-leaf values as appropriate + const nonLeafProperties = getNonLeafProperties(exportedProperties).map(replaceDotWithProperties); + for (const prop of nonLeafProperties) { + const ecsValue = lodash.get(ecsSchema.mappings.properties, prop); + const elValue = lodash.get(result.mappings.properties, prop); + + elValue.type = ecsValue.type; + elValue.dynamic = 'strict'; + } + + return result; +} + +// eg, 'ecs.version' -> 'ecs.properties.version' +function replaceDotWithProperties(s) { + return s.replace(/\./g, '.properties.'); +} + +// given an array of property names, return array of object/nested ones +function getNonLeafProperties(propertyNames) { + const result = new Set(); + + for (const propertyName of propertyNames) { + const parts = propertyName.split(/\./g); + if (parts.length <= 1) continue; + parts.pop(); + result.add(parts.join('.')); + } + + return Array.from(result); +} + +function writeEventLogMappings(elSchema) { + // fixObjectTypes(elSchema.mappings); + + const mappings = { + dynamic: 'strict', + properties: elSchema.mappings.properties, + }; + + writeGeneratedFile(EVENT_LOG_MAPPINGS_FILE, JSON.stringify(mappings, null, 4)); + console.log('generated:', EVENT_LOG_MAPPINGS_FILE); +} + +function writeEventLogConfigSchema(elSchema, ecsVersion, multiValuedProperties) { + const lineWriter = LineWriter.createLineWriter(); + + const elSchemaMappings = augmentMappings(elSchema.mappings, multiValuedProperties); + generateSchemaLines(lineWriter, null, elSchemaMappings); + // last line will have an extraneous comma + const schemaLines = lineWriter.getContent().replace(/,$/, ''); + + const contents = getSchemaFileContents(ecsVersion, schemaLines); + const schemaCode = `${contents}\n`; + + writeGeneratedFile(EVENT_LOG_CONFIG_SCHEMA_FILE, schemaCode); + console.log('generated:', EVENT_LOG_CONFIG_SCHEMA_FILE); +} + +const StringTypes = new Set(['string', 'keyword', 'text', 'ip']); +const NumberTypes = new Set(['long', 'integer', 'float']); + +function augmentMappings(mappings, multiValuedProperties) { + // clone the mappings, as we're adding some additional properties + mappings = JSON.parse(JSON.stringify(mappings)); + + for (const prop of multiValuedProperties) { + const fullProp = replaceDotWithProperties(prop); + lodash.set(mappings.properties, `${fullProp}.multiValued`, true); + } + + return mappings; +} + +function generateSchemaLines(lineWriter, prop, mappings) { + const propKey = legalPropertyName(prop); + + if (StringTypes.has(mappings.type)) { + if (mappings.multiValued) { + lineWriter.addLine(`${propKey}: ecsStringMulti(),`); + } else { + lineWriter.addLine(`${propKey}: ecsString(),`); + } + return; + } + + if (NumberTypes.has(mappings.type)) { + lineWriter.addLine(`${propKey}: ecsNumber(),`); + return; + } + + if (mappings.type === 'date') { + lineWriter.addLine(`${propKey}: ecsDate(),`); + return; + } + + // only handling objects for the rest of this function + if (mappings.properties == null) { + logError(`unknown properties to map: ${prop}: ${JSON.stringify(mappings)}`); + } + + // top-level object does not have a property name + if (prop == null) { + lineWriter.addLine(`schema.maybe(`); + lineWriter.indent(); + lineWriter.addLine(`schema.object({`); + } else { + lineWriter.addLine(`${propKey}: schema.maybe(`); + lineWriter.indent(); + if (mappings.type === 'nested') { + lineWriter.addLine(`schema.arrayOf(`); + lineWriter.indent(); + } + lineWriter.addLine(`schema.object({`); + } + + // write the object properties + lineWriter.indent(); + for (const prop of Object.keys(mappings.properties)) { + generateSchemaLines(lineWriter, prop, mappings.properties[prop]); + } + lineWriter.dedent(); + + lineWriter.addLine('})'); + if (mappings.type === 'nested') { + lineWriter.dedent(); + lineWriter.addLine(')'); + } + + lineWriter.dedent(); + lineWriter.addLine('),'); +} + +function legalPropertyName(prop) { + if (prop === '@timestamp') return `'@timestamp'`; + return prop; +} + +function readEcsJSONFile(ecsDir, fileName) { + const contents = readEcsFile(ecsDir, fileName); + + let object; + try { + object = JSON.parse(contents); + } catch (err) { + logError(`ecs file is not JSON: ${fileName}: ${err.message}`); + } + + return object; +} + +function writeGeneratedFile(fileName, contents) { + const genFileName = path.join(PLUGIN_DIR, fileName); + try { + fs.writeFileSync(genFileName, contents); + } catch (err) { + logError(`error writing file: ${genFileName}: ${err.message}`); + } +} + +function readEcsFile(ecsDir, fileName) { + const ecsFile = path.resolve(path.join(ecsDir, fileName)); + + let contents; + try { + contents = fs.readFileSync(ecsFile, { encoding: 'utf8' }); + } catch (err) { + logError(`ecs file not found: ${ecsFile}: ${err.message}`); + } + + return contents; +} + +function getEcsVersion(ecsDir) { + const contents = readEcsFile(ecsDir, 'version').trim(); + if (!contents.match(/^\d+\.\d+\.\d+$/)) { + logError(`ecs is not at a stable version: : ${contents}`); + } + + return contents; +} + +function getEcsDir() { + const ecsDir = path.resolve(path.join(__dirname, '../../../../../ecs')); + + let stats; + let error; + try { + stats = fs.statSync(ecsDir); + } catch (err) { + error = err; + } + + if (error || !stats.isDirectory()) { + logError( + `directory not found: ${ecsDir} - did you checkout elastic/ecs as a peer of this repo?` + ); + } + + return ecsDir; +} + +function logError(message) { + console.log(`error: ${message}`); + process.exit(1); +} + +const SchemaFileTemplate = ` +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// ---------------------------------- WARNING ---------------------------------- +// this file was generated, and should not be edited by hand +// ---------------------------------- WARNING ---------------------------------- + +// provides TypeScript and config-schema interfaces for ECS for use with +// the event log + +import { schema, TypeOf } from '@kbn/config-schema'; + +type DeepWriteable = { -readonly [P in keyof T]: DeepWriteable }; +type DeepPartial = { + [P in keyof T]?: T[P] extends Array ? Array> : DeepPartial; +}; + +export const ECS_VERSION = '%%ECS_VERSION%%'; + +// types and config-schema describing the es structures +export type IValidatedEvent = TypeOf; +export type IEvent = DeepPartial>; + +export const EventSchema = %%SCHEMA%%; + +function ecsStringMulti() { + return schema.maybe(schema.arrayOf(schema.string())); +} + +function ecsString() { + return schema.maybe(schema.string()); +} + +function ecsNumber() { + return schema.maybe(schema.number()); +} + +function ecsDate() { + return schema.maybe(schema.string({ validate: validateDate })); +} + +const ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/; + +function validateDate(isoDate: string) { + if (ISO_DATE_PATTERN.test(isoDate)) return; + return 'string is not a valid ISO date: ' + isoDate; +} +`.trim(); + +function getSchemaFileContents(ecsVersion, schemaLines) { + return SchemaFileTemplate.replace('%%ECS_VERSION%%', ecsVersion).replace( + '%%SCHEMA%%', + schemaLines + ); + // .replace('%%INTERFACE%%', interfaceLines); +} + +// run as a command-line script +if (require.main === module) main(); diff --git a/x-pack/plugins/event_log/scripts/lib/line_writer.js b/x-pack/plugins/event_log/scripts/lib/line_writer.js new file mode 100644 index 00000000000000..0da39022021196 --- /dev/null +++ b/x-pack/plugins/event_log/scripts/lib/line_writer.js @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +const INDENT_LENGTH = 2; +const INDENT = ''.padStart(INDENT_LENGTH); + +module.exports = { + createLineWriter, +}; + +class LineWriter { + constructor() { + this._indent = ''; + this._lines = []; + } + + addLine(line) { + this._lines.push(`${this._indent}${line}`); + } + + indent() { + this._indent = `${this._indent}${INDENT}`; + } + + dedent() { + this._indent = this._indent.substr(INDENT_LENGTH); + } + + getContent() { + return this._lines.join('\n'); + } +} + +function createLineWriter() { + return new LineWriter(); +} diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js new file mode 100644 index 00000000000000..43fd0c78183a10 --- /dev/null +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +exports.EcsKibanaExtensionsMappings = { + properties: { + // kibana server uuid + server_uuid: { + type: 'keyword', + ignore_above: 1024, + }, + // relevant kibana space + namespace: { + type: 'keyword', + ignore_above: 1024, + }, + // array of saved object references, for "linking" via search + saved_objects: { + type: 'nested', + properties: { + // 'kibana' for typical saved object, 'task_manager' for TM, etc + store: { + type: 'keyword', + ignore_above: 1024, + }, + id: { + type: 'keyword', + ignore_above: 1024, + }, + type: { + type: 'keyword', + ignore_above: 1024, + }, + }, + }, + }, +}; + +// ECS and Kibana ECS extension properties to generate +exports.EcsEventLogProperties = [ + '@timestamp', + 'tags', + 'message', + 'ecs.version', + 'event.action', + 'event.provider', + 'event.start', + 'event.duration', + 'event.end', + 'error.message', + 'user.name', + 'kibana.server_uuid', + 'kibana.namespace', + 'kibana.saved_objects.store', + 'kibana.saved_objects.id', + 'kibana.saved_objects.name', + 'kibana.saved_objects.type', +]; + +// properties that can have multiple values (array vs single value) +exports.EcsEventLogMultiValuedProperties = ['tags']; diff --git a/x-pack/plugins/event_log/server/es/context.mock.ts b/x-pack/plugins/event_log/server/es/context.mock.ts new file mode 100644 index 00000000000000..fb894ce6e77875 --- /dev/null +++ b/x-pack/plugins/event_log/server/es/context.mock.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Logger, ClusterClient } from '../../../../../src/core/server'; +import { EsContext } from './context'; + +import { EsNames } from './names'; + +export type EsClusterClient = Pick; + +export interface EsError { + readonly statusCode: number; + readonly message: string; +} + +interface CreateMockEsContextParams { + logger: Logger; + esNames: EsNames; +} + +export function createMockEsContext(params: CreateMockEsContextParams): EsContext { + return new EsContextMock(params); +} + +class EsContextMock implements EsContext { + public logger: Logger; + public esNames: EsNames; + + constructor(params: CreateMockEsContextParams) { + this.logger = params.logger; + this.esNames = params.esNames; + } + + initialize() {} + + async waitTillReady(): Promise { + return true; + } + + async callEs(operation: string, body?: any): Promise { + return {}; + } +} diff --git a/x-pack/plugins/event_log/server/es/context.ts b/x-pack/plugins/event_log/server/es/context.ts new file mode 100644 index 00000000000000..b93c1892d02064 --- /dev/null +++ b/x-pack/plugins/event_log/server/es/context.ts @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Logger, ClusterClient } from 'src/core/server'; + +import { EsNames, getEsNames } from './names'; +import { initializeEs } from './init'; +import { createReadySignal, ReadySignal } from '../lib/ready_signal'; + +export type EsClusterClient = Pick; + +export interface EsContext { + logger: Logger; + esNames: EsNames; + initialize(): void; + waitTillReady(): Promise; + callEs(operation: string, body?: any): Promise; +} + +export interface EsError { + readonly statusCode: number; + readonly message: string; +} + +export function createEsContext(params: EsContextCtorParams): EsContext { + return new EsContextImpl(params); +} + +export interface EsContextCtorParams { + logger: Logger; + clusterClient: EsClusterClient; + indexNameRoot: string; +} + +class EsContextImpl implements EsContext { + public readonly logger: Logger; + public readonly esNames: EsNames; + private readonly clusterClient: EsClusterClient; + private readonly readySignal: ReadySignal; + private initialized: boolean; + + constructor(params: EsContextCtorParams) { + this.logger = params.logger; + this.esNames = getEsNames(params.indexNameRoot); + this.clusterClient = params.clusterClient; + this.readySignal = createReadySignal(); + this.initialized = false; + } + + initialize() { + // only run the initialization method once + if (this.initialized) return; + this.initialized = true; + + this.logger.debug('initializing EsContext'); + + setImmediate(async () => { + try { + await this._initialize(); + this.logger.debug('readySignal.signal(true)'); + this.readySignal.signal(true); + } catch (err) { + this.logger.debug('readySignal.signal(false)'); + this.readySignal.signal(false); + } + }); + } + + async waitTillReady(): Promise { + return await this.readySignal.wait(); + } + + async callEs(operation: string, body?: any): Promise { + try { + this.debug(`callEs(${operation}) calls:`, body); + const result = await this.clusterClient.callAsInternalUser(operation, body); + this.debug(`callEs(${operation}) result:`, result); + return result; + } catch (err) { + this.debug(`callEs(${operation}) error:`, { + message: err.message, + statusCode: err.statusCode, + }); + throw err; + } + } + + private async _initialize() { + await initializeEs(this); + } + + private debug(message: string, object?: any) { + const objectString = object == null ? '' : JSON.stringify(object); + this.logger.debug(`esContext: ${message} ${objectString}`); + } +} diff --git a/x-pack/plugins/event_log/server/es/documents.test.ts b/x-pack/plugins/event_log/server/es/documents.test.ts new file mode 100644 index 00000000000000..2dec23c61de2f8 --- /dev/null +++ b/x-pack/plugins/event_log/server/es/documents.test.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getIndexTemplate, getIlmPolicy } from './documents'; +import { getEsNames } from './names'; + +describe('getIlmPolicy()', () => { + test('returns the basic structure of an ilm policy', () => { + expect(getIlmPolicy()).toMatchObject({ + policy: { + phases: {}, + }, + }); + }); +}); + +describe('getIndexTemplate()', () => { + const esNames = getEsNames('XYZ'); + + test('returns the correct details of the index template', () => { + const indexTemplate = getIndexTemplate(esNames, true); + expect(indexTemplate.index_patterns).toEqual([esNames.indexPattern]); + expect(indexTemplate.aliases[esNames.alias]).toEqual({}); + expect(indexTemplate.settings.number_of_shards).toBeGreaterThanOrEqual(0); + expect(indexTemplate.settings.number_of_replicas).toBeGreaterThanOrEqual(0); + expect(indexTemplate.mappings).toMatchObject({}); + }); + + test('returns correct index template bits for ilm when ilm is supported', () => { + const indexTemplate = getIndexTemplate(esNames, true); + expect(indexTemplate.settings['index.lifecycle.name']).toBe(esNames.ilmPolicy); + expect(indexTemplate.settings['index.lifecycle.rollover_alias']).toBe(esNames.alias); + }); + + test('returns correct index template bits for ilm when ilm is not supported', () => { + const indexTemplate = getIndexTemplate(esNames, false); + expect(indexTemplate.settings['index.lifecycle.name']).toBeUndefined(); + expect(indexTemplate.settings['index.lifecycle.rollover_alias']).toBeUndefined(); + }); +}); diff --git a/x-pack/plugins/event_log/server/es/documents.ts b/x-pack/plugins/event_log/server/es/documents.ts new file mode 100644 index 00000000000000..dfc544f8a41cbf --- /dev/null +++ b/x-pack/plugins/event_log/server/es/documents.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EsNames } from './names'; +import mappings from '../../generated/mappings.json'; + +// returns the body of an index template used in an ES indices.putTemplate call +export function getIndexTemplate(esNames: EsNames, ilmExists: boolean) { + const indexTemplateBody: any = { + index_patterns: [esNames.indexPattern], + aliases: { + [esNames.alias]: {}, + }, + settings: { + number_of_shards: 1, + number_of_replicas: 1, + 'index.lifecycle.name': esNames.ilmPolicy, + 'index.lifecycle.rollover_alias': esNames.alias, + }, + mappings, + }; + + if (!ilmExists) { + delete indexTemplateBody.settings['index.lifecycle.name']; + delete indexTemplateBody.settings['index.lifecycle.rollover_alias']; + } + + return indexTemplateBody; +} + +// returns the body of an ilm policy used in an ES PUT _ilm/policy call +export function getIlmPolicy() { + return { + policy: { + phases: { + hot: { + actions: { + rollover: { + max_size: '5GB', + max_age: '30d', + // max_docs: 1, // you know, for testing + }, + }, + }, + }, + }, + }; +} diff --git a/x-pack/plugins/event_log/server/es/index.ts b/x-pack/plugins/event_log/server/es/index.ts new file mode 100644 index 00000000000000..ad1409e33589fd --- /dev/null +++ b/x-pack/plugins/event_log/server/es/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { EsClusterClient, EsContext, createEsContext } from './context'; diff --git a/x-pack/plugins/event_log/server/es/init.ts b/x-pack/plugins/event_log/server/es/init.ts new file mode 100644 index 00000000000000..d87f5bce034757 --- /dev/null +++ b/x-pack/plugins/event_log/server/es/init.ts @@ -0,0 +1,137 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getIlmPolicy, getIndexTemplate } from './documents'; +import { EsContext } from './context'; + +export async function initializeEs(esContext: EsContext): Promise { + esContext.logger.debug('initializing elasticsearch resources starting'); + + try { + await initializeEsResources(esContext); + } catch (err) { + esContext.logger.error(`error initializing elasticsearch resources: ${err.message}`); + return false; + } + + esContext.logger.debug('initializing elasticsearch resources complete'); + return true; +} + +async function initializeEsResources(esContext: EsContext) { + const steps = new EsInitializationSteps(esContext); + let ilmExists: boolean; + + // create the ilm policy, if required + ilmExists = await steps.doesIlmPolicyExist(); + if (!ilmExists) { + ilmExists = await steps.createIlmPolicy(); + } + + if (!(await steps.doesIndexTemplateExist())) { + await steps.createIndexTemplate({ ilmExists }); + } + + if (!(await steps.doesInitialIndexExist())) { + await steps.createInitialIndex(); + } +} + +interface AddTemplateOpts { + ilmExists: boolean; +} + +class EsInitializationSteps { + constructor(private readonly esContext: EsContext) { + this.esContext = esContext; + } + + async doesIlmPolicyExist(): Promise { + const request = { + method: 'GET', + path: `_ilm/policy/${this.esContext.esNames.ilmPolicy}`, + }; + try { + await this.esContext.callEs('transport.request', request); + } catch (err) { + if (err.statusCode === 404) return false; + // TODO: remove following once kibana user can access ilm + if (err.statusCode === 403) return false; + + throw new Error(`error checking existance of ilm policy: ${err.message}`); + } + return true; + } + + async createIlmPolicy(): Promise { + const request = { + method: 'PUT', + path: `_ilm/policy/${this.esContext.esNames.ilmPolicy}`, + body: getIlmPolicy(), + }; + try { + await this.esContext.callEs('transport.request', request); + } catch (err) { + // TODO: remove following once kibana user can access ilm + if (err.statusCode === 403) return false; + throw new Error(`error creating ilm policy: ${err.message}`); + } + return true; + } + + async doesIndexTemplateExist(): Promise { + const name = this.esContext.esNames.indexTemplate; + let result; + try { + result = await this.esContext.callEs('indices.existsTemplate', { name }); + } catch (err) { + throw new Error(`error checking existance of index template: ${err.message}`); + } + return result as boolean; + } + + async createIndexTemplate(opts: AddTemplateOpts): Promise { + const templateBody = getIndexTemplate(this.esContext.esNames, opts.ilmExists); + const addTemplateParams = { + create: true, + name: this.esContext.esNames.indexTemplate, + body: templateBody, + }; + try { + await this.esContext.callEs('indices.putTemplate', addTemplateParams); + } catch (err) { + throw new Error(`error creating index template: ${err.message}`); + } + } + + async doesInitialIndexExist(): Promise { + const name = this.esContext.esNames.alias; + let result; + try { + result = await this.esContext.callEs('indices.existsAlias', { name }); + } catch (err) { + throw new Error(`error checking existance of initial index: ${err.message}`); + } + return result as boolean; + } + + async createInitialIndex(): Promise { + const index = this.esContext.esNames.initialIndex; + try { + await this.esContext.callEs('indices.create', { index }); + } catch (err) { + throw new Error(`error creating initial index: ${err.message}`); + } + } + + debug(message: string) { + this.esContext.logger.debug(message); + } + + warn(message: string) { + this.esContext.logger.warn(message); + } +} diff --git a/x-pack/plugins/event_log/server/es/names.test.ts b/x-pack/plugins/event_log/server/es/names.test.ts new file mode 100644 index 00000000000000..d88c4212df91ca --- /dev/null +++ b/x-pack/plugins/event_log/server/es/names.test.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getEsNames } from './names'; + +describe('getEsNames()', () => { + test('works as expected', () => { + const base = 'XYZ'; + const esNames = getEsNames(base); + expect(esNames.base).toEqual(base); + expect(esNames.alias).toEqual(`${base}-event-log`); + expect(esNames.ilmPolicy).toEqual(`${base}-event-log-policy`); + expect(esNames.indexPattern).toEqual(`${base}-event-log-*`); + expect(esNames.initialIndex).toEqual(`${base}-event-log-000001`); + expect(esNames.indexTemplate).toEqual(`${base}-event-log-template`); + }); +}); diff --git a/x-pack/plugins/event_log/server/es/names.ts b/x-pack/plugins/event_log/server/es/names.ts new file mode 100644 index 00000000000000..be737d23625f14 --- /dev/null +++ b/x-pack/plugins/event_log/server/es/names.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +const EVENT_LOG_NAME_SUFFIX = '-event-log'; + +export interface EsNames { + base: string; + alias: string; + ilmPolicy: string; + indexPattern: string; + initialIndex: string; + indexTemplate: string; +} + +export function getEsNames(baseName: string): EsNames { + const eventLogName = `${baseName}${EVENT_LOG_NAME_SUFFIX}`; + return { + base: baseName, + alias: eventLogName, + ilmPolicy: `${eventLogName}-policy`, + indexPattern: `${eventLogName}-*`, + initialIndex: `${eventLogName}-000001`, + indexTemplate: `${eventLogName}-template`, + }; +} diff --git a/x-pack/plugins/event_log/server/event_log_service.test.ts b/x-pack/plugins/event_log/server/event_log_service.test.ts new file mode 100644 index 00000000000000..5ab019e533dae1 --- /dev/null +++ b/x-pack/plugins/event_log/server/event_log_service.test.ts @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEventLogConfig } from './types'; +import { EventLogService } from './event_log_service'; +import { getEsNames } from './es/names'; +import { createMockEsContext } from './es/context.mock'; +import { loggingServiceMock } from '../../../../src/core/server/logging/logging_service.mock'; + +const loggingService = loggingServiceMock.create(); +const systemLogger = loggingService.get(); + +describe('EventLogService', () => { + const esContext = createMockEsContext({ + esNames: getEsNames('ABC'), + logger: systemLogger, + }); + + function getService(config: IEventLogConfig) { + const { enabled, logEntries, indexEntries } = config; + return new EventLogService({ + esContext, + systemLogger, + config: { + enabled, + logEntries, + indexEntries, + }, + }); + } + + test('returns config values from service methods', () => { + let service; + + service = getService({ enabled: true, logEntries: true, indexEntries: true }); + expect(service.isEnabled()).toEqual(true); + expect(service.isLoggingEntries()).toEqual(true); + expect(service.isIndexingEntries()).toEqual(true); + + service = getService({ enabled: true, logEntries: false, indexEntries: true }); + expect(service.isEnabled()).toEqual(true); + expect(service.isLoggingEntries()).toEqual(false); + expect(service.isIndexingEntries()).toEqual(true); + + service = getService({ enabled: true, logEntries: true, indexEntries: false }); + expect(service.isEnabled()).toEqual(true); + expect(service.isLoggingEntries()).toEqual(true); + expect(service.isIndexingEntries()).toEqual(false); + + service = getService({ enabled: true, logEntries: false, indexEntries: false }); + expect(service.isEnabled()).toEqual(true); + expect(service.isLoggingEntries()).toEqual(false); + expect(service.isIndexingEntries()).toEqual(false); + + // this is the only non-obvious one; when enabled is false, + // logging/indexing will be false as well. + service = getService({ enabled: false, logEntries: true, indexEntries: true }); + expect(service.isEnabled()).toEqual(false); + expect(service.isLoggingEntries()).toEqual(false); + expect(service.isIndexingEntries()).toEqual(false); + }); + + test('handles registering provider actions correctly', () => { + const params = { + esContext, + systemLogger, + config: { + enabled: true, + logEntries: true, + indexEntries: true, + }, + }; + + const service = new EventLogService(params); + let providerActions: ReturnType; + providerActions = service.getProviderActions(); + expect(providerActions.size).toEqual(0); + + service.registerProviderActions('foo', ['foo-1', 'foo-2']); + providerActions = service.getProviderActions(); + expect(providerActions.size).toEqual(1); + expect(providerActions.get('foo')).toEqual(new Set(['foo-1', 'foo-2'])); + + expect(() => { + service.registerProviderActions('invalid', []); + }).toThrow('actions parameter must not be empty for provider: "invalid"'); + + expect(() => { + service.registerProviderActions('foo', ['abc']); + }).toThrow('provider already registered: "foo"'); + expect(providerActions.get('foo')!.size).toEqual(2); + + expect(service.isProviderActionRegistered('foo', 'foo-1')).toEqual(true); + expect(service.isProviderActionRegistered('foo', 'foo-2')).toEqual(true); + expect(service.isProviderActionRegistered('foo', 'foo-3')).toEqual(false); + expect(service.isProviderActionRegistered('invalid', 'foo')).toEqual(false); + }); + + test('returns a non-null logger from getLogger()', () => { + const params = { + esContext, + systemLogger, + config: { + enabled: true, + logEntries: true, + indexEntries: true, + }, + }; + const service = new EventLogService(params); + const eventLogger = service.getLogger({}); + expect(eventLogger).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/event_log/server/event_log_service.ts b/x-pack/plugins/event_log/server/event_log_service.ts new file mode 100644 index 00000000000000..2746d86b8b2cb9 --- /dev/null +++ b/x-pack/plugins/event_log/server/event_log_service.ts @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { Observable } from 'rxjs'; +import { ClusterClient } from 'src/core/server'; + +import { Plugin } from './plugin'; +import { EsContext } from './es'; +import { IEvent, IEventLogger, IEventLogService, IEventLogConfig } from './types'; +import { EventLogger } from './event_logger'; +export type PluginClusterClient = Pick; +export type AdminClusterClient$ = Observable; + +type SystemLogger = Plugin['systemLogger']; + +interface EventLogServiceCtorParams { + config: IEventLogConfig; + esContext: EsContext; + systemLogger: SystemLogger; +} + +// note that clusterClient may be null, indicating we can't write to ES +export class EventLogService implements IEventLogService { + private config: IEventLogConfig; + private systemLogger: SystemLogger; + private esContext: EsContext; + private registeredProviderActions: Map>; + + constructor({ config, systemLogger, esContext }: EventLogServiceCtorParams) { + this.config = config; + this.esContext = esContext; + this.systemLogger = systemLogger; + this.registeredProviderActions = new Map>(); + } + + public isEnabled(): boolean { + return this.config.enabled; + } + + public isLoggingEntries(): boolean { + return this.isEnabled() && this.config.logEntries; + } + + public isIndexingEntries(): boolean { + return this.isEnabled() && this.config.indexEntries; + } + + registerProviderActions(provider: string, actions: string[]): void { + if (actions.length === 0) { + throw new Error(`actions parameter must not be empty for provider: "${provider}"`); + } + + if (this.registeredProviderActions.has(provider)) { + throw new Error(`provider already registered: "${provider}"`); + } + + this.registeredProviderActions.set(provider, new Set(actions)); + } + + isProviderActionRegistered(provider: string, action: string): boolean { + const actions = this.registeredProviderActions.get(provider); + if (actions == null) return false; + + if (actions.has(action)) return true; + + return false; + } + + getProviderActions() { + return new Map(this.registeredProviderActions.entries()); + } + + getLogger(initialProperties: IEvent): IEventLogger { + return new EventLogger({ + esContext: this.esContext, + eventLogService: this, + initialProperties, + systemLogger: this.systemLogger, + }); + } +} diff --git a/x-pack/plugins/event_log/server/event_logger.mock.ts b/x-pack/plugins/event_log/server/event_logger.mock.ts new file mode 100644 index 00000000000000..97c2b9f980dcd1 --- /dev/null +++ b/x-pack/plugins/event_log/server/event_logger.mock.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEvent, IEventLogger } from './types'; + +export function createEventLoggerMock(): IEventLogger { + return { + logEvent(eventProperties: IEvent): void {}, + startTiming(event: IEvent): void {}, + stopTiming(event: IEvent): void {}, + }; +} diff --git a/x-pack/plugins/event_log/server/event_logger.test.ts b/x-pack/plugins/event_log/server/event_logger.test.ts new file mode 100644 index 00000000000000..0b06515c00bf3c --- /dev/null +++ b/x-pack/plugins/event_log/server/event_logger.test.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEvent, IEventLogger } from './index'; +import { EventLogService } from './event_log_service'; +import { getEsNames } from './es/names'; +import { createMockEsContext } from './es/context.mock'; +import { loggingServiceMock } from '../../../../src/core/server/logging/logging_service.mock'; +import { delay } from './lib/delay'; + +const loggingService = loggingServiceMock.create(); +const systemLogger = loggingService.get(); + +describe('EventLogger', () => { + const esContext = createMockEsContext({ esNames: getEsNames('ABC'), logger: systemLogger }); + const config = { enabled: true, logEntries: true, indexEntries: true }; + const service = new EventLogService({ esContext, systemLogger, config }); + let eventLogger: IEventLogger; + + beforeEach(() => { + eventLogger = service.getLogger({}); + }); + + test('logEvent()', () => { + service.registerProviderActions('test-provider', ['test-action-1']); + const initialProperties = { + event: { provider: 'test-provider' }, + }; + eventLogger = service.getLogger(initialProperties); + + // ATM, just make sure it doesn't blow up + eventLogger.logEvent({}); + }); + + test('timing', async () => { + const event: IEvent = {}; + eventLogger.startTiming(event); + + const timeStart = event.event!.start!; + expect(timeStart).toBeTruthy(); + expect(new Date(timeStart)).toBeTruthy(); + + await delay(100); + eventLogger.stopTiming(event); + + const timeStop = event.event!.end!; + expect(timeStop).toBeTruthy(); + expect(new Date(timeStop)).toBeTruthy(); + + const duration = event.event!.duration!; + expect(duration).toBeGreaterThan(90 * 1000 * 1000); + }); + + test('timing - no start', async () => { + const event: IEvent = {}; + eventLogger.stopTiming(event); + + expect(event.event).toBeUndefined(); + }); + + test('timing - bad start', async () => { + const event: IEvent = { + event: { + start: 'not a date that can be parsed', + }, + }; + eventLogger.stopTiming(event); + + expect(event.event!.end).toBeUndefined(); + expect(event.event!.duration).toBeUndefined(); + }); +}); diff --git a/x-pack/plugins/event_log/server/event_logger.ts b/x-pack/plugins/event_log/server/event_logger.ts new file mode 100644 index 00000000000000..50cf83f55730b2 --- /dev/null +++ b/x-pack/plugins/event_log/server/event_logger.ts @@ -0,0 +1,177 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { Logger } from 'src/core/server'; +import { merge } from 'lodash'; + +import { Plugin } from './plugin'; +import { EsContext } from './es'; +import { + IEvent, + IValidatedEvent, + IEventLogger, + IEventLogService, + ECS_VERSION, + EventSchema, +} from './types'; + +type SystemLogger = Plugin['systemLogger']; + +interface Doc { + index: string; + body: IEvent; +} + +interface IEventLoggerCtorParams { + esContext: EsContext; + eventLogService: IEventLogService; + initialProperties: IEvent; + systemLogger: SystemLogger; +} + +export class EventLogger implements IEventLogger { + private esContext: EsContext; + private eventLogService: IEventLogService; + private initialProperties: IEvent; + private systemLogger: SystemLogger; + + constructor(ctorParams: IEventLoggerCtorParams) { + this.esContext = ctorParams.esContext; + this.eventLogService = ctorParams.eventLogService; + this.initialProperties = ctorParams.initialProperties; + this.systemLogger = ctorParams.systemLogger; + } + + startTiming(event: IEvent): void { + if (event == null) return; + event.event = event.event || {}; + + event.event.start = new Date().toISOString(); + } + + stopTiming(event: IEvent): void { + if (event?.event == null) return; + + const start = getEventStart(event); + if (start == null || isNaN(start)) return; + + const end = Date.now(); + event.event.end = new Date(end).toISOString(); + event.event.duration = (end - start) * 1000 * 1000; // nanoseconds + } + + // non-blocking, but spawns an async task to do the work + logEvent(eventProperties: IEvent): void { + if (!this.eventLogService.isEnabled()) return; + + const event: IEvent = {}; + + // merge the initial properties and event properties + merge(event, this.initialProperties, eventProperties); + + // add fixed properties + event['@timestamp'] = new Date().toISOString(); + event.ecs = event.ecs || {}; + event.ecs.version = ECS_VERSION; + + // TODO add kibana server uuid + // event.kibana.server_uuid = NP version of config.get('server.uuid'); + + let validatedEvent: IValidatedEvent; + try { + validatedEvent = validateEvent(this.eventLogService, event); + } catch (err) { + this.systemLogger.warn(`invalid event logged: ${err.message}`); + return; + } + + const doc: Doc = { + index: this.esContext.esNames.alias, + body: validatedEvent, + }; + + if (this.eventLogService.isIndexingEntries()) { + indexEventDoc(this.esContext, doc); + } + + if (this.eventLogService.isLoggingEntries()) { + logEventDoc(this.systemLogger, doc); + } + } +} + +// return the epoch millis of the start date, or null; may be NaN if garbage +function getEventStart(event: IEvent): number | null { + if (event?.event?.start == null) return null; + + return Date.parse(event.event.start); +} + +const RequiredEventSchema = schema.object({ + provider: schema.string({ minLength: 1 }), + action: schema.string({ minLength: 1 }), +}); + +function validateEvent(eventLogService: IEventLogService, event: IEvent): IValidatedEvent { + if (event?.event == null) { + throw new Error(`no "event" property`); + } + + // ensure there are provider/action properties in event as strings + const requiredProps = { + provider: event.event.provider, + action: event.event.action, + }; + + // will throw an error if structure doesn't validate + const { provider, action } = RequiredEventSchema.validate(requiredProps); + + if (!eventLogService.isProviderActionRegistered(provider, action)) { + throw new Error(`unregistered provider/action: "${provider}" / "${action}"`); + } + + // could throw an error + return EventSchema.validate(event); +} + +function logEventDoc(logger: Logger, doc: Doc): void { + setImmediate(() => { + logger.info(`event logged ${JSON.stringify(doc.body)}`); + }); +} + +function indexEventDoc(esContext: EsContext, doc: Doc): void { + // TODO: + // the setImmediate() on an async function is a little overkill, but, + // setImmediate() may be tweakable via node params, whereas async + // tweaking is in the v8 params realm, which is very dicey. + // Long-term, we should probably create an in-memory queue for this, so + // we can explictly see/set the queue lengths. + + // already verified this.clusterClient isn't null above + setImmediate(async () => { + try { + await indexLogEventDoc(esContext, doc); + } catch (err) { + esContext.logger.warn(`error writing event doc: ${err.message}`); + writeLogEventDocOnError(esContext, doc); + } + }); +} + +// whew, the thing that actually writes the event log document! +async function indexLogEventDoc(esContext: EsContext, doc: any) { + esContext.logger.debug(`writing to event log: ${JSON.stringify(doc)}`); + await esContext.waitTillReady(); + await esContext.callEs('index', doc); + esContext.logger.debug(`writing to event log complete`); +} + +// TODO: write log entry to a bounded queue buffer +function writeLogEventDocOnError(esContext: EsContext, doc: any) { + esContext.logger.warn(`unable to write event doc: ${JSON.stringify(doc)}`); +} diff --git a/x-pack/plugins/event_log/server/index.ts b/x-pack/plugins/event_log/server/index.ts new file mode 100644 index 00000000000000..81a56faa49964c --- /dev/null +++ b/x-pack/plugins/event_log/server/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginInitializerContext } from 'src/core/server'; +import { ConfigSchema } from './types'; +import { Plugin } from './plugin'; + +export { IEventLogService, IEventLogger, IEvent } from './types'; +export const config = { schema: ConfigSchema }; +export const plugin = (context: PluginInitializerContext) => new Plugin(context); diff --git a/x-pack/plugins/event_log/server/lib/bounded_queue.test.ts b/x-pack/plugins/event_log/server/lib/bounded_queue.test.ts new file mode 100644 index 00000000000000..c1bb6d70879f3b --- /dev/null +++ b/x-pack/plugins/event_log/server/lib/bounded_queue.test.ts @@ -0,0 +1,161 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createBoundedQueue } from './bounded_queue'; +import { loggingServiceMock } from '../../../../../src/core/server/logging/logging_service.mock'; + +const loggingService = loggingServiceMock.create(); +const logger = loggingService.get(); + +describe('basic', () => { + let discardedHelper: DiscardedHelper; + let onDiscarded: (object: number) => void; + let queue2: ReturnType; + let queue10: ReturnType; + + beforeAll(() => { + discardedHelper = new DiscardedHelper(); + onDiscarded = discardedHelper.onDiscarded.bind(discardedHelper); + }); + + beforeEach(() => { + queue2 = createBoundedQueue({ logger, maxLength: 2, onDiscarded }); + queue10 = createBoundedQueue({ logger, maxLength: 10, onDiscarded }); + }); + + test('queued items: 0', () => { + discardedHelper.reset(); + expect(queue2.isEmpty()).toEqual(true); + expect(queue2.isFull()).toEqual(false); + expect(queue2.isCloseToFull()).toEqual(false); + expect(queue2.length).toEqual(0); + expect(queue2.maxLength).toEqual(2); + expect(queue2.pull(1)).toEqual([]); + expect(queue2.pull(100)).toEqual([]); + expect(discardedHelper.discarded).toEqual([]); + }); + + test('queued items: 1', () => { + discardedHelper.reset(); + queue2.push(1); + expect(queue2.isEmpty()).toEqual(false); + expect(queue2.isFull()).toEqual(false); + expect(queue2.isCloseToFull()).toEqual(false); + expect(queue2.length).toEqual(1); + expect(queue2.maxLength).toEqual(2); + expect(queue2.pull(1)).toEqual([1]); + expect(queue2.pull(1)).toEqual([]); + expect(discardedHelper.discarded).toEqual([]); + }); + + test('queued items: 2', () => { + discardedHelper.reset(); + queue2.push(1); + queue2.push(2); + expect(queue2.isEmpty()).toEqual(false); + expect(queue2.isFull()).toEqual(true); + expect(queue2.isCloseToFull()).toEqual(true); + expect(queue2.length).toEqual(2); + expect(queue2.maxLength).toEqual(2); + expect(queue2.pull(1)).toEqual([1]); + expect(queue2.pull(1)).toEqual([2]); + expect(queue2.pull(1)).toEqual([]); + expect(discardedHelper.discarded).toEqual([]); + }); + + test('queued items: 3', () => { + discardedHelper.reset(); + queue2.push(1); + queue2.push(2); + queue2.push(3); + expect(queue2.isEmpty()).toEqual(false); + expect(queue2.isFull()).toEqual(true); + expect(queue2.isCloseToFull()).toEqual(true); + expect(queue2.length).toEqual(2); + expect(queue2.maxLength).toEqual(2); + expect(queue2.pull(1)).toEqual([2]); + expect(queue2.pull(1)).toEqual([3]); + expect(queue2.pull(1)).toEqual([]); + expect(discardedHelper.discarded).toEqual([1]); + }); + + test('closeToFull()', () => { + discardedHelper.reset(); + + expect(queue10.isCloseToFull()).toEqual(false); + + for (let i = 1; i <= 8; i++) { + queue10.push(i); + expect(queue10.isCloseToFull()).toEqual(false); + } + + queue10.push(9); + expect(queue10.isCloseToFull()).toEqual(true); + + queue10.push(10); + expect(queue10.isCloseToFull()).toEqual(true); + + queue10.pull(2); + expect(queue10.isCloseToFull()).toEqual(false); + + queue10.push(11); + expect(queue10.isCloseToFull()).toEqual(true); + }); + + test('discarded', () => { + discardedHelper.reset(); + queue2.push(1); + queue2.push(2); + queue2.push(3); + expect(discardedHelper.discarded).toEqual([1]); + + discardedHelper.reset(); + queue2.push(4); + queue2.push(5); + expect(discardedHelper.discarded).toEqual([2, 3]); + }); + + test('pull', () => { + discardedHelper.reset(); + + expect(queue10.pull(4)).toEqual([]); + + for (let i = 1; i <= 10; i++) { + queue10.push(i); + } + + expect(queue10.pull(4)).toEqual([1, 2, 3, 4]); + expect(queue10.length).toEqual(6); + expect(queue10.pull(4)).toEqual([5, 6, 7, 8]); + expect(queue10.length).toEqual(2); + expect(queue10.pull(4)).toEqual([9, 10]); + expect(queue10.length).toEqual(0); + expect(queue10.pull(1)).toEqual([]); + expect(queue10.pull(4)).toEqual([]); + }); +}); + +class DiscardedHelper { + private _discarded: T[]; + + constructor() { + this.reset(); + this._discarded = []; + this.onDiscarded = this.onDiscarded.bind(this); + } + + onDiscarded(object: T) { + this._discarded.push(object); + } + + public get discarded(): T[] { + return this._discarded; + } + + reset() { + this._discarded = []; + } +} diff --git a/x-pack/plugins/event_log/server/lib/bounded_queue.ts b/x-pack/plugins/event_log/server/lib/bounded_queue.ts new file mode 100644 index 00000000000000..2c5ebcd38f5a8a --- /dev/null +++ b/x-pack/plugins/event_log/server/lib/bounded_queue.ts @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Plugin } from '../plugin'; + +const CLOSE_TO_FULL_PERCENT = 0.9; + +type SystemLogger = Plugin['systemLogger']; + +export interface IBoundedQueue { + maxLength: number; + length: number; + push(object: T): void; + pull(count: number): T[]; + isEmpty(): boolean; + isFull(): boolean; + isCloseToFull(): boolean; +} + +export interface CreateBoundedQueueParams { + maxLength: number; + onDiscarded(object: T): void; + logger: SystemLogger; +} + +export function createBoundedQueue(params: CreateBoundedQueueParams): IBoundedQueue { + if (params.maxLength <= 0) throw new Error(`invalid bounded queue maxLength ${params.maxLength}`); + + return new BoundedQueue(params); +} + +class BoundedQueue implements IBoundedQueue { + private _maxLength: number; + private _buffer: T[]; + private _onDiscarded: (object: T) => void; + private _logger: SystemLogger; + + constructor(params: CreateBoundedQueueParams) { + this._maxLength = params.maxLength; + this._buffer = []; + this._onDiscarded = params.onDiscarded; + this._logger = params.logger; + } + + public get maxLength(): number { + return this._maxLength; + } + + public get length(): number { + return this._buffer.length; + } + + isEmpty() { + return this._buffer.length === 0; + } + + isFull() { + return this._buffer.length >= this._maxLength; + } + + isCloseToFull() { + return this._buffer.length / this._maxLength >= CLOSE_TO_FULL_PERCENT; + } + + push(object: T) { + this.ensureRoom(); + this._buffer.push(object); + } + + pull(count: number) { + if (count <= 0) throw new Error(`invalid pull count ${count}`); + + return this._buffer.splice(0, count); + } + + private ensureRoom() { + if (this.length < this._maxLength) return; + + const discarded = this.pull(this.length - this._maxLength + 1); + for (const object of discarded) { + try { + this._onDiscarded(object!); + } catch (err) { + this._logger.warn(`error discarding circular buffer entry: ${err.message}`); + } + } + } +} diff --git a/x-pack/plugins/event_log/server/lib/delay.test.ts b/x-pack/plugins/event_log/server/lib/delay.test.ts new file mode 100644 index 00000000000000..22355ebec505de --- /dev/null +++ b/x-pack/plugins/event_log/server/lib/delay.test.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { delay } from './delay'; + +const TEST_DELAY = 100; + +describe('delay', () => { + test('works as expected', async () => { + const timeStart = Date.now(); + await delay(TEST_DELAY); + + // note: testing with .toBeGreaterThanOrEqual(TEST_DELAY) is flaky, + // sometimes the actual value is TEST_DELAY - 1, so ... using that as the + // value to test against; something funky with time rounding I'd guess. + expect(Date.now() - timeStart).toBeGreaterThanOrEqual(TEST_DELAY - 1); + }); +}); diff --git a/x-pack/plugins/event_log/server/lib/delay.ts b/x-pack/plugins/event_log/server/lib/delay.ts new file mode 100644 index 00000000000000..a37569baaf6928 --- /dev/null +++ b/x-pack/plugins/event_log/server/lib/delay.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; + * you may not use this file except in compliance with the Elastic License. + */ + +export async function delay(millis: number) { + await new Promise(resolve => setTimeout(resolve, millis)); +} diff --git a/x-pack/plugins/event_log/server/lib/ready_signal.test.ts b/x-pack/plugins/event_log/server/lib/ready_signal.test.ts new file mode 100644 index 00000000000000..d4dbb9064a1ba5 --- /dev/null +++ b/x-pack/plugins/event_log/server/lib/ready_signal.test.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createReadySignal, ReadySignal } from './ready_signal'; + +describe('ReadySignal', () => { + let readySignal: ReadySignal; + + beforeEach(() => { + readySignal = createReadySignal(); + }); + + test('works as expected', async done => { + let value = 41; + + timeoutSet(100, () => { + expect(value).toBe(41); + }); + + timeoutSet(250, () => readySignal.signal(42)); + + timeoutSet(400, async () => { + expect(value).toBe(42); + + const innerValue = await readySignal.wait(); + expect(innerValue).toBe(42); + done(); + }); + + value = await readySignal.wait(); + expect(value).toBe(42); + }); +}); + +function timeoutSet(ms: number, fn: any) { + setTimeout(fn, ms); +} diff --git a/x-pack/plugins/event_log/server/lib/ready_signal.ts b/x-pack/plugins/event_log/server/lib/ready_signal.ts new file mode 100644 index 00000000000000..2ea8e655089daa --- /dev/null +++ b/x-pack/plugins/event_log/server/lib/ready_signal.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export interface ReadySignal { + wait(): Promise; + signal(value: T): void; +} + +export function createReadySignal(): ReadySignal { + let resolver: (value: T) => void; + + const promise = new Promise(resolve => { + resolver = resolve; + }); + + async function wait(): Promise { + return await promise; + } + + function signal(value: T) { + resolver(value); + } + + return { wait, signal }; +} diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts new file mode 100644 index 00000000000000..5bc0bcd4287b4b --- /dev/null +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { first } from 'rxjs/operators'; +import { + CoreSetup, + CoreStart, + Logger, + Plugin as CorePlugin, + PluginInitializerContext, + ClusterClient, +} from 'src/core/server'; + +import { IEventLogConfig, IEventLogService, IEventLogger, IEventLogConfig$ } from './types'; +import { EventLogService } from './event_log_service'; +import { createEsContext, EsContext } from './es'; + +export type PluginClusterClient = Pick; + +// TODO - figure out how to get ${kibana.index} for `.kibana` +const KIBANA_INDEX = '.kibana'; + +const PROVIDER = 'event_log'; +const ACTIONS = { + starting: 'starting', + stopping: 'stopping', +}; + +export class Plugin implements CorePlugin { + private readonly config$: IEventLogConfig$; + private systemLogger: Logger; + private eventLogService?: IEventLogService; + private esContext?: EsContext; + private eventLogger?: IEventLogger; + + constructor(private readonly context: PluginInitializerContext) { + this.systemLogger = this.context.logger.get(); + this.config$ = this.context.config.create(); + } + + async setup(core: CoreSetup): Promise { + this.systemLogger.debug('setting up plugin'); + + const config = await this.config$.pipe(first()).toPromise(); + + this.esContext = createEsContext({ + logger: this.systemLogger, + // TODO: get index prefix from config.get(kibana.index) + indexNameRoot: KIBANA_INDEX, + clusterClient: core.elasticsearch.adminClient, + }); + + this.eventLogService = new EventLogService({ + config, + esContext: this.esContext, + systemLogger: this.systemLogger, + }); + + this.eventLogService.registerProviderActions(PROVIDER, Object.values(ACTIONS)); + + this.eventLogger = this.eventLogService.getLogger({ + event: { provider: PROVIDER }, + }); + + return this.eventLogService; + } + + async start(core: CoreStart) { + this.systemLogger.debug('starting plugin'); + + if (!this.esContext) throw new Error('esContext not initialized'); + if (!this.eventLogger) throw new Error('eventLogger not initialized'); + if (!this.eventLogService) throw new Error('eventLogService not initialized'); + + // launches initialization async + if (this.eventLogService.isIndexingEntries()) { + this.esContext.initialize(); + } + + // will log the event after initialization + this.eventLogger.logEvent({ + event: { action: ACTIONS.starting }, + message: 'event_log starting', + }); + } + + stop() { + this.systemLogger.debug('stopping plugin'); + + if (!this.eventLogger) throw new Error('eventLogger not initialized'); + + // note that it's unlikely this event would ever be written, + // when Kibana is actuaelly stopping, as it's written asynchronously + this.eventLogger.logEvent({ + event: { action: ACTIONS.stopping }, + message: 'event_log stopping', + }); + } +} diff --git a/x-pack/plugins/event_log/server/types.ts b/x-pack/plugins/event_log/server/types.ts new file mode 100644 index 00000000000000..4cace59752f366 --- /dev/null +++ b/x-pack/plugins/event_log/server/types.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Observable } from 'rxjs'; +import { schema, TypeOf } from '@kbn/config-schema'; + +export { IEvent, IValidatedEvent, EventSchema, ECS_VERSION } from '../generated/schemas'; +import { IEvent } from '../generated/schemas'; + +export const ConfigSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), + logEntries: schema.boolean({ defaultValue: false }), + indexEntries: schema.boolean({ defaultValue: false }), +}); + +export type IEventLogConfig = TypeOf; +export type IEventLogConfig$ = Observable>; + +// the object exposed by plugin.setup() +export interface IEventLogService { + isEnabled(): boolean; + isLoggingEntries(): boolean; + isIndexingEntries(): boolean; + registerProviderActions(provider: string, actions: string[]): void; + isProviderActionRegistered(provider: string, action: string): boolean; + getProviderActions(): Map>; + + getLogger(properties: IEvent): IEventLogger; +} + +export interface IEventLogger { + logEvent(properties: IEvent): void; + startTiming(event: IEvent): void; + stopTiming(event: IEvent): void; +} diff --git a/x-pack/plugins/licensing/public/plugin.test.ts b/x-pack/plugins/licensing/public/plugin.test.ts index 01545ee8d48b4a..f68e1dcfaf62ba 100644 --- a/x-pack/plugins/licensing/public/plugin.test.ts +++ b/x-pack/plugins/licensing/public/plugin.test.ts @@ -64,10 +64,8 @@ describe('licensing plugin', () => { await refresh(); - expect(coreSetup.http.get.mock.calls[0][1]).toMatchObject({ - headers: { - 'kbn-system-api': 'true', - }, + expect(coreSetup.http.get.mock.calls[0][0]).toMatchObject({ + asSystemRequest: true, }); }); }); diff --git a/x-pack/plugins/licensing/public/plugin.ts b/x-pack/plugins/licensing/public/plugin.ts index 7d2498b0f7ff6e..dab4c4048ce4c4 100644 --- a/x-pack/plugins/licensing/public/plugin.ts +++ b/x-pack/plugins/licensing/public/plugin.ts @@ -132,10 +132,9 @@ export class LicensingPlugin implements Plugin { private fetchLicense = async (core: CoreSetup): Promise => { try { - const response = await core.http.get(this.infoEndpoint, { - headers: { - 'kbn-system-api': 'true', - }, + const response = await core.http.get({ + path: this.infoEndpoint, + asSystemRequest: true, }); return new License({ license: response.license, diff --git a/x-pack/plugins/observability/kibana.json b/x-pack/plugins/observability/kibana.json new file mode 100644 index 00000000000000..57063ea729ed6d --- /dev/null +++ b/x-pack/plugins/observability/kibana.json @@ -0,0 +1,6 @@ +{ + "id": "observability", + "version": "8.0.0", + "kibanaVersion": "kibana", + "ui": true +} diff --git a/x-pack/plugins/observability/public/components/action_menu.tsx b/x-pack/plugins/observability/public/components/action_menu.tsx new file mode 100644 index 00000000000000..6e964dde3aecf7 --- /dev/null +++ b/x-pack/plugins/observability/public/components/action_menu.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + EuiPopover, + EuiText, + EuiListGroup, + EuiSpacer, + EuiHorizontalRule, + EuiListGroupItem, + EuiPopoverProps, +} from '@elastic/eui'; + +import React, { HTMLAttributes } from 'react'; +import { EuiListGroupItemProps } from '@elastic/eui/src/components/list_group/list_group_item'; + +type Props = EuiPopoverProps & HTMLAttributes; + +export const SectionTitle: React.FC<{}> = props => ( + <> + +
    {props.children}
    +
    + + +); + +export const SectionSubtitle: React.FC<{}> = props => ( + <> + + {props.children} + + + +); + +export const SectionLinks: React.FC<{}> = props => ( + + {props.children} + +); + +export const SectionSpacer: React.FC<{}> = () => ; + +export const Section: React.FC<{}> = props => <>{props.children}; + +export type SectionLinkProps = EuiListGroupItemProps; +export const SectionLink: React.FC = props => ( + +); + +export const ActionMenuDivider: React.FC<{}> = props => ; + +export const ActionMenu: React.FC = props => ; diff --git a/x-pack/plugins/observability/public/index.ts b/x-pack/plugins/observability/public/index.ts new file mode 100644 index 00000000000000..c822edc3f4de8a --- /dev/null +++ b/x-pack/plugins/observability/public/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginInitializerContext, PluginInitializer } from 'kibana/public'; +import { Plugin, ClientSetup, ClientStart } from './plugin'; + +export const plugin: PluginInitializer = ( + context: PluginInitializerContext +) => { + return new Plugin(context); +}; + +export * from './components/action_menu'; diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts new file mode 100644 index 00000000000000..a7eb1c50a03928 --- /dev/null +++ b/x-pack/plugins/observability/public/plugin.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { Plugin as PluginClass, PluginInitializerContext } from 'kibana/public'; + +export type ClientSetup = void; +export type ClientStart = void; + +export class Plugin implements PluginClass { + constructor(context: PluginInitializerContext) {} + start() {} + setup() {} +} diff --git a/x-pack/plugins/searchprofiler/common/constants.ts b/x-pack/plugins/searchprofiler/common/constants.ts new file mode 100644 index 00000000000000..be653543f21f50 --- /dev/null +++ b/x-pack/plugins/searchprofiler/common/constants.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { LicenseType } from '../../licensing/common/types'; + +const basicLicense: LicenseType = 'basic'; + +/** @internal */ +export const PLUGIN = Object.freeze({ + id: 'searchprofiler', + minimumLicenseType: basicLicense, +}); diff --git a/x-pack/plugins/searchprofiler/common/index.ts b/x-pack/plugins/searchprofiler/common/index.ts new file mode 100644 index 00000000000000..e345d99f4bed70 --- /dev/null +++ b/x-pack/plugins/searchprofiler/common/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { PLUGIN } from './constants'; + +export { LicenseStatus } from './types'; diff --git a/x-pack/plugins/searchprofiler/common/types.ts b/x-pack/plugins/searchprofiler/common/types.ts new file mode 100644 index 00000000000000..fa69f249feb46e --- /dev/null +++ b/x-pack/plugins/searchprofiler/common/types.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** @internal */ +export interface LicenseStatus { + valid: boolean; + message?: string; +} diff --git a/x-pack/plugins/searchprofiler/kibana.json b/x-pack/plugins/searchprofiler/kibana.json new file mode 100644 index 00000000000000..af8ee68a9bfa29 --- /dev/null +++ b/x-pack/plugins/searchprofiler/kibana.json @@ -0,0 +1,8 @@ +{ + "id": "searchprofiler", + "version": "8.0.0", + "kibanaVersion": "kibana", + "requiredPlugins": ["dev_tools", "home", "licensing"], + "server": true, + "ui": true +} diff --git a/x-pack/plugins/searchprofiler/public/README.md b/x-pack/plugins/searchprofiler/public/README.md new file mode 100644 index 00000000000000..3cf79162b3965f --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/README.md @@ -0,0 +1,3 @@ +## Please note + +See x-pack/legacy/plugins/searchprofiler/public for styles. diff --git a/x-pack/plugins/searchprofiler/public/application/boot.tsx b/x-pack/plugins/searchprofiler/public/application/boot.tsx new file mode 100644 index 00000000000000..d6e865f0eb8865 --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/application/boot.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { render, unmountComponentAtNode } from 'react-dom'; +import { HttpStart as Http, ToastsSetup } from 'kibana/public'; +import React from 'react'; + +import { LicenseStatus } from '../../common'; +import { App } from '.'; + +export interface Dependencies { + el: HTMLElement; + http: Http; + I18nContext: any; + notifications: ToastsSetup; + initialLicenseStatus: LicenseStatus; +} + +export type AppDependencies = Omit; + +export function boot(deps: Dependencies): () => void { + const { el, ...rest } = deps; + render(, deps.el); + return () => unmountComponentAtNode(deps.el); +} diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx b/x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx similarity index 94% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx rename to x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx index 30a4c1dce1dff7..f539baadd50525 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx +++ b/x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/highlight_details_flyout.test.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed } from '../../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../../test_utils'; import { HighlightDetailsFlyout, Props } from '.'; describe('Highlight Details Flyout', () => { diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.tsx b/x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/highlight_details_flyout.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_flyout.tsx rename to x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/highlight_details_flyout.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_table.tsx b/x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/highlight_details_table.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/highlight_details_table.tsx rename to x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/highlight_details_table.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/index.ts b/x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/highlight_details_flyout/index.ts rename to x-pack/plugins/searchprofiler/public/application/components/highlight_details_flyout/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/index.ts b/x-pack/plugins/searchprofiler/public/application/components/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/index.ts rename to x-pack/plugins/searchprofiler/public/application/components/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.test.ts b/x-pack/plugins/searchprofiler/public/application/components/license_warning_notice.test.ts similarity index 87% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.test.ts rename to x-pack/plugins/searchprofiler/public/application/components/license_warning_notice.test.ts index ebe7a00737868f..79a2d6c1426f72 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.test.ts +++ b/x-pack/plugins/searchprofiler/public/application/components/license_warning_notice.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed } from '../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../test_utils'; import { LicenseWarningNotice } from './license_warning_notice'; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.tsx b/x-pack/plugins/searchprofiler/public/application/components/license_warning_notice.tsx similarity index 99% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.tsx rename to x-pack/plugins/searchprofiler/public/application/components/license_warning_notice.tsx index da9991529e7d44..295e15056acc4f 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/license_warning_notice.tsx +++ b/x-pack/plugins/searchprofiler/public/application/components/license_warning_notice.tsx @@ -36,7 +36,7 @@ export const LicenseWarningNotice = () => { title={i18n.translate('xpack.searchProfiler.licenseErrorMessageTitle', { defaultMessage: 'License error', })} - color="warning" + color="danger" iconType="alert" style={{ padding: '16px' }} > diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/percentage_badge.tsx b/x-pack/plugins/searchprofiler/public/application/components/percentage_badge.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/percentage_badge.tsx rename to x-pack/plugins/searchprofiler/public/application/components/percentage_badge.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/breakdown.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/breakdown.ts similarity index 88% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/breakdown.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/breakdown.ts index a65af9a7a3ff3e..41cad70b6b1dd6 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/breakdown.ts +++ b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/breakdown.ts @@ -1,3 +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; + * you may not use this file except in compliance with the Elastic License. + */ + export const breakdown = { advance: 0, advance_count: 0, diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_indices.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/normalize_indices.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_indices.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/normalize_indices.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_times.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/normalize_times.ts similarity index 98% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_times.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/normalize_times.ts index f26de49138f121..3cbacd2d31ac2b 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/normalize_times.ts +++ b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/normalize_times.ts @@ -1,3 +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; + * you may not use this file except in compliance with the Elastic License. + */ + export const inputTimes = [ { type: 'BooleanQuery', diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/processed_search_response.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/processed_search_response.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/processed_search_response.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/processed_search_response.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/search_response.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/search_response.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/fixtures/search_response.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/fixtures/search_response.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/init_data.test.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/init_data.test.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/init_data.test.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/init_data.test.ts diff --git a/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/profile_tree.test.tsx b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/profile_tree.test.tsx new file mode 100644 index 00000000000000..1286f30d69c262 --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/profile_tree.test.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { registerTestBed } from '../../../../../../../test_utils'; +import { searchResponse } from './fixtures/search_response'; +import { ProfileTree, Props } from '../profile_tree'; + +describe('ProfileTree', () => { + it('renders', async () => { + const props: Props = { + onHighlight: () => {}, + target: 'searches', + data: searchResponse, + }; + const init = registerTestBed(ProfileTree); + await init(props); + }); + + it('does not throw despite bad profile data', async () => { + // For now, ignore the console.error that gets logged. + const props: Props = { + onHighlight: () => {}, + target: 'searches', + data: [{}] as any, + }; + + const init = registerTestBed(ProfileTree); + await init(props); + }); +}); diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/unsafe_utils.test.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/unsafe_utils.test.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/unsafe_utils.test.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/unsafe_utils.test.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/utils.test.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/utils.test.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/__tests__/utils.test.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/__tests__/utils.test.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/constants.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/constants.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/constants.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/constants.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/highlight_context.tsx b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/highlight_context.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/highlight_context.tsx rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/highlight_context.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index_details.tsx b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/index_details.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/index_details.tsx rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/index_details.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/init_data.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/init_data.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/init_data.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/init_data.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/profile_tree.tsx b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/profile_tree.tsx similarity index 88% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/profile_tree.tsx rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/profile_tree.tsx index ea24abbdb56db2..87a73cdefba313 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/profile_tree.tsx +++ b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/profile_tree.tsx @@ -10,7 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { IndexDetails } from './index_details'; import { ShardDetails } from './shard_details'; import { initDataFor } from './init_data'; -import { Targets, ShardSerialized } from '../../types'; +import { Targets, ShardSerialized, Index } from '../../types'; import { HighlightContextProvider, OnHighlightChangeArgs } from './highlight_context'; export interface Props { @@ -24,7 +24,14 @@ export const ProfileTree = memo(({ data, target, onHighlight }: Props) => { return null; } - const sortedIndices = initDataFor(target)(data); + let sortedIndices: Index[]; + try { + sortedIndices = initDataFor(target)(data); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + return null; + } return ( diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/index.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/shard_details/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/index.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/shard_details/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details.tsx b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/shard_details/shard_details.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details.tsx rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/shard_details/shard_details.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree.tsx b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/shard_details/shard_details_tree.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree.tsx rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/shard_details/shard_details_tree.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree_node.tsx b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/shard_details/shard_details_tree_node.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/shard_details/shard_details_tree_node.tsx rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/shard_details/shard_details_tree_node.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/types.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/types.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/types.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/types.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/unsafe_utils.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/unsafe_utils.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/unsafe_utils.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/unsafe_utils.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/use_highlight_tree_node.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/use_highlight_tree_node.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/use_highlight_tree_node.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/use_highlight_tree_node.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/utils.ts b/x-pack/plugins/searchprofiler/public/application/components/profile_tree/utils.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/profile_tree/utils.ts rename to x-pack/plugins/searchprofiler/public/application/components/profile_tree/utils.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.test.ts b/x-pack/plugins/searchprofiler/public/application/components/searchprofiler_tabs.test.ts similarity index 90% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.test.ts rename to x-pack/plugins/searchprofiler/public/application/components/searchprofiler_tabs.test.ts index 8ee43e28bcd2c5..28eb56ae051c7d 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.test.ts +++ b/x-pack/plugins/searchprofiler/public/application/components/searchprofiler_tabs.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed } from '../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../test_utils'; import { SearchProfilerTabs, Props } from './searchprofiler_tabs'; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.tsx b/x-pack/plugins/searchprofiler/public/application/components/searchprofiler_tabs.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/components/searchprofiler_tabs.tsx rename to x-pack/plugins/searchprofiler/public/application/components/searchprofiler_tabs.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/index.ts b/x-pack/plugins/searchprofiler/public/application/containers/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/index.ts rename to x-pack/plugins/searchprofiler/public/application/containers/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.test.tsx b/x-pack/plugins/searchprofiler/public/application/containers/main/components/empty_tree_placeholder.test.tsx similarity index 85% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.test.tsx rename to x-pack/plugins/searchprofiler/public/application/containers/main/components/empty_tree_placeholder.test.tsx index 4f17d0b4304f64..811f83041006bb 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.test.tsx +++ b/x-pack/plugins/searchprofiler/public/application/containers/main/components/empty_tree_placeholder.test.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed } from '../../../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../../../test_utils'; import { EmptyTreePlaceHolder } from '.'; describe('EmptyTreePlaceholder', () => { diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.tsx b/x-pack/plugins/searchprofiler/public/application/containers/main/components/empty_tree_placeholder.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/empty_tree_placeholder.tsx rename to x-pack/plugins/searchprofiler/public/application/containers/main/components/empty_tree_placeholder.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/index.ts b/x-pack/plugins/searchprofiler/public/application/containers/main/components/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/index.ts rename to x-pack/plugins/searchprofiler/public/application/containers/main/components/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.test.tsx b/x-pack/plugins/searchprofiler/public/application/containers/main/components/profile_loading_placeholder.test.tsx similarity index 86% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.test.tsx rename to x-pack/plugins/searchprofiler/public/application/containers/main/components/profile_loading_placeholder.test.tsx index 9b3348b4cab4b2..1428840a9464fa 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.test.tsx +++ b/x-pack/plugins/searchprofiler/public/application/containers/main/components/profile_loading_placeholder.test.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed } from '../../../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../../../test_utils'; import { ProfileLoadingPlaceholder } from '.'; describe('Profile Loading Placeholder', () => { diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.tsx b/x-pack/plugins/searchprofiler/public/application/containers/main/components/profile_loading_placeholder.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/components/profile_loading_placeholder.tsx rename to x-pack/plugins/searchprofiler/public/application/containers/main/components/profile_loading_placeholder.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/index.ts b/x-pack/plugins/searchprofiler/public/application/containers/main/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/index.ts rename to x-pack/plugins/searchprofiler/public/application/containers/main/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/main.tsx b/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx similarity index 88% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/main.tsx rename to x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx index 63ae5c7583625a..90617ba1c51676 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/main/main.tsx +++ b/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx @@ -28,21 +28,13 @@ import { import { useAppContext } from '../../contexts/app_context'; import { EmptyTreePlaceHolder, ProfileLoadingPlaceholder } from './components'; -import { Targets, ShardSerialized } from '../../types'; +import { Targets } from '../../types'; import { useProfilerActionContext, useProfilerReadContext } from '../../contexts/profiler_context'; -function hasSearch(profileResponse: ShardSerialized[]) { - const aggs = _.get(profileResponse, '[0].searches', []); - return aggs.length > 0; -} - -function hasAggregations(profileResponse: ShardSerialized[]) { - const aggs = _.get(profileResponse, '[0].aggregations', []); - return aggs.length > 0; -} +import { hasAggregations, hasSearch } from '../../utils'; export const Main = () => { - const { licenseEnabled } = useAppContext(); + const { getLicenseStatus } = useAppContext(); const { activeTab, @@ -63,7 +55,7 @@ export const Main = () => { ]); const renderLicenseWarning = () => { - return !licenseEnabled ? ( + return !getLicenseStatus().valid ? ( <> @@ -84,7 +76,7 @@ export const Main = () => { ); } - if (licenseEnabled && pristine) { + if (getLicenseStatus().valid && pristine) { return ; } diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/profile_query_editor.tsx b/x-pack/plugins/searchprofiler/public/application/containers/profile_query_editor.tsx similarity index 97% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/profile_query_editor.tsx rename to x-pack/plugins/searchprofiler/public/application/containers/profile_query_editor.tsx index b879f15b729982..5348c55ad52139 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/containers/profile_query_editor.tsx +++ b/x-pack/plugins/searchprofiler/public/application/containers/profile_query_editor.tsx @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import React, { useRef, memo, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { @@ -39,7 +40,7 @@ export const ProfileQueryEditor = memo(() => { const dispatch = useProfilerActionContext(); - const { licenseEnabled, notifications } = useAppContext(); + const { getLicenseStatus, notifications } = useAppContext(); const requestProfile = useRequestProfile(); const handleProfileClick = async () => { @@ -65,6 +66,7 @@ export const ProfileQueryEditor = memo(() => { }; const onEditorReady = useCallback(editorInstance => (editorRef.current = editorInstance), []); + const licenseEnabled = getLicenseStatus().valid; return ( LicenseStatus; +} + +const AppContext = createContext(null as any); + +export const AppContextProvider = ({ + children, + args: { http, notifications, initialLicenseStatus }, +}: { + children: React.ReactNode; + args: ContextArgs; +}) => { + const getLicenseStatus = useCallback(() => initialLicenseStatus, [initialLicenseStatus]); + + return ( + + {children} + + ); +}; + +export const useAppContext = () => { + const ctx = useContext(AppContext); + if (ctx == null) { + throw new Error(`useAppContext must be called inside AppContextProvider`); + } + return ctx; +}; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/profiler_context.tsx b/x-pack/plugins/searchprofiler/public/application/contexts/profiler_context.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/contexts/profiler_context.tsx rename to x-pack/plugins/searchprofiler/public/application/contexts/profiler_context.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.test.tsx b/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx similarity index 91% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.test.tsx rename to x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx index d6702ef080ab73..a70d70f117edb6 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.test.tsx +++ b/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx @@ -10,7 +10,7 @@ jest.mock('./worker', () => { return { workerModule: { id: 'ace/mode/json_worker', src: '' } }; }); -import { registerTestBed } from '../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../test_utils'; import { Editor, Props } from '.'; describe('Editor Component', () => { diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.tsx b/x-pack/plugins/searchprofiler/public/application/editor/editor.tsx similarity index 84% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.tsx rename to x-pack/plugins/searchprofiler/public/application/editor/editor.tsx index 014336f379059a..5f8ab776a7672c 100644 --- a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/editor.tsx +++ b/x-pack/plugins/searchprofiler/public/application/editor/editor.tsx @@ -10,10 +10,7 @@ import { Editor as AceEditor } from 'brace'; import { initializeEditor } from './init_editor'; import { useUIAceKeyboardMode } from './use_ui_ace_keyboard_mode'; -interface EditorShim { - getValue(): string; - focus(): void; -} +type EditorShim = ReturnType; export type EditorInstance = EditorShim; @@ -23,7 +20,7 @@ export interface Props { onEditorReady: (editor: EditorShim) => void; } -const createEditorShim = (aceEditor: AceEditor): EditorShim => { +const createEditorShim = (aceEditor: AceEditor) => { return { getValue() { return aceEditor.getValue(); @@ -40,15 +37,13 @@ export const Editor = memo(({ licenseEnabled, initialValue, onEditorReady }: Pro const [textArea, setTextArea] = useState(null); - if (licenseEnabled) { - useUIAceKeyboardMode(textArea); - } + useUIAceKeyboardMode(textArea); useEffect(() => { const divEl = containerRef.current; editorInstanceRef.current = initializeEditor({ el: divEl, licenseEnabled }); editorInstanceRef.current.setValue(initialValue, 1); - setTextArea(containerRef.current!.querySelector('textarea')); + setTextArea(licenseEnabled ? containerRef.current!.querySelector('textarea') : null); onEditorReady(createEditorShim(editorInstanceRef.current)); }, [initialValue, onEditorReady, licenseEnabled]); diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/index.ts b/x-pack/plugins/searchprofiler/public/application/editor/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/index.ts rename to x-pack/plugins/searchprofiler/public/application/editor/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/init_editor.ts b/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/init_editor.ts rename to x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/use_ui_ace_keyboard_mode.tsx b/x-pack/plugins/searchprofiler/public/application/editor/use_ui_ace_keyboard_mode.tsx similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/use_ui_ace_keyboard_mode.tsx rename to x-pack/plugins/searchprofiler/public/application/editor/use_ui_ace_keyboard_mode.tsx diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/index.ts b/x-pack/plugins/searchprofiler/public/application/editor/worker/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/index.ts rename to x-pack/plugins/searchprofiler/public/application/editor/worker/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/worker.d.ts b/x-pack/plugins/searchprofiler/public/application/editor/worker/worker.d.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/worker.d.ts rename to x-pack/plugins/searchprofiler/public/application/editor/worker/worker.d.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/worker.js b/x-pack/plugins/searchprofiler/public/application/editor/worker/worker.js similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/worker/worker.js rename to x-pack/plugins/searchprofiler/public/application/editor/worker/worker.js diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/x_json_highlight_rules.ts b/x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/x_json_highlight_rules.ts rename to x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/x_json_mode.ts b/x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/editor/x_json_mode.ts rename to x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/index.ts b/x-pack/plugins/searchprofiler/public/application/hooks/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/hooks/index.ts rename to x-pack/plugins/searchprofiler/public/application/hooks/index.ts diff --git a/x-pack/plugins/searchprofiler/public/application/hooks/use_request_profile.ts b/x-pack/plugins/searchprofiler/public/application/hooks/use_request_profile.ts new file mode 100644 index 00000000000000..3d8bee1d62b274 --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/application/hooks/use_request_profile.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { i18n } from '@kbn/i18n'; + +import { useAppContext } from '../contexts/app_context'; +import { checkForParseErrors } from '../utils'; +import { ShardSerialized } from '../types'; + +interface Args { + query: string; + index: string; +} + +interface ReturnValue { + data: ShardSerialized[] | null; + error?: string; +} + +const extractProfilerErrorMessage = (e: any): string | undefined => { + if (e.body?.attributes?.error?.reason) { + const { reason, line, col } = e.body.attributes.error; + return `${reason} at line: ${line - 1} col: ${col}`; + } + + if (e.body?.message) { + return e.body.message; + } + + return; +}; + +export const useRequestProfile = () => { + const { http, notifications, getLicenseStatus } = useAppContext(); + const licenseEnabled = getLicenseStatus().valid; + return async ({ query, index }: Args): Promise => { + if (!licenseEnabled) { + return { data: null }; + } + const { error, parsed } = checkForParseErrors(query); + if (error) { + notifications.addError(error, { + title: i18n.translate('xpack.searchProfiler.errorToastTitle', { + defaultMessage: 'JSON parse error', + }), + }); + return { data: null }; + } + // Shortcut the network request if we have json with shards already... + if (parsed.profile && parsed.profile.shards) { + return { data: parsed.profile.shards }; + } + + const payload: Record = { query: parsed }; + + if (index == null || index === '') { + payload.index = '_all'; + } else { + payload.index = index; + } + + try { + const resp = await http.post('../api/searchprofiler/profile', { + body: JSON.stringify(payload), + headers: { 'Content-Type': 'application/json' }, + }); + + if (!resp.ok) { + return { data: null, error: resp.err.msg }; + } + + return { data: resp.resp.profile.shards }; + } catch (e) { + const profilerErrorMessage = extractProfilerErrorMessage(e); + if (profilerErrorMessage) { + notifications.addError(e, { + title: e.message, + toastMessage: profilerErrorMessage, + }); + } else { + // Otherwise just report the original error + notifications.addError(e, { + title: i18n.translate('xpack.searchProfiler.errorSomethingWentWrongTitle', { + defaultMessage: 'Something went wrong', + }), + }); + } + return { data: null }; + } + }; +}; diff --git a/x-pack/plugins/searchprofiler/public/application/index.tsx b/x-pack/plugins/searchprofiler/public/application/index.tsx new file mode 100644 index 00000000000000..fd8ab61eb9b089 --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/application/index.tsx @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { Main } from './containers'; +import { AppContextProvider } from './contexts/app_context'; +import { ProfileContextProvider } from './contexts/profiler_context'; + +import { AppDependencies } from './boot'; + +export function App({ I18nContext, initialLicenseStatus, notifications, http }: AppDependencies) { + return ( + + + +
    + + + + ); +} diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/index.ts b/x-pack/plugins/searchprofiler/public/application/store/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/index.ts rename to x-pack/plugins/searchprofiler/public/application/store/index.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/reducer.test.ts b/x-pack/plugins/searchprofiler/public/application/store/reducer.test.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/reducer.test.ts rename to x-pack/plugins/searchprofiler/public/application/store/reducer.test.ts diff --git a/x-pack/plugins/searchprofiler/public/application/store/reducer.ts b/x-pack/plugins/searchprofiler/public/application/store/reducer.ts new file mode 100644 index 00000000000000..5366dcec3fcf02 --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/application/store/reducer.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Reducer } from 'react'; +import { State } from './store'; + +import { OnHighlightChangeArgs } from '../components/profile_tree'; +import { ShardSerialized, Targets } from '../types'; +import { hasSearch, hasAggregations } from '../utils'; + +export type Action = + | { type: 'setProfiling'; value: boolean } + | { type: 'setHighlightDetails'; value: OnHighlightChangeArgs | null } + | { type: 'setActiveTab'; value: Targets | null } + | { type: 'setCurrentResponse'; value: ShardSerialized[] | null }; + +export const reducer: Reducer = (state, action) => { + const nextState = { ...state }; + + if (action.type === 'setProfiling') { + nextState.pristine = false; + nextState.profiling = action.value; + if (nextState.profiling) { + nextState.currentResponse = null; + nextState.highlightDetails = null; + } + return nextState; + } + + if (action.type === 'setHighlightDetails') { + if (action.value) { + const value = action.value; + // Exclude children to avoid unnecessary work copying a recursive structure. + const { children, parent, ...restOfOperation } = value.operation; + nextState.highlightDetails = { + indexName: value.indexName, + operation: Object.freeze(restOfOperation), + // prettier-ignore + shardName: `[${/* shard id */value.shard.id[0]}][${/* shard number */value.shard.id[2] }]` + }; + } else { + nextState.highlightDetails = null; + } + return nextState; + } + + if (action.type === 'setActiveTab') { + nextState.activeTab = action.value; + return nextState; + } + + if (action.type === 'setCurrentResponse') { + nextState.currentResponse = action.value; + if (nextState.currentResponse) { + const currentResponseHasAggregations = hasAggregations(nextState.currentResponse); + const currentResponseHasSearch = hasSearch(nextState.currentResponse); + if ( + nextState.activeTab === 'searches' && + !currentResponseHasSearch && + currentResponseHasAggregations + ) { + nextState.activeTab = 'aggregations'; + } else if ( + nextState.activeTab === 'aggregations' && + !currentResponseHasAggregations && + currentResponseHasSearch + ) { + nextState.activeTab = 'searches'; + } else if (!nextState.activeTab) { + // Default to searches tab + nextState.activeTab = 'searches'; + } + } else { + nextState.activeTab = null; + } + return nextState; + } + + throw new Error(`Unknown action: ${action}`); +}; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/store.ts b/x-pack/plugins/searchprofiler/public/application/store/store.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/store/store.ts rename to x-pack/plugins/searchprofiler/public/application/store/store.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/types.ts b/x-pack/plugins/searchprofiler/public/application/types.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/types.ts rename to x-pack/plugins/searchprofiler/public/application/types.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.test.ts b/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.test.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.test.ts rename to x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.test.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.ts b/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/check_for_json_errors.ts rename to x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts diff --git a/x-pack/plugins/searchprofiler/public/application/utils/has_aggregations.ts b/x-pack/plugins/searchprofiler/public/application/utils/has_aggregations.ts new file mode 100644 index 00000000000000..6d2803be185dc2 --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/application/utils/has_aggregations.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get } from 'lodash'; +import { ShardSerialized } from '../types'; + +export function hasAggregations(profileResponse: ShardSerialized[]) { + const aggs = get(profileResponse, '[0].aggregations', []); + return aggs.length > 0; +} diff --git a/x-pack/plugins/searchprofiler/public/application/utils/has_searches.ts b/x-pack/plugins/searchprofiler/public/application/utils/has_searches.ts new file mode 100644 index 00000000000000..0247e7a19584ba --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/application/utils/has_searches.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get } from 'lodash'; +import { ShardSerialized } from '../types'; + +export function hasSearch(profileResponse: ShardSerialized[]) { + const aggs = get(profileResponse, '[0].searches', []); + return aggs.length > 0; +} diff --git a/x-pack/plugins/searchprofiler/public/application/utils/index.ts b/x-pack/plugins/searchprofiler/public/application/utils/index.ts new file mode 100644 index 00000000000000..1623ff6fdd51bc --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/application/utils/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; + * you may not use this file except in compliance with the Elastic License. + */ +export { hasAggregations } from './has_aggregations'; +export { hasSearch } from './has_searches'; +export { checkForParseErrors } from './check_for_json_errors'; +export { msToPretty } from './ms_to_pretty'; +export { nsToPretty } from './ns_to_pretty'; diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ms_to_pretty.ts b/x-pack/plugins/searchprofiler/public/application/utils/ms_to_pretty.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ms_to_pretty.ts rename to x-pack/plugins/searchprofiler/public/application/utils/ms_to_pretty.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.test.ts b/x-pack/plugins/searchprofiler/public/application/utils/ns_to_pretty.test.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.test.ts rename to x-pack/plugins/searchprofiler/public/application/utils/ns_to_pretty.test.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.ts b/x-pack/plugins/searchprofiler/public/application/utils/ns_to_pretty.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/application/utils/ns_to_pretty.ts rename to x-pack/plugins/searchprofiler/public/application/utils/ns_to_pretty.ts diff --git a/x-pack/legacy/plugins/searchprofiler/public/np_ready/index.ts b/x-pack/plugins/searchprofiler/public/index.ts similarity index 100% rename from x-pack/legacy/plugins/searchprofiler/public/np_ready/index.ts rename to x-pack/plugins/searchprofiler/public/index.ts diff --git a/x-pack/plugins/searchprofiler/public/plugin.ts b/x-pack/plugins/searchprofiler/public/plugin.ts new file mode 100644 index 00000000000000..8f44e65e4546ae --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/plugin.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { Plugin, CoreStart, CoreSetup, PluginInitializerContext } from 'kibana/public'; +import { first } from 'rxjs/operators'; + +import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public'; +import { LICENSE_CHECK_STATE } from '../../licensing/public'; + +import { PLUGIN } from '../common'; +import { AppPublicPluginDependencies } from './types'; + +export class SearchProfilerUIPlugin implements Plugin { + constructor(ctx: PluginInitializerContext) {} + + async setup( + { http, getStartServices }: CoreSetup, + { dev_tools, home, licensing }: AppPublicPluginDependencies + ) { + home.featureCatalogue.register({ + id: PLUGIN.id, + title: i18n.translate('xpack.searchProfiler.registryProviderTitle', { + defaultMessage: 'Search Profiler', + }), + description: i18n.translate('xpack.searchProfiler.registryProviderDescription', { + defaultMessage: 'Quickly check the performance of any Elasticsearch query.', + }), + icon: 'searchProfilerApp', + path: '/app/kibana#/dev_tools/searchprofiler', + showOnHomePage: false, + category: FeatureCatalogueCategory.ADMIN, + }); + + dev_tools.register({ + id: 'searchprofiler', + title: i18n.translate('xpack.searchProfiler.pageDisplayName', { + defaultMessage: 'Search Profiler', + }), + order: 5, + enableRouting: false, + mount: async (ctx, params) => { + const [coreStart] = await getStartServices(); + const { notifications, i18n: i18nDep } = coreStart; + const { boot } = await import('./application/boot'); + + const license = await licensing.license$.pipe(first()).toPromise(); + const { state, message } = license.check(PLUGIN.id, PLUGIN.minimumLicenseType); + const initialLicenseStatus = + state === LICENSE_CHECK_STATE.Valid ? { valid: true } : { valid: false, message }; + + return boot({ + http, + initialLicenseStatus, + el: params.element, + I18nContext: i18nDep.Context, + notifications: notifications.toasts, + }); + }, + }); + } + + async start(core: CoreStart, plugins: any) {} + + async stop() {} +} diff --git a/x-pack/plugins/searchprofiler/public/types.ts b/x-pack/plugins/searchprofiler/public/types.ts new file mode 100644 index 00000000000000..697761669dd2f4 --- /dev/null +++ b/x-pack/plugins/searchprofiler/public/types.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; +import { DevToolsSetup } from '../../../../src/plugins/dev_tools/public'; +import { LicensingPluginSetup } from '../../licensing/public'; + +export interface AppPublicPluginDependencies { + licensing: LicensingPluginSetup; + home: HomePublicPluginSetup; + dev_tools: DevToolsSetup; +} diff --git a/x-pack/plugins/searchprofiler/server/index.ts b/x-pack/plugins/searchprofiler/server/index.ts new file mode 100644 index 00000000000000..459cd6c344d923 --- /dev/null +++ b/x-pack/plugins/searchprofiler/server/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { PluginInitializerContext } from 'kibana/server'; +import { SearchProfilerServerPlugin } from './plugin'; + +export const plugin = (ctx: PluginInitializerContext) => { + return new SearchProfilerServerPlugin(ctx); +}; diff --git a/x-pack/plugins/searchprofiler/server/plugin.ts b/x-pack/plugins/searchprofiler/server/plugin.ts new file mode 100644 index 00000000000000..e446b864287157 --- /dev/null +++ b/x-pack/plugins/searchprofiler/server/plugin.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'kibana/server'; + +import { LICENSE_CHECK_STATE } from '../../licensing/common/types'; + +import { LicenseStatus, PLUGIN } from '../common'; +import { AppServerPluginDependencies } from './types'; +import * as profileRoute from './routes/profile'; + +export class SearchProfilerServerPlugin implements Plugin { + licenseStatus: LicenseStatus; + log: Logger; + + constructor({ logger }: PluginInitializerContext) { + this.log = logger.get(); + this.licenseStatus = { valid: false }; + } + + async setup({ http }: CoreSetup, { licensing, elasticsearch }: AppServerPluginDependencies) { + const router = http.createRouter(); + profileRoute.register({ + elasticsearch, + router, + getLicenseStatus: () => this.licenseStatus, + log: this.log, + }); + + licensing.license$.subscribe(license => { + const { state, message } = license.check(PLUGIN.id, PLUGIN.minimumLicenseType); + const hasRequiredLicense = state === LICENSE_CHECK_STATE.Valid; + if (hasRequiredLicense) { + this.licenseStatus = { valid: true }; + } else { + this.licenseStatus = { + valid: false, + message: + message || + // Ensure that there is a message when license check fails + i18n.translate('xpack.searchProfiler.licenseCheckErrorMessage', { + defaultMessage: 'License check failed', + }), + }; + if (message) { + this.log.info(message); + } + } + }); + } + + start() {} + + stop() {} +} diff --git a/x-pack/plugins/searchprofiler/server/routes/profile.ts b/x-pack/plugins/searchprofiler/server/routes/profile.ts new file mode 100644 index 00000000000000..c47ab81b2ab7e6 --- /dev/null +++ b/x-pack/plugins/searchprofiler/server/routes/profile.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { schema } from '@kbn/config-schema'; +import { RouteDependencies } from '../types'; + +export const register = ({ router, getLicenseStatus, log }: RouteDependencies) => { + router.post( + { + path: '/api/searchprofiler/profile', + validate: { + body: schema.object({ + query: schema.object({}, { allowUnknowns: true }), + index: schema.string(), + }), + }, + }, + async (ctx, request, response) => { + const currentLicenseStatus = getLicenseStatus(); + if (!currentLicenseStatus.valid) { + return response.forbidden({ + body: { + message: currentLicenseStatus.message!, + }, + }); + } + + const { + core: { elasticsearch }, + } = ctx; + + const { + body: { query, index }, + } = request; + + const parsed = { + // Activate profiler mode for this query. + profile: true, + ...query, + }; + + const body = { + index, + body: JSON.stringify(parsed, null, 2), + }; + try { + const resp = await elasticsearch.dataClient.callAsCurrentUser('search', body); + return response.ok({ + body: { + ok: true, + resp, + }, + }); + } catch (err) { + log.error(err); + return response.customError({ + statusCode: err.status || 500, + body: err.body + ? { + message: err.message, + attributes: err.body, + } + : err, + }); + } + } + ); +}; diff --git a/x-pack/plugins/searchprofiler/server/types.ts b/x-pack/plugins/searchprofiler/server/types.ts new file mode 100644 index 00000000000000..7aa0032afba138 --- /dev/null +++ b/x-pack/plugins/searchprofiler/server/types.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IRouter, Logger } from 'kibana/server'; +import { ElasticsearchPlugin } from '../../../../src/legacy/core_plugins/elasticsearch'; +import { LicensingPluginSetup } from '../../licensing/server'; +import { LicenseStatus } from '../common'; + +export interface AppServerPluginDependencies { + licensing: LicensingPluginSetup; + elasticsearch: ElasticsearchPlugin; +} + +export interface RouteDependencies { + getLicenseStatus: () => LicenseStatus; + elasticsearch: ElasticsearchPlugin; + router: IRouter; + log: Logger; +} diff --git a/x-pack/plugins/security/common/model/index.ts b/x-pack/plugins/security/common/model/index.ts index f3c65ed7e3cf17..121791d113bd5d 100644 --- a/x-pack/plugins/security/common/model/index.ts +++ b/x-pack/plugins/security/common/model/index.ts @@ -10,7 +10,16 @@ export { AuthenticatedUser, canUserChangePassword } from './authenticated_user'; export { BuiltinESPrivileges } from './builtin_es_privileges'; export { FeaturesPrivileges } from './features_privileges'; export { RawKibanaPrivileges, RawKibanaFeaturePrivileges } from './raw_kibana_privileges'; -export { Role, RoleIndexPrivilege, RoleKibanaPrivilege } from './role'; +export { + Role, + RoleIndexPrivilege, + RoleKibanaPrivilege, + copyRole, + isReadOnlyRole, + isReservedRole, + isRoleEnabled, + prepareRoleClone, +} from './role'; export { KibanaPrivileges } from './kibana_privileges'; export { InlineRoleTemplate, diff --git a/x-pack/plugins/security/common/model/role.test.ts b/x-pack/plugins/security/common/model/role.test.ts new file mode 100644 index 00000000000000..d4a910a1785ebd --- /dev/null +++ b/x-pack/plugins/security/common/model/role.test.ts @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Role, isReadOnlyRole, isReservedRole, isRoleEnabled, copyRole, prepareRoleClone } from '.'; + +describe('role', () => { + describe('isRoleEnabled', () => { + test('should return false if role is explicitly not enabled', () => { + const testRole = { + transient_metadata: { + enabled: false, + }, + }; + expect(isRoleEnabled(testRole)).toBe(false); + }); + + test('should return true if role is explicitly enabled', () => { + const testRole = { + transient_metadata: { + enabled: true, + }, + }; + expect(isRoleEnabled(testRole)).toBe(true); + }); + + test('should return true if role is NOT explicitly enabled or disabled', () => { + const testRole = {}; + expect(isRoleEnabled(testRole)).toBe(true); + }); + }); + + describe('isReservedRole', () => { + test('should return false if role is explicitly not reserved', () => { + const testRole = { + metadata: { + _reserved: false, + }, + }; + expect(isReservedRole(testRole)).toBe(false); + }); + + test('should return true if role is explicitly reserved', () => { + const testRole = { + metadata: { + _reserved: true, + }, + }; + expect(isReservedRole(testRole)).toBe(true); + }); + + test('should return false if role is NOT explicitly reserved or not reserved', () => { + const testRole = {}; + expect(isReservedRole(testRole)).toBe(false); + }); + }); + + describe('isReadOnlyRole', () => { + test('returns true for reserved roles', () => { + const testRole = { + metadata: { + _reserved: true, + }, + }; + expect(isReadOnlyRole(testRole)).toBe(true); + }); + + test('returns true for roles with transform errors', () => { + const testRole = { + _transform_error: ['kibana'], + }; + expect(isReadOnlyRole(testRole)).toBe(true); + }); + + test('returns false for disabled roles', () => { + const testRole = { + transient_metadata: { + enabled: false, + }, + }; + expect(isReadOnlyRole(testRole)).toBe(false); + }); + + test('returns false for all other roles', () => { + const testRole = {}; + expect(isReadOnlyRole(testRole)).toBe(false); + }); + }); + + describe('copyRole', () => { + it('should perform a deep copy', () => { + const role: Role = { + name: '', + elasticsearch: { + cluster: ['all'], + indices: [{ names: ['index*'], privileges: ['all'] }], + run_as: ['user'], + }, + kibana: [ + { + spaces: ['*'], + base: ['all'], + feature: {}, + }, + { + spaces: ['default'], + base: ['foo'], + feature: {}, + }, + { + spaces: ['marketing'], + base: ['read'], + feature: {}, + }, + ], + }; + + const result = copyRole(role); + expect(result).toEqual(role); + + role.elasticsearch.indices[0].names = ['something else']; + + expect(result).not.toEqual(role); + }); + }); + + describe('prepareRoleClone', () => { + it('should return a copy of the role, with a blank role name', () => { + const role: Role = { + name: 'my_role', + elasticsearch: { + cluster: ['all'], + indices: [{ names: ['index*'], privileges: ['all'] }], + run_as: ['user'], + }, + kibana: [ + { + spaces: ['*'], + base: ['all'], + feature: {}, + }, + { + spaces: ['default'], + base: ['foo'], + feature: {}, + }, + { + spaces: ['marketing'], + base: ['read'], + feature: {}, + }, + ], + metadata: { + _reserved: true, + }, + transient_metadata: { + enabled: false, + }, + }; + + const { name: originalName, ...originalRest } = role; + + const result = prepareRoleClone(role); + const { name, ...rest } = result; + + expect(originalName).toEqual('my_role'); + expect(name).toEqual(''); + + expect(rest).toEqual(originalRest); + }); + }); +}); diff --git a/x-pack/plugins/security/common/model/role.ts b/x-pack/plugins/security/common/model/role.ts index 89f68aaa55b5cb..1edcf147262ede 100644 --- a/x-pack/plugins/security/common/model/role.ts +++ b/x-pack/plugins/security/common/model/role.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { cloneDeep } from 'lodash'; import { FeaturesPrivileges } from './features_privileges'; export interface RoleIndexPrivilege { @@ -40,3 +41,53 @@ export interface Role { _transform_error?: string[]; _unrecognized_applications?: string[]; } + +/** + * Returns whether given role is enabled or not + * + * @param role Object Role JSON, as returned by roles API + * @return Boolean true if role is enabled; false otherwise + */ +export function isRoleEnabled(role: Partial) { + return role.transient_metadata?.enabled ?? true; +} + +/** + * Returns whether given role is reserved or not. + * + * @param role Role as returned by roles API + */ +export function isReservedRole(role: Partial) { + return (role.metadata?._reserved as boolean) ?? false; +} + +/** + * Returns whether given role is editable through the UI or not. + * + * @param role the Role as returned by roles API + */ +export function isReadOnlyRole(role: Partial): boolean { + return isReservedRole(role) || (role._transform_error?.length ?? 0) > 0; +} + +/** + * Returns a deep copy of the role. + * + * @param role the Role to copy. + */ +export function copyRole(role: Role) { + return cloneDeep(role); +} + +/** + * Creates a deep copy of the role suitable for cloning. + * + * @param role the Role to clone. + */ +export function prepareRoleClone(role: Role): Role { + const clone = copyRole(role); + + clone.name = ''; + + return clone; +} diff --git a/x-pack/plugins/security/kibana.json b/x-pack/plugins/security/kibana.json index 32f860b1423d30..7d1940e393becf 100644 --- a/x-pack/plugins/security/kibana.json +++ b/x-pack/plugins/security/kibana.json @@ -3,7 +3,8 @@ "version": "8.0.0", "kibanaVersion": "kibana", "configPath": ["xpack", "security"], - "requiredPlugins": ["features", "licensing"], + "requiredPlugins": ["data", "features", "licensing"], + "optionalPlugins": ["home", "management"], "server": true, "ui": true } diff --git a/x-pack/plugins/security/public/_index.scss b/x-pack/plugins/security/public/_index.scss new file mode 100644 index 00000000000000..9fa81bad7c3f40 --- /dev/null +++ b/x-pack/plugins/security/public/_index.scss @@ -0,0 +1,2 @@ +// Management styles +@import './management/index'; diff --git a/x-pack/plugins/security/public/account_management/account_management_page.test.tsx b/x-pack/plugins/security/public/account_management/account_management_page.test.tsx new file mode 100644 index 00000000000000..b7cf8e6dd14181 --- /dev/null +++ b/x-pack/plugins/security/public/account_management/account_management_page.test.tsx @@ -0,0 +1,141 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { act } from '@testing-library/react'; +import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; +import { AuthenticatedUser } from '../../common/model'; +import { AccountManagementPage } from './account_management_page'; + +import { coreMock } from 'src/core/public/mocks'; +import { securityMock } from '../mocks'; +import { userAPIClientMock } from '../management/users/index.mock'; + +interface Options { + withFullName?: boolean; + withEmail?: boolean; + realm?: string; +} +const createUser = ({ withFullName = true, withEmail = true, realm = 'native' }: Options = {}) => { + return { + full_name: withFullName ? 'Casey Smith' : '', + username: 'csmith', + email: withEmail ? 'csmith@domain.com' : '', + enabled: true, + roles: [], + authentication_realm: { + type: realm, + name: realm, + }, + lookup_realm: { + type: realm, + name: realm, + }, + }; +}; + +function getSecuritySetupMock({ currentUser }: { currentUser: AuthenticatedUser }) { + const securitySetupMock = securityMock.createSetup(); + securitySetupMock.authc.getCurrentUser.mockResolvedValue(currentUser); + return securitySetupMock; +} + +describe('', () => { + it(`displays users full name, username, and email address`, async () => { + const user = createUser(); + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('EuiText[data-test-subj="userDisplayName"]').text()).toEqual( + user.full_name + ); + expect(wrapper.find('[data-test-subj="username"]').text()).toEqual(user.username); + expect(wrapper.find('[data-test-subj="email"]').text()).toEqual(user.email); + }); + + it(`displays username when full_name is not provided`, async () => { + const user = createUser({ withFullName: false }); + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('EuiText[data-test-subj="userDisplayName"]').text()).toEqual(user.username); + }); + + it(`displays a placeholder when no email address is provided`, async () => { + const user = createUser({ withEmail: false }); + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="email"]').text()).toEqual('no email address'); + }); + + it(`displays change password form for users in the native realm`, async () => { + const user = createUser(); + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('EuiFieldText[data-test-subj="currentPassword"]')).toHaveLength(1); + expect(wrapper.find('EuiFieldText[data-test-subj="newPassword"]')).toHaveLength(1); + }); + + it(`does not display change password form for users in the saml realm`, async () => { + const user = createUser({ realm: 'saml' }); + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('EuiFieldText[data-test-subj="currentPassword"]')).toHaveLength(0); + expect(wrapper.find('EuiFieldText[data-test-subj="newPassword"]')).toHaveLength(0); + }); +}); diff --git a/x-pack/plugins/security/public/account_management/account_management_page.tsx b/x-pack/plugins/security/public/account_management/account_management_page.tsx new file mode 100644 index 00000000000000..3f764adc7949f2 --- /dev/null +++ b/x-pack/plugins/security/public/account_management/account_management_page.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { EuiPage, EuiPageBody, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; +import React, { useEffect, useState } from 'react'; +import { NotificationsStart } from 'src/core/public'; +import { getUserDisplayName, AuthenticatedUser } from '../../common/model'; +import { AuthenticationServiceSetup } from '../authentication'; +import { ChangePassword } from './change_password'; +import { UserAPIClient } from '../management'; +import { PersonalInfo } from './personal_info'; + +interface Props { + authc: AuthenticationServiceSetup; + apiClient: PublicMethodsOf; + notifications: NotificationsStart; +} + +export const AccountManagementPage = ({ apiClient, authc, notifications }: Props) => { + const [currentUser, setCurrentUser] = useState(null); + useEffect(() => { + authc.getCurrentUser().then(setCurrentUser); + }, [authc]); + + if (!currentUser) { + return null; + } + + return ( + + + + +

    {getUserDisplayName(currentUser)}

    +
    + + + + + + +
    +
    +
    + ); +}; diff --git a/x-pack/legacy/plugins/security/public/views/account/components/change_password/change_password.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx similarity index 81% rename from x-pack/legacy/plugins/security/public/views/account/components/change_password/change_password.tsx rename to x-pack/plugins/security/public/account_management/change_password/change_password.tsx index 63abb4539470d2..f5ac5f3b21d2e6 100644 --- a/x-pack/legacy/plugins/security/public/views/account/components/change_password/change_password.tsx +++ b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx @@ -3,18 +3,18 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { - // @ts-ignore - EuiDescribedFormGroup, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import React, { Component } from 'react'; -import { UserAPIClient } from '../../../../lib/api'; -import { AuthenticatedUser, canUserChangePassword } from '../../../../../common/model'; -import { ChangePasswordForm } from '../../../../components/management/change_password_form'; +import { EuiDescribedFormGroup } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NotificationsSetup } from 'src/core/public'; +import { AuthenticatedUser, canUserChangePassword } from '../../../common/model'; +import { UserAPIClient } from '../../management/users'; +import { ChangePasswordForm } from '../../management/users/components/change_password_form'; interface Props { user: AuthenticatedUser; + apiClient: PublicMethodsOf; + notifications: NotificationsSetup; } export class ChangePassword extends Component { @@ -48,7 +48,8 @@ export class ChangePassword extends Component { ); diff --git a/x-pack/legacy/plugins/security/public/views/account/components/change_password/index.ts b/x-pack/plugins/security/public/account_management/change_password/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/account/components/change_password/index.ts rename to x-pack/plugins/security/public/account_management/change_password/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/account/components/index.ts b/x-pack/plugins/security/public/account_management/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/account/components/index.ts rename to x-pack/plugins/security/public/account_management/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/account/components/personal_info/index.ts b/x-pack/plugins/security/public/account_management/personal_info/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/account/components/personal_info/index.ts rename to x-pack/plugins/security/public/account_management/personal_info/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/account/components/personal_info/personal_info.tsx b/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx similarity index 89% rename from x-pack/legacy/plugins/security/public/views/account/components/personal_info/personal_info.tsx rename to x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx index 7121bf7ab28ee7..9cbbc242e8400e 100644 --- a/x-pack/legacy/plugins/security/public/views/account/components/personal_info/personal_info.tsx +++ b/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx @@ -3,15 +3,10 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { - // @ts-ignore - EuiDescribedFormGroup, - EuiFormRow, - EuiText, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; -import { AuthenticatedUser } from '../../../../../common/model'; +import { EuiDescribedFormGroup, EuiFormRow, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { AuthenticatedUser } from '../../../common/model'; interface Props { user: AuthenticatedUser; diff --git a/x-pack/plugins/security/public/authentication/authentication_service.ts b/x-pack/plugins/security/public/authentication/authentication_service.ts index 23c45c88e563a1..2679bc20d6a7d9 100644 --- a/x-pack/plugins/security/public/authentication/authentication_service.ts +++ b/x-pack/plugins/security/public/authentication/authentication_service.ts @@ -23,7 +23,7 @@ export class AuthenticationService { return { async getCurrentUser() { return (await http.get('/internal/security/me', { - headers: { 'kbn-system-api': true }, + asSystemRequest: true, })) as AuthenticatedUser; }, }; diff --git a/x-pack/plugins/security/public/management/_index.scss b/x-pack/plugins/security/public/management/_index.scss new file mode 100644 index 00000000000000..5d419b53230799 --- /dev/null +++ b/x-pack/plugins/security/public/management/_index.scss @@ -0,0 +1,3 @@ +@import './roles/index'; +@import './users/index'; +@import './role_mappings/index'; diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.mock.ts b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.mock.ts new file mode 100644 index 00000000000000..2a45d497029f41 --- /dev/null +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.mock.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; + * you may not use this file except in compliance with the Elastic License. + */ + +export const apiKeysAPIClientMock = { + create: () => ({ + checkPrivileges: jest.fn(), + getApiKeys: jest.fn(), + invalidateApiKeys: jest.fn(), + }), +}; diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.test.ts b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.test.ts new file mode 100644 index 00000000000000..7d51a80459a6e9 --- /dev/null +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.test.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { APIKeysAPIClient } from './api_keys_api_client'; + +import { httpServiceMock } from '../../../../../../src/core/public/mocks'; + +describe('APIKeysAPIClient', () => { + it('checkPrivileges() queries correct endpoint', async () => { + const httpMock = httpServiceMock.createStartContract(); + + const mockResponse = Symbol('mockResponse'); + httpMock.get.mockResolvedValue(mockResponse); + + const apiClient = new APIKeysAPIClient(httpMock); + + await expect(apiClient.checkPrivileges()).resolves.toBe(mockResponse); + expect(httpMock.get).toHaveBeenCalledTimes(1); + expect(httpMock.get).toHaveBeenCalledWith('/internal/security/api_key/privileges'); + }); + + it('getApiKeys() queries correct endpoint', async () => { + const httpMock = httpServiceMock.createStartContract(); + + const mockResponse = Symbol('mockResponse'); + httpMock.get.mockResolvedValue(mockResponse); + + const apiClient = new APIKeysAPIClient(httpMock); + + await expect(apiClient.getApiKeys()).resolves.toBe(mockResponse); + expect(httpMock.get).toHaveBeenCalledTimes(1); + expect(httpMock.get).toHaveBeenCalledWith('/internal/security/api_key', { + query: { isAdmin: false }, + }); + httpMock.get.mockClear(); + + await expect(apiClient.getApiKeys(false)).resolves.toBe(mockResponse); + expect(httpMock.get).toHaveBeenCalledTimes(1); + expect(httpMock.get).toHaveBeenCalledWith('/internal/security/api_key', { + query: { isAdmin: false }, + }); + httpMock.get.mockClear(); + + await expect(apiClient.getApiKeys(true)).resolves.toBe(mockResponse); + expect(httpMock.get).toHaveBeenCalledTimes(1); + expect(httpMock.get).toHaveBeenCalledWith('/internal/security/api_key', { + query: { isAdmin: true }, + }); + }); + + it('invalidateApiKeys() queries correct endpoint', async () => { + const httpMock = httpServiceMock.createStartContract(); + + const mockResponse = Symbol('mockResponse'); + httpMock.post.mockResolvedValue(mockResponse); + + const apiClient = new APIKeysAPIClient(httpMock); + const mockAPIKeys = [ + { id: 'one', name: 'name-one' }, + { id: 'two', name: 'name-two' }, + ]; + + await expect(apiClient.invalidateApiKeys(mockAPIKeys)).resolves.toBe(mockResponse); + expect(httpMock.post).toHaveBeenCalledTimes(1); + expect(httpMock.post).toHaveBeenCalledWith('/internal/security/api_key/invalidate', { + body: JSON.stringify({ apiKeys: mockAPIKeys, isAdmin: false }), + }); + httpMock.post.mockClear(); + + await expect(apiClient.invalidateApiKeys(mockAPIKeys, false)).resolves.toBe(mockResponse); + expect(httpMock.post).toHaveBeenCalledTimes(1); + expect(httpMock.post).toHaveBeenCalledWith('/internal/security/api_key/invalidate', { + body: JSON.stringify({ apiKeys: mockAPIKeys, isAdmin: false }), + }); + httpMock.post.mockClear(); + + await expect(apiClient.invalidateApiKeys(mockAPIKeys, true)).resolves.toBe(mockResponse); + expect(httpMock.post).toHaveBeenCalledTimes(1); + expect(httpMock.post).toHaveBeenCalledWith('/internal/security/api_key/invalidate', { + body: JSON.stringify({ apiKeys: mockAPIKeys, isAdmin: true }), + }); + }); +}); diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.ts b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.ts new file mode 100644 index 00000000000000..372b1e56a73c47 --- /dev/null +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpStart } from 'src/core/public'; +import { ApiKey, ApiKeyToInvalidate } from '../../../common/model'; + +interface CheckPrivilegesResponse { + areApiKeysEnabled: boolean; + isAdmin: boolean; +} + +interface InvalidateApiKeysResponse { + itemsInvalidated: ApiKeyToInvalidate[]; + errors: any[]; +} + +interface GetApiKeysResponse { + apiKeys: ApiKey[]; +} + +const apiKeysUrl = '/internal/security/api_key'; + +export class APIKeysAPIClient { + constructor(private readonly http: HttpStart) {} + + public async checkPrivileges() { + return await this.http.get(`${apiKeysUrl}/privileges`); + } + + public async getApiKeys(isAdmin = false) { + return await this.http.get(apiKeysUrl, { query: { isAdmin } }); + } + + public async invalidateApiKeys(apiKeys: ApiKeyToInvalidate[], isAdmin = false) { + return await this.http.post(`${apiKeysUrl}/invalidate`, { + body: JSON.stringify({ apiKeys, isAdmin }), + }); + } +} diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/__snapshots__/api_keys_grid_page.test.tsx.snap similarity index 91% rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/__snapshots__/api_keys_grid_page.test.tsx.snap index c2537235c99f61..42fd4417e238b1 100644 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/__snapshots__/api_keys_grid_page.test.tsx.snap @@ -1,7 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ApiKeysGridPage renders a callout when API keys are not enabled 1`] = ` - +exports[`APIKeysGridPage renders a callout when API keys are not enabled 1`] = ` + Contact your system administrator and refer to the `; -exports[`ApiKeysGridPage renders permission denied if user does not have required permissions 1`] = ` +exports[`APIKeysGridPage renders permission denied if user does not have required permissions 1`] = ` ({ body: { statusCode: 403 } }); +const mock500 = () => ({ body: { error: 'Internal Server Error', message: '', statusCode: 500 } }); + +const waitForRender = async ( + wrapper: ReactWrapper, + condition: (wrapper: ReactWrapper) => boolean +) => { + return new Promise((resolve, reject) => { + const interval = setInterval(async () => { + await Promise.resolve(); + wrapper.update(); + if (condition(wrapper)) { + resolve(); + } + }, 10); + + setTimeout(() => { + clearInterval(interval); + reject(new Error('waitForRender timeout after 2000ms')); + }, 2000); + }); +}; + +describe('APIKeysGridPage', () => { + let apiClientMock: jest.Mocked>; + beforeEach(() => { + apiClientMock = apiKeysAPIClientMock.create(); + apiClientMock.checkPrivileges.mockResolvedValue({ + isAdmin: true, + areApiKeysEnabled: true, + }); + apiClientMock.getApiKeys.mockResolvedValue({ + apiKeys: [ + { + creation: 1571322182082, + expiration: 1571408582082, + id: '0QQZ2m0BO2XZwgJFuWTT', + invalidated: false, + name: 'my-api-key', + realm: 'reserved', + username: 'elastic', + }, + ], + }); + }); + + const getViewProperties = () => { + const { docLinks, notifications } = coreMock.createStart(); + return { + docLinks: new DocumentationLinksService(docLinks), + notifications, + apiKeysAPIClient: apiClientMock, + }; + }; + + it('renders a loading state when fetching API keys', async () => { + const wrapper = mountWithIntl(); + + expect(wrapper.find('[data-test-subj="apiKeysSectionLoading"]')).toHaveLength(1); + }); + + it('renders a callout when API keys are not enabled', async () => { + apiClientMock.checkPrivileges.mockResolvedValue({ + isAdmin: true, + areApiKeysEnabled: false, + }); + + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(NotEnabled).length > 0; + }); + + expect(wrapper.find(NotEnabled)).toMatchSnapshot(); + }); + + it('renders permission denied if user does not have required permissions', async () => { + apiClientMock.checkPrivileges.mockRejectedValue(mock403()); + + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(PermissionDenied).length > 0; + }); + + expect(wrapper.find(PermissionDenied)).toMatchSnapshot(); + }); + + it('renders error callout if error fetching API keys', async () => { + apiClientMock.getApiKeys.mockRejectedValue(mock500()); + + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(EuiCallOut).length > 0; + }); + + expect(wrapper.find('EuiCallOut[data-test-subj="apiKeysError"]')).toHaveLength(1); + }); + + describe('Admin view', () => { + let wrapper: ReactWrapper; + beforeEach(() => { + wrapper = mountWithIntl(); + }); + + it('renders a callout indicating the user is an administrator', async () => { + const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(calloutEl).length > 0; + }); + + expect(wrapper.find(calloutEl).text()).toEqual('You are an API Key administrator.'); + }); + + it('renders the correct description text', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(descriptionEl).text()).toEqual( + 'View and invalidate API keys. An API key sends requests on behalf of a user.' + ); + }); + }); + + describe('Non-admin view', () => { + let wrapper: ReactWrapper; + beforeEach(() => { + apiClientMock.checkPrivileges.mockResolvedValue({ + isAdmin: false, + areApiKeysEnabled: true, + }); + + wrapper = mountWithIntl(); + }); + + it('does NOT render a callout indicating the user is an administrator', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(calloutEl).length).toEqual(0); + }); + + it('renders the correct description text', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(descriptionEl).text()).toEqual( + 'View and invalidate your API keys. An API key sends requests on your behalf.' + ); + }); + }); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx similarity index 90% rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx index 92633a4b0ef57c..779a2302cfadf9 100644 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx @@ -27,16 +27,23 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment-timezone'; import _ from 'lodash'; -import { toastNotifications } from 'ui/notify'; +import { NotificationsStart } from 'src/core/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { SectionLoading } from '../../../../../../../../../src/plugins/es_ui_shared/public/components/section_loading'; -import { ApiKey, ApiKeyToInvalidate } from '../../../../../common/model'; -import { ApiKeysApi } from '../../../../lib/api_keys_api'; +import { SectionLoading } from '../../../../../../../src/plugins/es_ui_shared/public/components/section_loading'; +import { ApiKey, ApiKeyToInvalidate } from '../../../../common/model'; +import { APIKeysAPIClient } from '../api_keys_api_client'; +import { DocumentationLinksService } from '../documentation_links'; import { PermissionDenied } from './permission_denied'; import { EmptyPrompt } from './empty_prompt'; import { NotEnabled } from './not_enabled'; import { InvalidateProvider } from './invalidate_provider'; +interface Props { + notifications: NotificationsStart; + docLinks: DocumentationLinksService; + apiKeysAPIClient: PublicMethodsOf; +} + interface State { isLoadingApp: boolean; isLoadingTable: boolean; @@ -50,7 +57,7 @@ interface State { const DATE_FORMAT = 'MMMM Do YYYY HH:mm:ss'; -export class ApiKeysGridPage extends Component { +export class APIKeysGridPage extends Component { constructor(props: any) { super(props); this.state = { @@ -124,7 +131,7 @@ export class ApiKeysGridPage extends Component { if (!areApiKeysEnabled) { return ( - + ); } @@ -132,7 +139,7 @@ export class ApiKeysGridPage extends Component { if (!isLoadingTable && apiKeys && apiKeys.length === 0) { return ( - + ); } @@ -210,7 +217,11 @@ export class ApiKeysGridPage extends Component { const search: EuiInMemoryTableProps['search'] = { toolsLeft: selectedItems.length ? ( - + {invalidateApiKeyPrompt => { return ( { return ( - + {invalidateApiKeyPrompt => { return ( { private async checkPrivileges() { try { - const { isAdmin, areApiKeysEnabled } = await ApiKeysApi.checkPrivileges(); + const { isAdmin, areApiKeysEnabled } = await this.props.apiKeysAPIClient.checkPrivileges(); this.setState({ isAdmin, areApiKeysEnabled }); if (areApiKeysEnabled) { @@ -494,14 +509,11 @@ export class ApiKeysGridPage extends Component { if (_.get(e, 'body.statusCode') === 403) { this.setState({ permissionDenied: true, isLoadingApp: false }); } else { - toastNotifications.addDanger( - this.props.i18n.translate( - 'xpack.security.management.apiKeys.table.fetchingApiKeysErrorMessage', - { - defaultMessage: 'Error checking privileges: {message}', - values: { message: _.get(e, 'body.message', '') }, - } - ) + this.props.notifications.toasts.addDanger( + i18n.translate('xpack.security.management.apiKeys.table.fetchingApiKeysErrorMessage', { + defaultMessage: 'Error checking privileges: {message}', + values: { message: _.get(e, 'body.message', '') }, + }) ); } } @@ -520,7 +532,7 @@ export class ApiKeysGridPage extends Component { private loadApiKeys = async () => { try { const { isAdmin } = this.state; - const { apiKeys } = await ApiKeysApi.getApiKeys(isAdmin); + const { apiKeys } = await this.props.apiKeysAPIClient.getApiKeys(isAdmin); this.setState({ apiKeys }); } catch (e) { this.setState({ error: e }); diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/empty_prompt/empty_prompt.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx similarity index 89% rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/empty_prompt/empty_prompt.tsx rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx index 957ca7010a1a0a..7d762a1ceb04e0 100644 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/empty_prompt/empty_prompt.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx @@ -7,13 +7,14 @@ import React, { Fragment } from 'react'; import { EuiEmptyPrompt, EuiButton, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { documentationLinks } from '../../services/documentation_links'; +import { DocumentationLinksService } from '../../documentation_links'; interface Props { isAdmin: boolean; + docLinks: DocumentationLinksService; } -export const EmptyPrompt: React.FunctionComponent = ({ isAdmin }) => ( +export const EmptyPrompt: React.FunctionComponent = ({ isAdmin, docLinks }) => ( = ({ isAdmin }) => ( defaultMessage="You can create an {link} from Console." values={{ link: ( - + React.ReactElement; + notifications: NotificationsStart; + apiKeysAPIClient: PublicMethodsOf; } export type InvalidateApiKeys = ( @@ -23,7 +25,12 @@ export type InvalidateApiKeys = ( type OnSuccessCallback = (apiKeysInvalidated: ApiKeyToInvalidate[]) => void; -export const InvalidateProvider: React.FunctionComponent = ({ isAdmin, children }) => { +export const InvalidateProvider: React.FunctionComponent = ({ + isAdmin, + children, + notifications, + apiKeysAPIClient, +}) => { const [apiKeys, setApiKeys] = useState([]); const [isModalOpen, setIsModalOpen] = useState(false); const onSuccessCallback = useRef(null); @@ -48,7 +55,7 @@ export const InvalidateProvider: React.FunctionComponent = ({ isAdmin, ch let errors; try { - result = await ApiKeysApi.invalidateApiKeys(apiKeys, isAdmin); + result = await apiKeysAPIClient.invalidateApiKeys(apiKeys, isAdmin); } catch (e) { error = e; } @@ -77,7 +84,7 @@ export const InvalidateProvider: React.FunctionComponent = ({ isAdmin, ch values: { name: itemsInvalidated[0].name }, } ); - toastNotifications.addSuccess(successMessage); + notifications.toasts.addSuccess(successMessage); if (onSuccessCallback.current) { onSuccessCallback.current([...itemsInvalidated]); } @@ -106,7 +113,7 @@ export const InvalidateProvider: React.FunctionComponent = ({ isAdmin, ch values: { name: (errors && errors[0].name) || apiKeys[0].name }, } ); - toastNotifications.addDanger(errorMessage); + notifications.toasts.addDanger(errorMessage); } }; diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/index.ts b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/index.ts rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/not_enabled.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/not_enabled.tsx similarity index 78% rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/not_enabled.tsx rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/not_enabled.tsx index c419e15450c1e1..08fe5425577573 100644 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/not_enabled.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/not_enabled.tsx @@ -7,9 +7,13 @@ import React from 'react'; import { EuiCallOut, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { documentationLinks } from '../../services/documentation_links'; +import { DocumentationLinksService } from '../../documentation_links'; -export const NotEnabled: React.FunctionComponent = () => ( +interface Props { + docLinks: DocumentationLinksService; +} + +export const NotEnabled: React.FunctionComponent = ({ docLinks }) => ( ( defaultMessage="Contact your system administrator and refer to the {link} to enable API keys." values={{ link: ( - + ({ + APIKeysGridPage: (props: any) => `Page: ${JSON.stringify(props)}`, +})); + +import { apiKeysManagementApp } from './api_keys_management_app'; +import { coreMock } from '../../../../../../src/core/public/mocks'; + +describe('apiKeysManagementApp', () => { + it('create() returns proper management app descriptor', () => { + const { getStartServices } = coreMock.createSetup(); + + expect(apiKeysManagementApp.create({ getStartServices: getStartServices as any })) + .toMatchInlineSnapshot(` + Object { + "id": "api_keys", + "mount": [Function], + "order": 30, + "title": "API Keys", + } + `); + }); + + it('mount() works for the `grid` page', async () => { + const { getStartServices } = coreMock.createSetup(); + const container = document.createElement('div'); + + const setBreadcrumbs = jest.fn(); + const unmount = await apiKeysManagementApp + .create({ getStartServices: getStartServices as any }) + .mount({ + basePath: '/some-base-path', + element: container, + setBreadcrumbs, + }); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: '#/some-base-path', text: 'API Keys' }]); + expect(container).toMatchInlineSnapshot(` +
    + Page: {"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"apiKeysAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); +}); diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx new file mode 100644 index 00000000000000..35de732b84ce9b --- /dev/null +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { i18n } from '@kbn/i18n'; +import { CoreSetup } from 'src/core/public'; +import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public'; +import { PluginStartDependencies } from '../../plugin'; +import { APIKeysGridPage } from './api_keys_grid'; +import { APIKeysAPIClient } from './api_keys_api_client'; +import { DocumentationLinksService } from './documentation_links'; + +interface CreateParams { + getStartServices: CoreSetup['getStartServices']; +} + +export const apiKeysManagementApp = Object.freeze({ + id: 'api_keys', + create({ getStartServices }: CreateParams) { + return { + id: this.id, + order: 30, + title: i18n.translate('xpack.security.management.apiKeysTitle', { + defaultMessage: 'API Keys', + }), + async mount({ basePath, element, setBreadcrumbs }) { + const [{ docLinks, http, notifications, i18n: i18nStart }] = await getStartServices(); + setBreadcrumbs([ + { + text: i18n.translate('xpack.security.apiKeys.breadcrumb', { + defaultMessage: 'API Keys', + }), + href: `#${basePath}`, + }, + ]); + + render( + + + , + element + ); + + return () => { + unmountComponentAtNode(element); + }; + }, + } as RegisterManagementAppArgs; + }, +}); diff --git a/x-pack/plugins/security/public/management/api_keys/documentation_links.ts b/x-pack/plugins/security/public/management/api_keys/documentation_links.ts new file mode 100644 index 00000000000000..4165c2a2372c96 --- /dev/null +++ b/x-pack/plugins/security/public/management/api_keys/documentation_links.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DocLinksStart } from 'src/core/public'; + +export class DocumentationLinksService { + private readonly esDocBasePath: string; + + constructor(docLinks: DocLinksStart) { + this.esDocBasePath = `${docLinks.ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${docLinks.DOC_LINK_VERSION}/`; + } + + public getApiKeyServiceSettingsDocUrl() { + return `${this.esDocBasePath}security-settings.html#api-key-service-settings`; + } + + public getCreateApiKeyDocUrl() { + return `${this.esDocBasePath}security-api-create-api-key.html`; + } +} diff --git a/x-pack/plugins/security/public/management/api_keys/index.mock.ts b/x-pack/plugins/security/public/management/api_keys/index.mock.ts new file mode 100644 index 00000000000000..3c11cd6bb9c654 --- /dev/null +++ b/x-pack/plugins/security/public/management/api_keys/index.mock.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { apiKeysAPIClientMock } from './api_keys_api_client.mock'; diff --git a/x-pack/plugins/security/public/management/api_keys/index.ts b/x-pack/plugins/security/public/management/api_keys/index.ts new file mode 100644 index 00000000000000..e15da7d5eb4092 --- /dev/null +++ b/x-pack/plugins/security/public/management/api_keys/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { apiKeysManagementApp } from './api_keys_management_app'; diff --git a/x-pack/plugins/security/public/management/index.ts b/x-pack/plugins/security/public/management/index.ts new file mode 100644 index 00000000000000..e1a13d66e68836 --- /dev/null +++ b/x-pack/plugins/security/public/management/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ManagementService } from './management_service'; +export { UserAPIClient } from './users/user_api_client'; diff --git a/x-pack/plugins/security/public/management/management_service.test.ts b/x-pack/plugins/security/public/management/management_service.test.ts new file mode 100644 index 00000000000000..53c12ad7ab12c4 --- /dev/null +++ b/x-pack/plugins/security/public/management/management_service.test.ts @@ -0,0 +1,226 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { BehaviorSubject } from 'rxjs'; +import { ManagementApp } from '../../../../../src/plugins/management/public'; +import { SecurityLicenseFeatures } from '../../common/licensing/license_features'; +import { ManagementService } from './management_service'; +import { usersManagementApp } from './users'; + +import { coreMock } from '../../../../../src/core/public/mocks'; +import { licenseMock } from '../../common/licensing/index.mock'; +import { securityMock } from '../mocks'; +import { rolesManagementApp } from './roles'; +import { apiKeysManagementApp } from './api_keys'; +import { roleMappingsManagementApp } from './role_mappings'; + +describe('ManagementService', () => { + describe('setup()', () => { + it('properly registers security section and its applications', () => { + const { fatalErrors, getStartServices } = coreMock.createSetup(); + const { authc } = securityMock.createSetup(); + const license = licenseMock.create(); + + const mockSection = { registerApp: jest.fn() }; + const managementSetup = { + sections: { + getSection: jest.fn(), + getAllSections: jest.fn(), + register: jest.fn().mockReturnValue(mockSection), + }, + }; + + const service = new ManagementService(); + service.setup({ + getStartServices: getStartServices as any, + license, + fatalErrors, + authc, + management: managementSetup, + }); + + expect(managementSetup.sections.register).toHaveBeenCalledTimes(1); + expect(managementSetup.sections.register).toHaveBeenCalledWith({ + id: 'security', + title: 'Security', + order: 100, + euiIconType: 'securityApp', + }); + + expect(mockSection.registerApp).toHaveBeenCalledTimes(4); + expect(mockSection.registerApp).toHaveBeenCalledWith({ + id: 'users', + mount: expect.any(Function), + order: 10, + title: 'Users', + }); + expect(mockSection.registerApp).toHaveBeenCalledWith({ + id: 'roles', + mount: expect.any(Function), + order: 20, + title: 'Roles', + }); + expect(mockSection.registerApp).toHaveBeenCalledWith({ + id: 'api_keys', + mount: expect.any(Function), + order: 30, + title: 'API Keys', + }); + expect(mockSection.registerApp).toHaveBeenCalledWith({ + id: 'role_mappings', + mount: expect.any(Function), + order: 40, + title: 'Role Mappings', + }); + }); + }); + + describe('start()', () => { + function startService(initialFeatures: Partial) { + const { fatalErrors, getStartServices } = coreMock.createSetup(); + + const licenseSubject = new BehaviorSubject( + (initialFeatures as unknown) as SecurityLicenseFeatures + ); + const license = licenseMock.create(); + license.features$ = licenseSubject; + + const service = new ManagementService(); + service.setup({ + getStartServices: getStartServices as any, + license, + fatalErrors, + authc: securityMock.createSetup().authc, + management: { + sections: { + getSection: jest.fn(), + getAllSections: jest.fn(), + register: jest.fn().mockReturnValue({ registerApp: jest.fn() }), + }, + }, + }); + + const getMockedApp = () => { + // All apps are enabled by default. + let enabled = true; + return ({ + get enabled() { + return enabled; + }, + enable: jest.fn().mockImplementation(() => { + enabled = true; + }), + disable: jest.fn().mockImplementation(() => { + enabled = false; + }), + } as unknown) as jest.Mocked; + }; + const mockApps = new Map>([ + [usersManagementApp.id, getMockedApp()], + [rolesManagementApp.id, getMockedApp()], + [apiKeysManagementApp.id, getMockedApp()], + [roleMappingsManagementApp.id, getMockedApp()], + ] as Array<[string, jest.Mocked]>); + + service.start({ + management: { + sections: { + getSection: jest + .fn() + .mockReturnValue({ getApp: jest.fn().mockImplementation(id => mockApps.get(id)) }), + getAllSections: jest.fn(), + navigateToApp: jest.fn(), + }, + legacy: undefined, + }, + }); + + return { + mockApps, + updateFeatures(features: Partial) { + licenseSubject.next((features as unknown) as SecurityLicenseFeatures); + }, + }; + } + + it('does not do anything if `showLinks` is `true` at `start`', () => { + const { mockApps } = startService({ showLinks: true, showRoleMappingsManagement: true }); + for (const [, mockApp] of mockApps) { + expect(mockApp.enable).not.toHaveBeenCalled(); + expect(mockApp.disable).not.toHaveBeenCalled(); + expect(mockApp.enabled).toBe(true); + } + }); + + it('disables all apps if `showLinks` is `false` at `start`', () => { + const { mockApps } = startService({ showLinks: false, showRoleMappingsManagement: true }); + for (const [, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(false); + } + }); + + it('disables only Role Mappings app if `showLinks` is `true`, but `showRoleMappingsManagement` is `false` at `start`', () => { + const { mockApps } = startService({ showLinks: true, showRoleMappingsManagement: false }); + for (const [appId, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(appId !== roleMappingsManagementApp.id); + } + }); + + it('apps are disabled if `showLinks` changes after `start`', () => { + const { mockApps, updateFeatures } = startService({ + showLinks: true, + showRoleMappingsManagement: true, + }); + for (const [, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(true); + } + + updateFeatures({ showLinks: false, showRoleMappingsManagement: false }); + + for (const [, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(false); + } + }); + + it('role mappings app is disabled if `showRoleMappingsManagement` changes after `start`', () => { + const { mockApps, updateFeatures } = startService({ + showLinks: true, + showRoleMappingsManagement: true, + }); + for (const [, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(true); + } + + updateFeatures({ showLinks: true, showRoleMappingsManagement: false }); + + for (const [appId, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(appId !== roleMappingsManagementApp.id); + } + }); + + it('apps are re-enabled if `showLinks` eventually transitions to `true` after `start`', () => { + const { mockApps, updateFeatures } = startService({ + showLinks: true, + showRoleMappingsManagement: true, + }); + for (const [, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(true); + } + + updateFeatures({ showLinks: false, showRoleMappingsManagement: false }); + + for (const [, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(false); + } + + updateFeatures({ showLinks: true, showRoleMappingsManagement: true }); + + for (const [, mockApp] of mockApps) { + expect(mockApp.enabled).toBe(true); + } + }); + }); +}); diff --git a/x-pack/plugins/security/public/management/management_service.ts b/x-pack/plugins/security/public/management/management_service.ts new file mode 100644 index 00000000000000..5ad3681590fbf6 --- /dev/null +++ b/x-pack/plugins/security/public/management/management_service.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Subscription } from 'rxjs'; +import { i18n } from '@kbn/i18n'; +import { CoreSetup, FatalErrorsSetup } from 'src/core/public'; +import { + ManagementApp, + ManagementSetup, + ManagementStart, +} from '../../../../../src/plugins/management/public'; +import { SecurityLicense } from '../../common/licensing'; +import { AuthenticationServiceSetup } from '../authentication'; +import { PluginStartDependencies } from '../plugin'; +import { apiKeysManagementApp } from './api_keys'; +import { roleMappingsManagementApp } from './role_mappings'; +import { rolesManagementApp } from './roles'; +import { usersManagementApp } from './users'; + +interface SetupParams { + management: ManagementSetup; + license: SecurityLicense; + authc: AuthenticationServiceSetup; + fatalErrors: FatalErrorsSetup; + getStartServices: CoreSetup['getStartServices']; +} + +interface StartParams { + management: ManagementStart; +} + +export class ManagementService { + private license!: SecurityLicense; + private licenseFeaturesSubscription?: Subscription; + + setup({ getStartServices, management, authc, license, fatalErrors }: SetupParams) { + this.license = license; + + const securitySection = management.sections.register({ + id: 'security', + title: i18n.translate('xpack.security.management.securityTitle', { + defaultMessage: 'Security', + }), + order: 100, + euiIconType: 'securityApp', + }); + + securitySection.registerApp(usersManagementApp.create({ authc, getStartServices })); + securitySection.registerApp( + rolesManagementApp.create({ fatalErrors, license, getStartServices }) + ); + securitySection.registerApp(apiKeysManagementApp.create({ getStartServices })); + securitySection.registerApp(roleMappingsManagementApp.create({ getStartServices })); + } + + start({ management }: StartParams) { + this.licenseFeaturesSubscription = this.license.features$.subscribe(async features => { + const securitySection = management.sections.getSection('security')!; + + const securityManagementAppsStatuses: Array<[ManagementApp, boolean]> = [ + [securitySection.getApp(usersManagementApp.id)!, features.showLinks], + [securitySection.getApp(rolesManagementApp.id)!, features.showLinks], + [securitySection.getApp(apiKeysManagementApp.id)!, features.showLinks], + [ + securitySection.getApp(roleMappingsManagementApp.id)!, + features.showLinks && features.showRoleMappingsManagement, + ], + ]; + + // Iterate over all registered apps and update their enable status depending on the available + // license features. + for (const [app, enableStatus] of securityManagementAppsStatuses) { + if (app.enabled === enableStatus) { + continue; + } + + if (enableStatus) { + app.enable(); + } else { + app.disable(); + } + } + }); + } + + stop() { + if (this.licenseFeaturesSubscription) { + this.licenseFeaturesSubscription.unsubscribe(); + this.licenseFeaturesSubscription = undefined; + } + } +} diff --git a/x-pack/plugins/security/public/management/management_urls.ts b/x-pack/plugins/security/public/management/management_urls.ts new file mode 100644 index 00000000000000..0d4e3fc920bdba --- /dev/null +++ b/x-pack/plugins/security/public/management/management_urls.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +const MANAGEMENT_PATH = '/management'; +const SECURITY_PATH = `${MANAGEMENT_PATH}/security`; +export const ROLES_PATH = `${SECURITY_PATH}/roles`; +export const EDIT_ROLES_PATH = `${ROLES_PATH}/edit`; +export const CLONE_ROLES_PATH = `${ROLES_PATH}/clone`; +export const USERS_PATH = `${SECURITY_PATH}/users`; +export const EDIT_USERS_PATH = `${USERS_PATH}/edit`; +export const ROLE_MAPPINGS_PATH = `${SECURITY_PATH}/role_mappings`; +const CREATE_ROLE_MAPPING_PATH = `${ROLE_MAPPINGS_PATH}/edit`; + +export const getEditRoleHref = (roleName: string) => + `#${ROLES_PATH}/edit/${encodeURIComponent(roleName)}`; + +export const getCreateRoleMappingHref = () => `#${CREATE_ROLE_MAPPING_PATH}`; + +export const getEditRoleMappingHref = (roleMappingName: string) => + `#${CREATE_ROLE_MAPPING_PATH}/${encodeURIComponent(roleMappingName)}`; diff --git a/x-pack/plugins/security/public/management/role_mappings/_index.scss b/x-pack/plugins/security/public/management/role_mappings/_index.scss new file mode 100644 index 00000000000000..bae6effcd2ec56 --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/_index.scss @@ -0,0 +1 @@ +@import './edit_role_mapping/index'; diff --git a/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.test.tsx b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.test.tsx new file mode 100644 index 00000000000000..69142b1ad610e6 --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.test.tsx @@ -0,0 +1,291 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiConfirmModal } from '@elastic/eui'; +import { act } from '@testing-library/react'; +import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; +import { findTestSubject } from 'test_utils/find_test_subject'; +import { RoleMapping } from '../../../../../common/model'; +import { DeleteProvider } from '.'; + +import { roleMappingsAPIClientMock } from '../../index.mock'; +import { coreMock } from '../../../../../../../../src/core/public/mocks'; + +describe('DeleteProvider', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('allows a single role mapping to be deleted', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.deleteRoleMappings.mockResolvedValue([{ name: 'delete-me', success: true }]); + + const notifications = coreMock.createStart().notifications; + + const props = { + roleMappingsAPI, + notifications, + }; + + const roleMappingsToDelete = [ + { + name: 'delete-me', + }, + ] as RoleMapping[]; + + const onSuccess = jest.fn(); + + const wrapper = mountWithIntl( + + {onDelete => ( + + )} + + ); + + await act(async () => { + wrapper.find('#invoker').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + const { title, confirmButtonText } = wrapper.find(EuiConfirmModal).props(); + expect(title).toMatchInlineSnapshot(`"Delete role mapping 'delete-me'?"`); + expect(confirmButtonText).toMatchInlineSnapshot(`"Delete role mapping"`); + + await act(async () => { + findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['delete-me']); + + expect(notifications.toasts.addError).toHaveBeenCalledTimes(0); + expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(0); + expect(notifications.toasts.addSuccess).toHaveBeenCalledTimes(1); + expect(notifications.toasts.addSuccess.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "data-test-subj": "deletedRoleMappingSuccessToast", + "title": "Deleted role mapping 'delete-me'", + }, + ] + `); + }); + + it('allows multiple role mappings to be deleted', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.deleteRoleMappings.mockResolvedValue([ + { + name: 'delete-me', + success: true, + }, + { + name: 'delete-me-too', + success: true, + }, + ]); + + const notifications = coreMock.createStart().notifications; + + const props = { + roleMappingsAPI, + notifications, + }; + + const roleMappingsToDelete = [ + { + name: 'delete-me', + }, + { + name: 'delete-me-too', + }, + ] as RoleMapping[]; + + const onSuccess = jest.fn(); + + const wrapper = mountWithIntl( + + {onDelete => ( + + )} + + ); + + await act(async () => { + wrapper.find('#invoker').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + const { title, confirmButtonText } = wrapper.find(EuiConfirmModal).props(); + expect(title).toMatchInlineSnapshot(`"Delete 2 role mappings?"`); + expect(confirmButtonText).toMatchInlineSnapshot(`"Delete role mappings"`); + + await act(async () => { + findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith([ + 'delete-me', + 'delete-me-too', + ]); + + expect(notifications.toasts.addError).toHaveBeenCalledTimes(0); + expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(0); + expect(notifications.toasts.addSuccess).toHaveBeenCalledTimes(1); + expect(notifications.toasts.addSuccess.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "data-test-subj": "deletedRoleMappingSuccessToast", + "title": "Deleted 2 role mappings", + }, + ] + `); + }); + + it('handles mixed success/failure conditions', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.deleteRoleMappings.mockResolvedValue([ + { + name: 'delete-me', + success: true, + }, + { + name: 'i-wont-work', + success: false, + error: new Error('something went wrong. sad.'), + }, + ]); + + const notifications = coreMock.createStart().notifications; + + const props = { + roleMappingsAPI, + notifications, + }; + + const roleMappingsToDelete = [ + { + name: 'delete-me', + }, + { + name: 'i-wont-work', + }, + ] as RoleMapping[]; + + const onSuccess = jest.fn(); + + const wrapper = mountWithIntl( + + {onDelete => ( + + )} + + ); + + await act(async () => { + wrapper.find('#invoker').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + await act(async () => { + findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith([ + 'delete-me', + 'i-wont-work', + ]); + + expect(notifications.toasts.addError).toHaveBeenCalledTimes(0); + expect(notifications.toasts.addSuccess).toHaveBeenCalledTimes(1); + expect(notifications.toasts.addSuccess.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "data-test-subj": "deletedRoleMappingSuccessToast", + "title": "Deleted role mapping 'delete-me'", + }, + ] + `); + + expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(1); + expect(notifications.toasts.addDanger.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "Error deleting role mapping 'i-wont-work'", + ] + `); + }); + + it('handles errors calling the API', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.deleteRoleMappings.mockRejectedValue(new Error('AHHHHH')); + + const notifications = coreMock.createStart().notifications; + const props = { + roleMappingsAPI, + notifications, + }; + + const roleMappingsToDelete = [ + { + name: 'delete-me', + }, + ] as RoleMapping[]; + + const onSuccess = jest.fn(); + + const wrapper = mountWithIntl( + + {onDelete => ( + + )} + + ); + + await act(async () => { + wrapper.find('#invoker').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + await act(async () => { + findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['delete-me']); + + expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(0); + expect(notifications.toasts.addSuccess).toHaveBeenCalledTimes(0); + + expect(notifications.toasts.addError).toHaveBeenCalledTimes(1); + expect(notifications.toasts.addError.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + [Error: AHHHHH], + Object { + "title": "Error deleting role mappings", + }, + ] + `); + }); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.tsx b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx similarity index 93% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.tsx rename to x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx index 2072cedeab4628..860fe22cb8032c 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx @@ -6,13 +6,14 @@ import React, { Fragment, useRef, useState, ReactElement } from 'react'; import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; -import { toastNotifications } from 'ui/notify'; import { i18n } from '@kbn/i18n'; -import { RoleMapping } from '../../../../../../common/model'; -import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api'; +import { NotificationsStart } from 'src/core/public'; +import { RoleMapping } from '../../../../../common/model'; +import { RoleMappingsAPIClient } from '../../role_mappings_api_client'; interface Props { - roleMappingsAPI: RoleMappingsAPI; + roleMappingsAPI: PublicMethodsOf; + notifications: NotificationsStart; children: (deleteMappings: DeleteRoleMappings) => ReactElement; } @@ -23,7 +24,11 @@ export type DeleteRoleMappings = ( type OnSuccessCallback = (deletedRoleMappings: string[]) => void; -export const DeleteProvider: React.FunctionComponent = ({ roleMappingsAPI, children }) => { +export const DeleteProvider: React.FunctionComponent = ({ + roleMappingsAPI, + children, + notifications, +}) => { const [roleMappings, setRoleMappings] = useState([]); const [isModalOpen, setIsModalOpen] = useState(false); const [isDeleteInProgress, setIsDeleteInProgress] = useState(false); @@ -55,7 +60,7 @@ export const DeleteProvider: React.FunctionComponent = ({ roleMappingsAPI try { result = await roleMappingsAPI.deleteRoleMappings(roleMappings.map(rm => rm.name)); } catch (e) { - toastNotifications.addError(e, { + notifications.toasts.addError(e, { title: i18n.translate( 'xpack.security.management.roleMappings.deleteRoleMapping.unknownError', { @@ -92,7 +97,7 @@ export const DeleteProvider: React.FunctionComponent = ({ roleMappingsAPI values: { name: successfulDeletes[0].name }, } ); - toastNotifications.addSuccess({ + notifications.toasts.addSuccess({ title: successMessage, 'data-test-subj': 'deletedRoleMappingSuccessToast', }); @@ -121,7 +126,7 @@ export const DeleteProvider: React.FunctionComponent = ({ roleMappingsAPI values: { name: erroredDeletes[0].name }, } ); - toastNotifications.addDanger(errorMessage); + notifications.toasts.addDanger(errorMessage); } }; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/index.ts b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/index.ts rename to x-pack/plugins/security/public/management/role_mappings/components/delete_provider/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/index.ts b/x-pack/plugins/security/public/management/role_mappings/components/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/index.ts rename to x-pack/plugins/security/public/management/role_mappings/components/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/index.ts b/x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/index.ts rename to x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx b/x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx similarity index 78% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx rename to x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx index 969832b3ecbae1..5e14b0c179bfd7 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx @@ -7,9 +7,13 @@ import React from 'react'; import { EuiCallOut, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { documentationLinks } from '../../services/documentation_links'; +import { DocumentationLinksService } from '../../documentation_links'; -export const NoCompatibleRealms: React.FunctionComponent = () => ( +interface Props { + docLinks: DocumentationLinksService; +} + +export const NoCompatibleRealms: React.FunctionComponent = ({ docLinks }: Props) => ( ( defaultMessage="Role mappings will not be applied to any users. Contact your system administrator and refer to the {link} for more information." values={{ link: ( - + { + let rolesAPI: PublicMethodsOf; + beforeEach(() => { + rolesAPI = rolesAPIClientMock.create(); + (rolesAPI as jest.Mocked).getRoles.mockResolvedValue([ + { name: 'foo_role' }, + { name: 'bar role' }, + ] as Role[]); + }); + + it('allows a role mapping to be created', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.saveRoleMapping.mockResolvedValue(null); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + canUseInlineScripts: true, + canUseStoredScripts: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + + await nextTick(); + wrapper.update(); + + findTestSubject(wrapper, 'roleMappingFormNameInput').simulate('change', { + target: { value: 'my-role-mapping' }, + }); + + (wrapper + .find(EuiComboBox) + .filter('[data-test-subj="roleMappingFormRoleComboBox"]') + .props() as any).onChange([{ label: 'foo_role' }]); + + findTestSubject(wrapper, 'roleMappingsAddRuleButton').simulate('click'); + + findTestSubject(wrapper, 'saveRoleMappingButton').simulate('click'); + + expect(roleMappingsAPI.saveRoleMapping).toHaveBeenCalledWith({ + name: 'my-role-mapping', + enabled: true, + roles: ['foo_role'], + role_templates: [], + rules: { + all: [{ field: { username: '*' } }], + }, + metadata: {}, + }); + }); + + it('allows a role mapping to be updated', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.saveRoleMapping.mockResolvedValue(null); + roleMappingsAPI.getRoleMapping.mockResolvedValue({ + name: 'foo', + role_templates: [ + { + template: { id: 'foo' }, + }, + ], + enabled: true, + rules: { + any: [{ field: { 'metadata.someCustomOption': [false, true, 'asdf'] } }], + }, + metadata: { + foo: 'bar', + bar: 'baz', + }, + }); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + canUseInlineScripts: true, + canUseStoredScripts: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + + await nextTick(); + wrapper.update(); + + findTestSubject(wrapper, 'switchToRolesButton').simulate('click'); + + (wrapper + .find(EuiComboBox) + .filter('[data-test-subj="roleMappingFormRoleComboBox"]') + .props() as any).onChange([{ label: 'foo_role' }]); + + findTestSubject(wrapper, 'roleMappingsAddRuleButton').simulate('click'); + wrapper.find('button[id="addRuleOption"]').simulate('click'); + + findTestSubject(wrapper, 'saveRoleMappingButton').simulate('click'); + + expect(roleMappingsAPI.saveRoleMapping).toHaveBeenCalledWith({ + name: 'foo', + enabled: true, + roles: ['foo_role'], + role_templates: [], + rules: { + any: [ + { field: { 'metadata.someCustomOption': [false, true, 'asdf'] } }, + { field: { username: '*' } }, + ], + }, + metadata: { + foo: 'bar', + bar: 'baz', + }, + }); + }); + + it('renders a permission denied message when unauthorized to manage role mappings', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: false, + hasCompatibleRealms: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + expect(wrapper.find(SectionLoading)).toHaveLength(1); + expect(wrapper.find(PermissionDenied)).toHaveLength(0); + + await nextTick(); + wrapper.update(); + + expect(wrapper.find(SectionLoading)).toHaveLength(0); + expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); + expect(wrapper.find(PermissionDenied)).toHaveLength(1); + }); + + it('renders a warning when there are no compatible realms enabled', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: false, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + expect(wrapper.find(SectionLoading)).toHaveLength(1); + expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); + + await nextTick(); + wrapper.update(); + + expect(wrapper.find(SectionLoading)).toHaveLength(0); + expect(wrapper.find(NoCompatibleRealms)).toHaveLength(1); + }); + + it('renders a warning when editing a mapping with a stored role template, when stored scripts are disabled', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMapping.mockResolvedValue({ + name: 'foo', + role_templates: [ + { + template: { id: 'foo' }, + }, + ], + enabled: true, + rules: { + field: { username: '*' }, + }, + }); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + canUseInlineScripts: true, + canUseStoredScripts: false, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + + expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0); + expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0); + + await nextTick(); + wrapper.update(); + + expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0); + expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(1); + }); + + it('renders a warning when editing a mapping with an inline role template, when inline scripts are disabled', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMapping.mockResolvedValue({ + name: 'foo', + role_templates: [ + { + template: { source: 'foo' }, + }, + ], + enabled: true, + rules: { + field: { username: '*' }, + }, + }); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + canUseInlineScripts: false, + canUseStoredScripts: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + + expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0); + expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0); + + await nextTick(); + wrapper.update(); + + expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(1); + expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0); + }); + + it('renders the visual editor by default for simple rule sets', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMapping.mockResolvedValue({ + name: 'foo', + roles: ['superuser'], + enabled: true, + rules: { + all: [ + { + field: { + username: '*', + }, + }, + { + field: { + dn: null, + }, + }, + { + field: { + realm: ['ldap', 'pki', null, 12], + }, + }, + ], + }, + }); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + canUseInlineScripts: true, + canUseStoredScripts: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + + await nextTick(); + wrapper.update(); + + expect(wrapper.find(VisualRuleEditor)).toHaveLength(1); + expect(wrapper.find(JSONRuleEditor)).toHaveLength(0); + }); + + it('renders the JSON editor by default for complex rule sets', async () => { + const createRule = (depth: number): Record => { + if (depth > 0) { + const rule = { + all: [ + { + field: { + username: '*', + }, + }, + ], + } as Record; + + const subRule = createRule(depth - 1); + if (subRule) { + rule.all.push(subRule); + } + + return rule; + } + return null as any; + }; + + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMapping.mockResolvedValue({ + name: 'foo', + roles: ['superuser'], + enabled: true, + rules: createRule(10), + }); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + canUseInlineScripts: true, + canUseStoredScripts: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + + await nextTick(); + wrapper.update(); + + expect(wrapper.find(VisualRuleEditor)).toHaveLength(0); + expect(wrapper.find(JSONRuleEditor)).toHaveLength(1); + }); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx similarity index 87% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx index b8a75a4ad9fdf7..142b53cbb50f29 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx @@ -19,20 +19,21 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { toastNotifications } from 'ui/notify'; -import { RoleMapping } from '../../../../../../common/model'; -import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api'; +import { NotificationsStart } from 'src/core/public'; +import { RoleMapping } from '../../../../common/model'; import { RuleEditorPanel } from './rule_editor_panel'; import { NoCompatibleRealms, PermissionDenied, DeleteProvider, SectionLoading, -} from '../../components'; -import { ROLE_MAPPINGS_PATH } from '../../../management_urls'; -import { validateRoleMappingForSave } from '../services/role_mapping_validation'; +} from '../components'; +import { RolesAPIClient } from '../../roles'; +import { ROLE_MAPPINGS_PATH } from '../../management_urls'; +import { validateRoleMappingForSave } from './services/role_mapping_validation'; import { MappingInfoPanel } from './mapping_info_panel'; -import { documentationLinks } from '../../services/documentation_links'; +import { DocumentationLinksService } from '../documentation_links'; +import { RoleMappingsAPIClient } from '../role_mappings_api_client'; interface State { loadState: 'loading' | 'permissionDenied' | 'ready' | 'saveInProgress'; @@ -50,7 +51,10 @@ interface State { interface Props { name?: string; - roleMappingsAPI: RoleMappingsAPI; + roleMappingsAPI: PublicMethodsOf; + rolesAPIClient: PublicMethodsOf; + notifications: NotificationsStart; + docLinks: DocumentationLinksService; } export class EditRoleMappingPage extends Component { @@ -74,6 +78,12 @@ export class EditRoleMappingPage extends Component { this.loadAppData(); } + public async componentDidUpdate(prevProps: Props) { + if (prevProps.name !== this.props.name) { + await this.loadAppData(); + } + } + public render() { const { loadState } = this.state; @@ -101,6 +111,8 @@ export class EditRoleMappingPage extends Component { validateForm={this.state.validateForm} canUseInlineScripts={this.state.canUseInlineScripts} canUseStoredScripts={this.state.canUseStoredScripts} + rolesAPIClient={this.props.rolesAPIClient} + docLinks={this.props.docLinks} /> { }, }) } + docLinks={this.props.docLinks} /> {this.getFormButtons()} @@ -149,7 +162,7 @@ export class EditRoleMappingPage extends Component { values={{ learnMoreLink: ( @@ -166,7 +179,7 @@ export class EditRoleMappingPage extends Component { {!this.state.hasCompatibleRealms && ( <> - + )} @@ -201,7 +214,10 @@ export class EditRoleMappingPage extends Component { {this.editingExistingRoleMapping() && ( - + {deleteRoleMappingsPrompt => { return ( { this.props.roleMappingsAPI .saveRoleMapping(this.state.roleMapping) .then(() => { - toastNotifications.addSuccess({ + this.props.notifications.toasts.addSuccess({ title: i18n.translate('xpack.security.management.editRoleMapping.saveSuccess', { defaultMessage: `Saved role mapping '{roleMappingName}'`, values: { @@ -264,7 +280,7 @@ export class EditRoleMappingPage extends Component { this.backToRoleMappingsList(); }) .catch(e => { - toastNotifications.addError(e, { + this.props.notifications.toasts.addError(e, { title: i18n.translate('xpack.security.management.editRoleMapping.saveError', { defaultMessage: `Error saving role mapping`, }), @@ -312,7 +328,7 @@ export class EditRoleMappingPage extends Component { roleMapping, }); } catch (e) { - toastNotifications.addDanger({ + this.props.notifications.toasts.addDanger({ title: i18n.translate( 'xpack.security.management.editRoleMapping.table.fetchingRoleMappingsErrorMessage', { diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/index.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/index.ts rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/index.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/index.ts rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx similarity index 82% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.test.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx index d821b33ace6a7b..9b62ca27ca569c 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx @@ -6,21 +6,27 @@ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { MappingInfoPanel } from '.'; -import { RoleMapping } from '../../../../../../../common/model'; import { findTestSubject } from 'test_utils/find_test_subject'; +import { Role, RoleMapping } from '../../../../../common/model'; +import { RolesAPIClient } from '../../../roles'; +import { DocumentationLinksService } from '../../documentation_links'; import { RoleSelector } from '../role_selector'; import { RoleTemplateEditor } from '../role_selector/role_template_editor'; +import { MappingInfoPanel } from '.'; -jest.mock('../../../../../../lib/roles_api', () => { - return { - RolesApi: { - getRoles: () => Promise.resolve([{ name: 'foo_role' }, { name: 'bar role' }]), - }, - }; -}); +import { rolesAPIClientMock } from '../../../roles/roles_api_client.mock'; +import { coreMock } from '../../../../../../../../src/core/public/mocks'; describe('MappingInfoPanel', () => { + let rolesAPI: PublicMethodsOf; + beforeEach(() => { + rolesAPI = rolesAPIClientMock.create(); + (rolesAPI as jest.Mocked).getRoles.mockResolvedValue([ + { name: 'foo_role' }, + { name: 'bar role' }, + ] as Role[]); + }); + it('renders when creating a role mapping, default to the "roles" view', () => { const props = { roleMapping: { @@ -32,6 +38,8 @@ describe('MappingInfoPanel', () => { metadata: {}, } as RoleMapping, mode: 'create', + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), + rolesAPIClient: rolesAPI, } as MappingInfoPanel['props']; const wrapper = mountWithIntl(); @@ -77,6 +85,8 @@ describe('MappingInfoPanel', () => { metadata: {}, } as RoleMapping, mode: 'edit', + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), + rolesAPIClient: rolesAPI, } as MappingInfoPanel['props']; const wrapper = mountWithIntl(); @@ -101,6 +111,8 @@ describe('MappingInfoPanel', () => { canUseInlineScripts: true, canUseStoredScripts: false, validateForm: false, + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), + rolesAPIClient: rolesAPI, }; const wrapper = mountWithIntl(); @@ -140,6 +152,8 @@ describe('MappingInfoPanel', () => { canUseInlineScripts: false, canUseStoredScripts: true, validateForm: false, + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), + rolesAPIClient: rolesAPI, }; const wrapper = mountWithIntl(); @@ -179,6 +193,8 @@ describe('MappingInfoPanel', () => { canUseInlineScripts: false, canUseStoredScripts: false, validateForm: false, + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), + rolesAPIClient: rolesAPI, }; const wrapper = mountWithIntl(); @@ -202,6 +218,8 @@ describe('MappingInfoPanel', () => { metadata: {}, } as RoleMapping, mode: 'edit', + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), + rolesAPIClient: rolesAPI, } as MappingInfoPanel['props']; const wrapper = mountWithIntl(); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx index a02b4fc1709f02..02af6bfbafa7e0 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx @@ -18,14 +18,15 @@ import { EuiSwitch, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { RoleMapping } from '../../../../../../../common/model'; +import { RoleMapping } from '../../../../../common/model'; +import { RolesAPIClient } from '../../../roles'; import { validateRoleMappingName, validateRoleMappingRoles, validateRoleMappingRoleTemplates, -} from '../../services/role_mapping_validation'; +} from '../services/role_mapping_validation'; import { RoleSelector } from '../role_selector'; -import { documentationLinks } from '../../../services/documentation_links'; +import { DocumentationLinksService } from '../../documentation_links'; interface Props { roleMapping: RoleMapping; @@ -34,6 +35,8 @@ interface Props { validateForm: boolean; canUseInlineScripts: boolean; canUseStoredScripts: boolean; + rolesAPIClient: PublicMethodsOf; + docLinks: DocumentationLinksService; } interface State { @@ -163,6 +166,7 @@ export class MappingInfoPanel extends Component { > { defaultMessage="Create templates that describe the roles to assign to your users." />{' '} @@ -230,6 +234,7 @@ export class MappingInfoPanel extends Component { > { - return { - RolesApi: { - getRoles: () => Promise.resolve([{ name: 'foo_role' }, { name: 'bar role' }]), - }, - }; -}); +import { RolesAPIClient } from '../../../roles'; +import { rolesAPIClientMock } from '../../../roles/roles_api_client.mock'; describe('RoleSelector', () => { + let rolesAPI: PublicMethodsOf; + beforeEach(() => { + rolesAPI = rolesAPIClientMock.create(); + (rolesAPI as jest.Mocked).getRoles.mockResolvedValue([ + { name: 'foo_role' }, + { name: 'bar role' }, + ] as Role[]); + }); + it('allows roles to be selected, removing any previously selected role templates', () => { const props = { roleMapping: { @@ -36,6 +39,7 @@ describe('RoleSelector', () => { canUseInlineScripts: true, onChange: jest.fn(), mode: 'roles', + rolesAPIClient: rolesAPI, } as RoleSelector['props']; const wrapper = mountWithIntl(); @@ -57,6 +61,7 @@ describe('RoleSelector', () => { canUseInlineScripts: true, onChange: jest.fn(), mode: 'templates', + rolesAPIClient: rolesAPI, } as RoleSelector['props']; const wrapper = mountWithIntl(); @@ -87,6 +92,7 @@ describe('RoleSelector', () => { canUseInlineScripts: true, onChange: jest.fn(), mode: 'templates', + rolesAPIClient: rolesAPI, } as RoleSelector['props']; const wrapper = mountWithIntl(); @@ -122,6 +128,7 @@ describe('RoleSelector', () => { canUseInlineScripts: true, onChange: jest.fn(), mode: 'templates', + rolesAPIClient: rolesAPI, } as RoleSelector['props']; const wrapper = mountWithIntl(); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_selector.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx similarity index 94% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_selector.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx index 6b92d6b4907f16..992c2741ae93ee 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_selector.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx @@ -7,12 +7,13 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiComboBox, EuiFormRow, EuiHorizontalRule } from '@elastic/eui'; -import { RoleMapping, Role } from '../../../../../../../common/model'; -import { RolesApi } from '../../../../../../lib/roles_api'; +import { RoleMapping, Role } from '../../../../../common/model'; +import { RolesAPIClient } from '../../../roles'; import { AddRoleTemplateButton } from './add_role_template_button'; import { RoleTemplateEditor } from './role_template_editor'; interface Props { + rolesAPIClient: PublicMethodsOf; roleMapping: RoleMapping; canUseInlineScripts: boolean; canUseStoredScripts: boolean; @@ -32,7 +33,7 @@ export class RoleSelector extends React.Component { } public async componentDidMount() { - const roles = await RolesApi.getRoles(); + const roles = await this.props.rolesAPIClient.getRoles(); this.setState({ roles }); } diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.test.tsx similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.test.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.test.tsx diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.tsx similarity index 98% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.tsx index 4b8d34d2719960..d79651d7b9cd6d 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.tsx @@ -18,12 +18,12 @@ import { EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { RoleTemplate } from '../../../../../../../common/model'; +import { RoleTemplate } from '../../../../../common/model'; import { isInlineRoleTemplate, isStoredRoleTemplate, isInvalidRoleTemplate, -} from '../../services/role_template_type'; +} from '../services/role_template_type'; import { RoleTemplateTypeSelect } from './role_template_type_select'; interface Props { diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_type_select.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_type_select.tsx similarity index 92% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_type_select.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_type_select.tsx index 4a06af0fb436ba..aa65c5c9bcae74 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_type_select.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_type_select.tsx @@ -7,8 +7,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiComboBox } from '@elastic/eui'; -import { RoleTemplate } from '../../../../../../../common/model'; -import { isInlineRoleTemplate, isStoredRoleTemplate } from '../../services/role_template_type'; +import { RoleTemplate } from '../../../../../common/model'; +import { isInlineRoleTemplate, isStoredRoleTemplate } from '../services/role_template_type'; const templateTypeOptions = [ { diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_index.scss b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_index.scss new file mode 100644 index 00000000000000..c3b2764e647130 --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_index.scss @@ -0,0 +1 @@ +@import './rule_editor_group'; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/_index.scss b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_rule_editor_group.scss similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/_index.scss rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_rule_editor_group.scss diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.test.tsx similarity index 97% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.test.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.test.tsx index 917b822acef3f2..d1411bd9bf2b97 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { AddRuleButton } from './add_rule_button'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { findTestSubject } from 'test_utils/find_test_subject'; -import { FieldRule, AllRule } from '../../../model'; +import { FieldRule, AllRule } from '../../model'; describe('AddRuleButton', () => { it('allows a field rule to be created', () => { diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.tsx similarity index 97% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.tsx index 100c0dd3eeaee4..9696fa337a74fc 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.tsx @@ -7,7 +7,7 @@ import React, { useState } from 'react'; import { EuiButtonEmpty, EuiPopover, EuiContextMenuPanel, EuiContextMenuItem } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Rule, FieldRule, AllRule } from '../../../model'; +import { Rule, FieldRule, AllRule } from '../../model'; interface Props { onClick: (newRule: Rule) => void; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.test.tsx similarity index 99% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.test.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.test.tsx index 8d5d5c99ee99d7..5374f4625336de 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { FieldRuleEditor } from './field_rule_editor'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { FieldRule } from '../../../model'; +import { FieldRule } from '../../model'; import { findTestSubject } from 'test_utils/find_test_subject'; import { ReactWrapper } from 'enzyme'; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.tsx similarity index 99% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.tsx index 52cf70dbd12bd2..168c0e97d4f278 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.tsx @@ -18,7 +18,7 @@ import { EuiIcon, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FieldRule, FieldRuleValue } from '../../../model'; +import { FieldRule, FieldRuleValue } from '../../model'; interface Props { rule: FieldRule; @@ -37,7 +37,7 @@ const userFields = [ name: 'groups', }, { - name: 'realm', + name: 'realm.name', }, ]; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/index.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/index.tsx similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/index.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/index.tsx diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.test.tsx similarity index 84% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.test.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.test.tsx index 8a9b37ab0f4065..43f6c50ea11723 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.test.tsx @@ -17,7 +17,10 @@ import { act } from 'react-dom/test-utils'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { JSONRuleEditor } from './json_rule_editor'; import { EuiCodeEditor } from '@elastic/eui'; -import { AllRule, AnyRule, FieldRule, ExceptAnyRule, ExceptAllRule } from '../../../model'; +import { AllRule, AnyRule, FieldRule, ExceptAnyRule, ExceptAllRule } from '../../model'; +import { DocumentationLinksService } from '../../documentation_links'; + +import { coreMock } from '../../../../../../../../src/core/public/mocks'; describe('JSONRuleEditor', () => { it('renders an empty rule set', () => { @@ -25,6 +28,7 @@ describe('JSONRuleEditor', () => { rules: null, onChange: jest.fn(), onValidityChange: jest.fn(), + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); @@ -40,12 +44,13 @@ describe('JSONRuleEditor', () => { new AnyRule([new FieldRule('username', '*')]), new ExceptAnyRule([ new FieldRule('metadata.foo.bar', '*'), - new AllRule([new FieldRule('realm', 'special-one')]), + new AllRule([new FieldRule('realm.name', 'special-one')]), ]), - new ExceptAllRule([new FieldRule('realm', '*')]), + new ExceptAllRule([new FieldRule('realm.name', '*')]), ]), onChange: jest.fn(), onValidityChange: jest.fn(), + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); @@ -60,14 +65,14 @@ describe('JSONRuleEditor', () => { any: [ { field: { 'metadata.foo.bar': '*' } }, { - all: [{ field: { realm: 'special-one' } }], + all: [{ field: { ['realm.name']: 'special-one' } }], }, ], }, }, { except: { - all: [{ field: { realm: '*' } }], + all: [{ field: { ['realm.name']: '*' } }], }, }, ], @@ -79,6 +84,7 @@ describe('JSONRuleEditor', () => { rules: null, onChange: jest.fn(), onValidityChange: jest.fn(), + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); @@ -100,6 +106,7 @@ describe('JSONRuleEditor', () => { rules: null, onChange: jest.fn(), onValidityChange: jest.fn(), + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); @@ -130,6 +137,7 @@ describe('JSONRuleEditor', () => { rules: null, onChange: jest.fn(), onValidityChange: jest.fn(), + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx index 371fb59f7a5d13..e7a9149513d208 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx @@ -11,13 +11,14 @@ import 'brace/theme/github'; import { EuiCodeEditor, EuiFormRow, EuiButton, EuiSpacer, EuiLink, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { Rule, RuleBuilderError, generateRulesFromRaw } from '../../../model'; -import { documentationLinks } from '../../../services/documentation_links'; +import { DocumentationLinksService } from '../../documentation_links'; +import { Rule, RuleBuilderError, generateRulesFromRaw } from '../../model'; interface Props { rules: Rule | null; onChange: (updatedRules: Rule | null) => void; onValidityChange: (isValid: boolean) => void; + docLinks: DocumentationLinksService; } export const JSONRuleEditor = (props: Props) => { @@ -107,7 +108,7 @@ export const JSONRuleEditor = (props: Props) => { values={{ roleMappingAPI: ( diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.test.tsx similarity index 88% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.test.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.test.tsx index 809264183d30ca..b9c650cc1f77a4 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.test.tsx @@ -15,8 +15,11 @@ import { findTestSubject } from 'test_utils/find_test_subject'; // This is not required for the tests to pass, but it rather suppresses lengthy // warnings in the console which adds unnecessary noise to the test output. import 'test_utils/stub_web_worker'; -import { AllRule, FieldRule } from '../../../model'; +import { AllRule, FieldRule } from '../../model'; import { EuiErrorBoundary } from '@elastic/eui'; +import { DocumentationLinksService } from '../../documentation_links'; + +import { coreMock } from '../../../../../../../../src/core/public/mocks'; describe('RuleEditorPanel', () => { it('renders the visual editor when no rules are defined', () => { @@ -25,6 +28,7 @@ describe('RuleEditorPanel', () => { onChange: jest.fn(), onValidityChange: jest.fn(), validateForm: false, + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); expect(wrapper.find(VisualRuleEditor)).toHaveLength(1); @@ -45,6 +49,7 @@ describe('RuleEditorPanel', () => { onChange: jest.fn(), onValidityChange: jest.fn(), validateForm: false, + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); expect(wrapper.find(VisualRuleEditor)).toHaveLength(1); @@ -68,6 +73,7 @@ describe('RuleEditorPanel', () => { onChange: jest.fn(), onValidityChange: jest.fn(), validateForm: false, + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); @@ -103,6 +109,7 @@ describe('RuleEditorPanel', () => { onChange: jest.fn(), onValidityChange: jest.fn(), validateForm: false, + docLinks: new DocumentationLinksService(coreMock.createStart().docLinks), }; const wrapper = mountWithIntl(); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.tsx similarity index 94% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.tsx index 4aab49b2b2efcf..6e6641caa1f399 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.tsx @@ -22,19 +22,20 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { RoleMapping } from '../../../../../../../common/model'; +import { RoleMapping } from '../../../../../common/model'; import { VisualRuleEditor } from './visual_rule_editor'; import { JSONRuleEditor } from './json_rule_editor'; -import { VISUAL_MAX_RULE_DEPTH } from '../../services/role_mapping_constants'; -import { Rule, generateRulesFromRaw } from '../../../model'; -import { validateRoleMappingRules } from '../../services/role_mapping_validation'; -import { documentationLinks } from '../../../services/documentation_links'; +import { VISUAL_MAX_RULE_DEPTH } from '../services/role_mapping_constants'; +import { Rule, generateRulesFromRaw } from '../../model'; +import { DocumentationLinksService } from '../../documentation_links'; +import { validateRoleMappingRules } from '../services/role_mapping_validation'; interface Props { rawRules: RoleMapping['rules']; onChange: (rawRules: RoleMapping['rules']) => void; onValidityChange: (isValid: boolean) => void; validateForm: boolean; + docLinks: DocumentationLinksService; } interface State { @@ -91,7 +92,7 @@ export class RuleEditorPanel extends Component { values={{ learnMoreLink: ( @@ -214,6 +215,7 @@ export class RuleEditorPanel extends Component { rules={this.state.rules} onChange={this.onRuleChange} onValidityChange={this.onValidityChange} + docLinks={this.props.docLinks} /> ); default: diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.test.tsx similarity index 99% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.test.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.test.tsx index 3e0e0e386e98c2..5946aac4306b1f 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { RuleGroupEditor } from './rule_group_editor'; import { shallowWithIntl, mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { AllRule, FieldRule, AnyRule, ExceptAnyRule } from '../../../model'; +import { AllRule, FieldRule, AnyRule, ExceptAnyRule } from '../../model'; import { FieldRuleEditor } from './field_rule_editor'; import { AddRuleButton } from './add_rule_button'; import { EuiContextMenuItem } from '@elastic/eui'; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.tsx similarity index 97% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.tsx index 6fb33db179e8a6..c17a853a654676 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.tsx @@ -16,8 +16,8 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { AddRuleButton } from './add_rule_button'; import { RuleGroupTitle } from './rule_group_title'; import { FieldRuleEditor } from './field_rule_editor'; -import { RuleGroup, Rule, FieldRule } from '../../../model'; -import { isRuleGroup } from '../../services/is_rule_group'; +import { RuleGroup, Rule, FieldRule } from '../../model'; +import { isRuleGroup } from '../services/is_rule_group'; interface Props { rule: RuleGroup; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_title.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_title.tsx similarity index 97% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_title.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_title.tsx index e46893afd4d86e..6bef9c09eeef39 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_title.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_title.tsx @@ -15,14 +15,7 @@ import { EuiConfirmModal, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - RuleGroup, - AllRule, - AnyRule, - ExceptAllRule, - ExceptAnyRule, - FieldRule, -} from '../../../model'; +import { RuleGroup, AllRule, AnyRule, ExceptAllRule, ExceptAnyRule, FieldRule } from '../../model'; interface Props { rule: RuleGroup; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.test.tsx similarity index 96% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.test.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.test.tsx index 7c63613ee1cc9e..7ec723853863ad 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { VisualRuleEditor } from './visual_rule_editor'; import { findTestSubject } from 'test_utils/find_test_subject'; -import { AnyRule, AllRule, FieldRule, ExceptAnyRule, ExceptAllRule } from '../../../model'; +import { AnyRule, AllRule, FieldRule, ExceptAnyRule, ExceptAllRule } from '../../model'; import { RuleGroupEditor } from './rule_group_editor'; import { FieldRuleEditor } from './field_rule_editor'; @@ -72,9 +72,9 @@ describe('VisualRuleEditor', () => { new AnyRule([new FieldRule('username', '*')]), new ExceptAnyRule([ new FieldRule('metadata.foo.bar', '*'), - new AllRule([new FieldRule('realm', 'special-one')]), + new AllRule([new FieldRule('realm.name', 'special-one')]), ]), - new ExceptAllRule([new FieldRule('realm', '*')]), + new ExceptAllRule([new FieldRule('realm.name', '*')]), ]), maxDepth: 4, onSwitchEditorMode: jest.fn(), diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.tsx rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.tsx index 214c583189fb80..2e3db275788ee4 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.tsx @@ -9,9 +9,9 @@ import { EuiEmptyPrompt, EuiCallOut, EuiSpacer, EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { FieldRuleEditor } from './field_rule_editor'; import { RuleGroupEditor } from './rule_group_editor'; -import { VISUAL_MAX_RULE_DEPTH } from '../../services/role_mapping_constants'; -import { Rule, FieldRule, RuleGroup, AllRule } from '../../../model'; -import { isRuleGroup } from '../../services/is_rule_group'; +import { VISUAL_MAX_RULE_DEPTH } from '../services/role_mapping_constants'; +import { Rule, FieldRule, RuleGroup, AllRule } from '../../model'; +import { isRuleGroup } from '../services/is_rule_group'; interface Props { rules: Rule | null; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/is_rule_group.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/is_rule_group.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/is_rule_group.ts rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/is_rule_group.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts similarity index 98% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts index 9614c4338b631f..0c3f988ae6b105 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts @@ -10,7 +10,7 @@ import { validateRoleMappingRules, validateRoleMappingForSave, } from './role_mapping_validation'; -import { RoleMapping } from '../../../../../../common/model'; +import { RoleMapping } from '../../../../../common/model'; describe('validateRoleMappingName', () => { it('requires a value', () => { diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts similarity index 97% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts index 5916d6fd9e1891..7695f1da14881a 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { RoleMapping } from '../../../../../../common/model'; +import { RoleMapping } from '../../../../../common/model'; import { generateRulesFromRaw } from '../../model'; interface ValidationResult { diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts similarity index 96% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts index 8e1f47a4157ae9..c093bb1b3fbbc9 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts @@ -9,7 +9,7 @@ import { isInlineRoleTemplate, isInvalidRoleTemplate, } from './role_template_type'; -import { RoleTemplate } from '../../../../../../common/model'; +import { RoleTemplate } from '../../../../../common/model'; describe('#isStoredRoleTemplate', () => { it('returns true for stored templates, false otherwise', () => { diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.ts similarity index 96% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.ts rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.ts index 90d8d1a09e5877..5e646535a6c4d5 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.ts +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.ts @@ -9,7 +9,7 @@ import { StoredRoleTemplate, InlineRoleTemplate, InvalidRoleTemplate, -} from '../../../../../../common/model'; +} from '../../../../../common/model'; export function isStoredRoleTemplate( roleMappingTemplate: RoleTemplate diff --git a/x-pack/plugins/security/public/management/role_mappings/index.mock.ts b/x-pack/plugins/security/public/management/role_mappings/index.mock.ts new file mode 100644 index 00000000000000..826477a1a5b153 --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/index.mock.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { roleMappingsAPIClientMock } from './role_mappings_api_client.mock'; diff --git a/x-pack/plugins/security/public/management/role_mappings/index.ts b/x-pack/plugins/security/public/management/role_mappings/index.ts new file mode 100644 index 00000000000000..f670ea61810386 --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { roleMappingsManagementApp } from './role_mappings_management_app'; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap b/x-pack/plugins/security/public/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap rename to x-pack/plugins/security/public/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/all_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/all_rule.test.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/all_rule.test.ts rename to x-pack/plugins/security/public/management/role_mappings/model/all_rule.test.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/all_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/all_rule.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/all_rule.ts rename to x-pack/plugins/security/public/management/role_mappings/model/all_rule.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/any_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/any_rule.test.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/any_rule.test.ts rename to x-pack/plugins/security/public/management/role_mappings/model/any_rule.test.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/any_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/any_rule.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/any_rule.ts rename to x-pack/plugins/security/public/management/role_mappings/model/any_rule.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_all_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/except_all_rule.test.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_all_rule.test.ts rename to x-pack/plugins/security/public/management/role_mappings/model/except_all_rule.test.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_all_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/except_all_rule.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_all_rule.ts rename to x-pack/plugins/security/public/management/role_mappings/model/except_all_rule.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_any_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/except_any_rule.test.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_any_rule.test.ts rename to x-pack/plugins/security/public/management/role_mappings/model/except_any_rule.test.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_any_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/except_any_rule.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_any_rule.ts rename to x-pack/plugins/security/public/management/role_mappings/model/except_any_rule.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/field_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/field_rule.test.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/field_rule.test.ts rename to x-pack/plugins/security/public/management/role_mappings/model/field_rule.test.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/field_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/field_rule.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/field_rule.ts rename to x-pack/plugins/security/public/management/role_mappings/model/field_rule.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/index.ts b/x-pack/plugins/security/public/management/role_mappings/model/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/index.ts rename to x-pack/plugins/security/public/management/role_mappings/model/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule.ts rename to x-pack/plugins/security/public/management/role_mappings/model/rule.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder.test.ts similarity index 99% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.test.ts rename to x-pack/plugins/security/public/management/role_mappings/model/rule_builder.test.ts index ebd48f6d15d99e..ad486a8b314c4f 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.test.ts +++ b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder.test.ts @@ -5,7 +5,7 @@ */ import { generateRulesFromRaw, FieldRule } from '.'; -import { RoleMapping } from '../../../../../common/model'; +import { RoleMapping } from '../../../../common/model'; import { RuleBuilderError } from './rule_builder_error'; describe('generateRulesFromRaw', () => { diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder.ts similarity index 99% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.ts rename to x-pack/plugins/security/public/management/role_mappings/model/rule_builder.ts index fe344b2ae38dd0..a384e61e521aba 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.ts +++ b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { RoleMapping } from '../../../../../common/model'; +import { RoleMapping } from '../../../../common/model'; import { FieldRule, FieldRuleValue } from './field_rule'; import { AllRule } from './all_rule'; import { AnyRule } from './any_rule'; diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder_error.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder_error.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder_error.ts rename to x-pack/plugins/security/public/management/role_mappings/model/rule_builder_error.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_group.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule_group.ts similarity index 94% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_group.ts rename to x-pack/plugins/security/public/management/role_mappings/model/rule_group.ts index 3e1e7fad9b36f5..5077c79a543c46 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_group.ts +++ b/x-pack/plugins/security/public/management/role_mappings/model/rule_group.ts @@ -7,7 +7,7 @@ import { Rule } from './rule'; /** - * Represents a catagory of Role Mapping rules which are capable of containing other rules. + * Represents a category of Role Mapping rules which are capable of containing other rules. */ export abstract class RuleGroup extends Rule { /** diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts new file mode 100644 index 00000000000000..07d583d1e983f6 --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const roleMappingsAPIClientMock = { + create: () => ({ + checkRoleMappingFeatures: jest.fn(), + getRoleMappings: jest.fn(), + getRoleMapping: jest.fn(), + saveRoleMapping: jest.fn(), + deleteRoleMappings: jest.fn(), + }), +}; diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts new file mode 100644 index 00000000000000..0a88ed1da9ac3a --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpStart } from 'src/core/public'; +import { RoleMapping } from '../../../common/model'; + +interface CheckRoleMappingFeaturesResponse { + canManageRoleMappings: boolean; + canUseInlineScripts: boolean; + canUseStoredScripts: boolean; + hasCompatibleRealms: boolean; +} + +type DeleteRoleMappingsResponse = Array<{ + name: string; + success: boolean; + error?: Error; +}>; + +export class RoleMappingsAPIClient { + constructor(private readonly http: HttpStart) {} + + public async checkRoleMappingFeatures(): Promise { + return this.http.get(`/internal/security/_check_role_mapping_features`); + } + + public async getRoleMappings(): Promise { + return this.http.get(`/internal/security/role_mapping`); + } + + public async getRoleMapping(name: string): Promise { + return this.http.get(`/internal/security/role_mapping/${encodeURIComponent(name)}`); + } + + public async saveRoleMapping(roleMapping: RoleMapping) { + const payload = { ...roleMapping }; + delete payload.name; + + return this.http.post( + `/internal/security/role_mapping/${encodeURIComponent(roleMapping.name)}`, + { body: JSON.stringify(payload) } + ); + } + + public async deleteRoleMappings(names: string[]): Promise { + return Promise.all( + names.map(name => + this.http + .delete(`/internal/security/role_mapping/${encodeURIComponent(name)}`) + .then(() => ({ success: true, name })) + .catch(error => ({ success: false, name, error })) + ) + ); + } +} diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/create_role_mapping_button.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx similarity index 90% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/create_role_mapping_button.tsx rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx index 2342eeb97d03e3..6fe4bcc7a0bbb0 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/create_role_mapping_button.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { getCreateRoleMappingHref } from '../../../../management_urls'; +import { getCreateRoleMappingHref } from '../../../management_urls'; export const CreateRoleMappingButton = () => { return ( diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/index.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/index.ts rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/empty_prompt/empty_prompt.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/empty_prompt.tsx similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/empty_prompt/empty_prompt.tsx rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/empty_prompt.tsx diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/empty_prompt/index.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/empty_prompt/index.ts rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/index.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/index.ts rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/index.ts diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx new file mode 100644 index 00000000000000..de0722b4cd85e2 --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx @@ -0,0 +1,219 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; +import { RoleMappingsGridPage } from '.'; +import { SectionLoading, PermissionDenied, NoCompatibleRealms } from '../components'; +import { EmptyPrompt } from './empty_prompt'; +import { findTestSubject } from 'test_utils/find_test_subject'; +import { EuiLink } from '@elastic/eui'; +import { act } from '@testing-library/react'; +import { DocumentationLinksService } from '../documentation_links'; + +import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { roleMappingsAPIClientMock } from '../role_mappings_api_client.mock'; + +describe('RoleMappingsGridPage', () => { + it('renders an empty prompt when no role mappings exist', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMappings.mockResolvedValue([]); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + expect(wrapper.find(SectionLoading)).toHaveLength(1); + expect(wrapper.find(EmptyPrompt)).toHaveLength(0); + + await nextTick(); + wrapper.update(); + + expect(wrapper.find(SectionLoading)).toHaveLength(0); + expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); + expect(wrapper.find(EmptyPrompt)).toHaveLength(1); + }); + + it('renders a permission denied message when unauthorized to manage role mappings', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: false, + hasCompatibleRealms: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + expect(wrapper.find(SectionLoading)).toHaveLength(1); + expect(wrapper.find(PermissionDenied)).toHaveLength(0); + + await nextTick(); + wrapper.update(); + + expect(wrapper.find(SectionLoading)).toHaveLength(0); + expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); + expect(wrapper.find(PermissionDenied)).toHaveLength(1); + }); + + it('renders a warning when there are no compatible realms enabled', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMappings.mockResolvedValue([ + { + name: 'some realm', + enabled: true, + roles: [], + rules: { field: { username: '*' } }, + }, + ]); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: false, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + expect(wrapper.find(SectionLoading)).toHaveLength(1); + expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); + + await nextTick(); + wrapper.update(); + + expect(wrapper.find(SectionLoading)).toHaveLength(0); + expect(wrapper.find(NoCompatibleRealms)).toHaveLength(1); + }); + + it('renders links to mapped roles', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMappings.mockResolvedValue([ + { + name: 'some realm', + enabled: true, + roles: ['superuser'], + rules: { field: { username: '*' } }, + }, + ]); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + await nextTick(); + wrapper.update(); + + const links = findTestSubject(wrapper, 'roleMappingRoles').find(EuiLink); + expect(links).toHaveLength(1); + expect(links.at(0).props()).toMatchObject({ + href: '#/management/security/roles/edit/superuser', + }); + }); + + it('describes the number of mapped role templates', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMappings.mockResolvedValue([ + { + name: 'some realm', + enabled: true, + role_templates: [{}, {}], + rules: { field: { username: '*' } }, + }, + ]); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + }); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + await nextTick(); + wrapper.update(); + + const templates = findTestSubject(wrapper, 'roleMappingRoles'); + expect(templates).toHaveLength(1); + expect(templates.text()).toEqual(`2 role templates defined`); + }); + + it('allows role mappings to be deleted, refreshing the grid after', async () => { + const roleMappingsAPI = roleMappingsAPIClientMock.create(); + roleMappingsAPI.getRoleMappings.mockResolvedValue([ + { + name: 'some-realm', + enabled: true, + roles: ['superuser'], + rules: { field: { username: '*' } }, + }, + ]); + roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ + canManageRoleMappings: true, + hasCompatibleRealms: true, + }); + roleMappingsAPI.deleteRoleMappings.mockResolvedValue([ + { + name: 'some-realm', + success: true, + }, + ]); + + const { docLinks, notifications } = coreMock.createStart(); + const wrapper = mountWithIntl( + + ); + await nextTick(); + wrapper.update(); + + expect(roleMappingsAPI.getRoleMappings).toHaveBeenCalledTimes(1); + expect(roleMappingsAPI.deleteRoleMappings).not.toHaveBeenCalled(); + + findTestSubject(wrapper, `deleteRoleMappingButton-some-realm`).simulate('click'); + expect(findTestSubject(wrapper, 'deleteRoleMappingConfirmationModal')).toHaveLength(1); + + await act(async () => { + findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click'); + await nextTick(); + wrapper.update(); + }); + + expect(roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['some-realm']); + // Expect an additional API call to refresh the grid + expect(roleMappingsAPI.getRoleMappings).toHaveBeenCalledTimes(2); + }); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx similarity index 93% rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.tsx rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx index 7b23f2288d1ba6..feb918cb6b301f 100644 --- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx @@ -25,24 +25,27 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { RoleMapping } from '../../../../../../common/model'; -import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api'; +import { NotificationsStart } from 'src/core/public'; +import { RoleMapping } from '../../../../common/model'; import { EmptyPrompt } from './empty_prompt'; import { NoCompatibleRealms, DeleteProvider, PermissionDenied, SectionLoading, -} from '../../components'; -import { documentationLinks } from '../../services/documentation_links'; +} from '../components'; import { getCreateRoleMappingHref, getEditRoleMappingHref, getEditRoleHref, -} from '../../../management_urls'; +} from '../../management_urls'; +import { DocumentationLinksService } from '../documentation_links'; +import { RoleMappingsAPIClient } from '../role_mappings_api_client'; interface Props { - roleMappingsAPI: RoleMappingsAPI; + roleMappingsAPI: PublicMethodsOf; + notifications: NotificationsStart; + docLinks: DocumentationLinksService; } interface State { @@ -140,7 +143,7 @@ export class RoleMappingsGridPage extends Component { values={{ learnMoreLink: ( @@ -168,7 +171,7 @@ export class RoleMappingsGridPage extends Component { {!this.state.hasCompatibleRealms && ( <> - + )} @@ -214,7 +217,10 @@ export class RoleMappingsGridPage extends Component { const search = { toolsLeft: selectedItems.length ? ( - + {deleteRoleMappingsPrompt => { return ( { return ( - + {deleteRoleMappingPrompt => { return ( ({ + RoleMappingsGridPage: (props: any) => `Role Mappings Page: ${JSON.stringify(props)}`, +})); + +jest.mock('./edit_role_mapping', () => ({ + EditRoleMappingPage: (props: any) => `Role Mapping Edit Page: ${JSON.stringify(props)}`, +})); + +import { roleMappingsManagementApp } from './role_mappings_management_app'; + +import { coreMock } from '../../../../../../src/core/public/mocks'; + +async function mountApp(basePath: string) { + const container = document.createElement('div'); + const setBreadcrumbs = jest.fn(); + + const unmount = await roleMappingsManagementApp + .create({ getStartServices: coreMock.createSetup().getStartServices as any }) + .mount({ basePath, element: container, setBreadcrumbs }); + + return { unmount, container, setBreadcrumbs }; +} + +describe('roleMappingsManagementApp', () => { + it('create() returns proper management app descriptor', () => { + expect( + roleMappingsManagementApp.create({ + getStartServices: coreMock.createSetup().getStartServices as any, + }) + ).toMatchInlineSnapshot(` + Object { + "id": "role_mappings", + "mount": [Function], + "order": 40, + "title": "Role Mappings", + } + `); + }); + + it('mount() works for the `grid` page', async () => { + const basePath = '/some-base-path/role_mappings'; + window.location.hash = basePath; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Role Mappings' }]); + expect(container).toMatchInlineSnapshot(` +
    + Role Mappings Page: {"notifications":{"toasts":{}},"roleMappingsAPI":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() works for the `create role mapping` page', async () => { + const basePath = '/some-base-path/role_mappings'; + window.location.hash = `${basePath}/edit`; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Role Mappings' }, + { text: 'Create' }, + ]); + expect(container).toMatchInlineSnapshot(` +
    + Role Mapping Edit Page: {"roleMappingsAPI":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() works for the `edit role mapping` page', async () => { + const basePath = '/some-base-path/role_mappings'; + const roleMappingName = 'someRoleMappingName'; + window.location.hash = `${basePath}/edit/${roleMappingName}`; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Role Mappings' }, + { href: `#/some-base-path/role_mappings/edit/${roleMappingName}`, text: roleMappingName }, + ]); + expect(container).toMatchInlineSnapshot(` +
    + Role Mapping Edit Page: {"name":"someRoleMappingName","roleMappingsAPI":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() properly encodes role mapping name in `edit role mapping` page link in breadcrumbs', async () => { + const basePath = '/some-base-path/role_mappings'; + const roleMappingName = 'some 安全性 role mapping'; + window.location.hash = `${basePath}/edit/${roleMappingName}`; + + const { setBreadcrumbs } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Role Mappings' }, + { + href: + '#/some-base-path/role_mappings/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20role%20mapping', + text: roleMappingName, + }, + ]); + }); +}); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx new file mode 100644 index 00000000000000..af1572cedbadef --- /dev/null +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx @@ -0,0 +1,104 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; +import { CoreSetup } from 'src/core/public'; +import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public'; +import { PluginStartDependencies } from '../../plugin'; +import { RolesAPIClient } from '../roles'; +import { RoleMappingsAPIClient } from './role_mappings_api_client'; +import { DocumentationLinksService } from './documentation_links'; +import { RoleMappingsGridPage } from './role_mappings_grid'; +import { EditRoleMappingPage } from './edit_role_mapping'; + +interface CreateParams { + getStartServices: CoreSetup['getStartServices']; +} + +export const roleMappingsManagementApp = Object.freeze({ + id: 'role_mappings', + create({ getStartServices }: CreateParams) { + return { + id: this.id, + order: 40, + title: i18n.translate('xpack.security.management.roleMappingsTitle', { + defaultMessage: 'Role Mappings', + }), + async mount({ basePath, element, setBreadcrumbs }) { + const [{ docLinks, http, notifications, i18n: i18nStart }] = await getStartServices(); + const roleMappingsBreadcrumbs = [ + { + text: i18n.translate('xpack.security.roleMapping.breadcrumb', { + defaultMessage: 'Role Mappings', + }), + href: `#${basePath}`, + }, + ]; + + const roleMappingsAPIClient = new RoleMappingsAPIClient(http); + const dockLinksService = new DocumentationLinksService(docLinks); + const RoleMappingsGridPageWithBreadcrumbs = () => { + setBreadcrumbs(roleMappingsBreadcrumbs); + return ( + + ); + }; + + const EditRoleMappingsPageWithBreadcrumbs = () => { + const { name } = useParams<{ name?: string }>(); + + setBreadcrumbs([ + ...roleMappingsBreadcrumbs, + name + ? { text: name, href: `#${basePath}/edit/${encodeURIComponent(name)}` } + : { + text: i18n.translate('xpack.security.roleMappings.createBreadcrumb', { + defaultMessage: 'Create', + }), + }, + ]); + + return ( + + ); + }; + + render( + + + + + + + + + + + + , + element + ); + + return () => { + unmountComponentAtNode(element); + }; + }, + } as RegisterManagementAppArgs; + }, +}); diff --git a/x-pack/plugins/security/public/management/roles/_index.scss b/x-pack/plugins/security/public/management/roles/_index.scss new file mode 100644 index 00000000000000..5256c79f01f10f --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/_index.scss @@ -0,0 +1 @@ +@import './edit_role/index'; diff --git a/x-pack/plugins/security/public/management/roles/documentation_links.ts b/x-pack/plugins/security/public/management/roles/documentation_links.ts new file mode 100644 index 00000000000000..cf46973d3541ca --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/documentation_links.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DocLinksStart } from 'src/core/public'; + +export class DocumentationLinksService { + private readonly esDocBasePath: string; + + constructor(docLinks: DocLinksStart) { + this.esDocBasePath = `${docLinks.ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${docLinks.DOC_LINK_VERSION}/`; + } + + public getESClusterPrivilegesDocUrl() { + return `${this.esDocBasePath}security-privileges.html#privileges-list-cluster`; + } + + public getESRunAsPrivilegesDocUrl() { + return `${this.esDocBasePath}security-privileges.html#_run_as_privilege`; + } + + public getESIndicesPrivilegesDocUrl() { + return `${this.esDocBasePath}security-privileges.html#privileges-list-indices`; + } +} diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/lib/__snapshots__/validate_role.test.ts.snap b/x-pack/plugins/security/public/management/roles/edit_role/__snapshots__/validate_role.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/lib/__snapshots__/validate_role.test.ts.snap rename to x-pack/plugins/security/public/management/roles/edit_role/__snapshots__/validate_role.test.ts.snap diff --git a/x-pack/plugins/security/public/management/roles/edit_role/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/_index.scss new file mode 100644 index 00000000000000..0153b1734ceba0 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/_index.scss @@ -0,0 +1,3 @@ +@import './collapsible_panel/index'; +@import './spaces_popover_list/index'; +@import './privileges/index'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/_collapsible_panel.scss b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_collapsible_panel.scss similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/_collapsible_panel.scss rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_collapsible_panel.scss diff --git a/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_index.scss new file mode 100644 index 00000000000000..c0f4f8ab9a8701 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_index.scss @@ -0,0 +1 @@ +@import './collapsible_panel'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.test.tsx similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.test.tsx diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.tsx b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.tsx similarity index 99% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.tsx index 416dd7f6c4e5c7..01af7cb4509f64 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.tsx @@ -50,7 +50,6 @@ export class CollapsiblePanel extends Component { public getTitle = () => { return ( - // @ts-ignore diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/index.ts rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.test.tsx similarity index 94% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.test.tsx index cc16866c883555..f4af935be66487 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.test.tsx @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiButtonEmpty, - // @ts-ignore - EuiConfirmModal, -} from '@elastic/eui'; +import { EuiButtonEmpty, EuiConfirmModal } from '@elastic/eui'; import React from 'react'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import { DeleteRoleButton } from './delete_role_button'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.tsx b/x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.tsx index 1ae84d3fb72242..c6a10396f235c4 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.tsx @@ -4,13 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiButtonEmpty, - // @ts-ignore - EuiConfirmModal, - // @ts-ignore - EuiOverlayMask, -} from '@elastic/eui'; +import { EuiButtonEmpty, EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { Component, Fragment } from 'react'; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx new file mode 100644 index 00000000000000..e183eae08d1e17 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx @@ -0,0 +1,552 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ReactWrapper } from 'enzyme'; +import React from 'react'; +import { act } from '@testing-library/react'; +import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; +import { Capabilities } from 'src/core/public'; +import { Space } from '../../../../../spaces/common/model/space'; +import { Feature } from '../../../../../features/public'; +// These modules should be moved into a common directory +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { Actions } from '../../../../server/authorization/actions'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { privilegesFactory } from '../../../../server/authorization/privileges'; +import { Role } from '../../../../common/model'; +import { DocumentationLinksService } from '../documentation_links'; +import { EditRolePage } from './edit_role_page'; +import { SimplePrivilegeSection } from './privileges/kibana/simple_privilege_section'; +import { SpaceAwarePrivilegeSection } from './privileges/kibana/space_aware_privilege_section'; + +import { TransformErrorSection } from './privileges/kibana/transform_error_section'; +import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; +import { licenseMock } from '../../../../common/licensing/index.mock'; +import { userAPIClientMock } from '../../users/index.mock'; +import { rolesAPIClientMock, indicesAPIClientMock, privilegesAPIClientMock } from '../index.mock'; + +const buildFeatures = () => { + return [ + { + id: 'feature1', + name: 'Feature 1', + icon: 'addDataApp', + app: ['feature1App'], + privileges: { + all: { + app: ['feature1App'], + ui: ['feature1-ui'], + savedObject: { + all: [], + read: [], + }, + }, + }, + }, + { + id: 'feature2', + name: 'Feature 2', + icon: 'addDataApp', + app: ['feature2App'], + privileges: { + all: { + app: ['feature2App'], + ui: ['feature2-ui'], + savedObject: { + all: ['feature2'], + read: ['config'], + }, + }, + }, + }, + ] as Feature[]; +}; + +const buildRawKibanaPrivileges = () => { + return privilegesFactory(new Actions('unit_test_version'), { + getFeatures: () => buildFeatures(), + }).get(); +}; + +const buildBuiltinESPrivileges = () => { + return { + cluster: ['all', 'manage', 'monitor'], + index: ['all', 'read', 'write', 'index'], + }; +}; + +const buildUICapabilities = (canManageSpaces = true) => { + return { + catalogue: {}, + management: {}, + navLinks: {}, + spaces: { + manage: canManageSpaces, + }, + } as Capabilities; +}; + +const buildSpaces = () => { + return [ + { + id: 'default', + name: 'Default', + disabledFeatures: [], + _reserved: true, + }, + { + id: 'space_1', + name: 'Space 1', + disabledFeatures: [], + }, + { + id: 'space_2', + name: 'Space 2', + disabledFeatures: ['feature2'], + }, + ] as Space[]; +}; + +const expectReadOnlyFormButtons = (wrapper: ReactWrapper) => { + expect(wrapper.find('button[data-test-subj="roleFormReturnButton"]')).toHaveLength(1); + expect(wrapper.find('button[data-test-subj="roleFormSaveButton"]')).toHaveLength(0); +}; + +const expectSaveFormButtons = (wrapper: ReactWrapper) => { + expect(wrapper.find('button[data-test-subj="roleFormReturnButton"]')).toHaveLength(0); + expect(wrapper.find('button[data-test-subj="roleFormSaveButton"]')).toHaveLength(1); +}; + +function getProps({ + action, + role, + canManageSpaces = true, + spacesEnabled = true, +}: { + action: 'edit' | 'clone'; + role?: Role; + canManageSpaces?: boolean; + spacesEnabled?: boolean; +}) { + const rolesAPIClient = rolesAPIClientMock.create(); + rolesAPIClient.getRole.mockResolvedValue(role); + + const indexPatterns = dataPluginMock.createStartContract().indexPatterns; + indexPatterns.getTitles = jest.fn().mockResolvedValue(['foo*', 'bar*']); + + const indicesAPIClient = indicesAPIClientMock.create(); + + const userAPIClient = userAPIClientMock.create(); + userAPIClient.getUsers.mockResolvedValue([]); + + const privilegesAPIClient = privilegesAPIClientMock.create(); + privilegesAPIClient.getAll.mockResolvedValue(buildRawKibanaPrivileges()); + privilegesAPIClient.getBuiltIn.mockResolvedValue(buildBuiltinESPrivileges()); + + const license = licenseMock.create(); + license.getFeatures.mockReturnValue({ + allowRoleDocumentLevelSecurity: true, + allowRoleFieldLevelSecurity: true, + } as any); + + const { fatalErrors } = coreMock.createSetup(); + const { http, docLinks, notifications } = coreMock.createStart(); + http.get.mockImplementation(async (path: any) => { + if (path === '/api/features') { + return buildFeatures(); + } + + if (path === '/api/spaces/space') { + return buildSpaces(); + } + }); + + return { + action, + roleName: role?.name, + license, + http, + indexPatterns, + indicesAPIClient, + privilegesAPIClient, + rolesAPIClient, + userAPIClient, + notifications, + docLinks: new DocumentationLinksService(docLinks), + fatalErrors, + spacesEnabled, + uiCapabilities: buildUICapabilities(canManageSpaces), + }; +} + +describe('', () => { + describe('with spaces enabled', () => { + it('can render a reserved role', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(1); + expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); + expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); + expectReadOnlyFormButtons(wrapper); + }); + + it('can render a user defined role', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0); + expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); + expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); + expectSaveFormButtons(wrapper); + }); + + it('can render when creating a new role', async () => { + const wrapper = mountWithIntl(); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); + expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); + expectSaveFormButtons(wrapper); + }); + + it('can render when cloning an existing role', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); + expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); + expectSaveFormButtons(wrapper); + }); + + it('renders an auth error when not authorized to manage spaces', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0); + + expect( + wrapper.find('EuiCallOut[data-test-subj="userCannotManageSpacesCallout"]') + ).toHaveLength(1); + + expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); + expectSaveFormButtons(wrapper); + }); + + it('renders a partial read-only view when there is a transform error', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find(TransformErrorSection)).toHaveLength(1); + expectReadOnlyFormButtons(wrapper); + }); + }); + + describe('with spaces disabled', () => { + it('can render a reserved role', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(1); + expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); + expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); + expectReadOnlyFormButtons(wrapper); + }); + + it('can render a user defined role', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0); + expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); + expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); + expectSaveFormButtons(wrapper); + }); + + it('can render when creating a new role', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); + expectSaveFormButtons(wrapper); + }); + + it('can render when cloning an existing role', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); + expectSaveFormButtons(wrapper); + }); + + it('does not care if user cannot manage spaces', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0); + + expect( + wrapper.find('EuiCallOut[data-test-subj="userCannotManageSpacesCallout"]') + ).toHaveLength(0); + + expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1); + expectSaveFormButtons(wrapper); + }); + + it('renders a partial read-only view when there is a transform error', async () => { + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find(TransformErrorSection)).toHaveLength(1); + expectReadOnlyFormButtons(wrapper); + }); + }); + + it('can render if features are not available', async () => { + const { http } = coreMock.createStart(); + http.get.mockImplementation(async (path: any) => { + if (path === '/api/features') { + const error = { response: { status: 404 } }; + throw error; + } + + if (path === '/api/spaces/space') { + return buildSpaces(); + } + }); + + const wrapper = mountWithIntl(); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); + expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); + expectSaveFormButtons(wrapper); + }); + + it('can render if index patterns are not available', async () => { + const indexPatterns = dataPluginMock.createStartContract().indexPatterns; + indexPatterns.getTitles = jest.fn().mockRejectedValue({ response: { status: 403 } }); + + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); + expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); + expectSaveFormButtons(wrapper); + }); +}); diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx new file mode 100644 index 00000000000000..33e69a68ca8960 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -0,0 +1,594 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _, { get } from 'lodash'; +import { + EuiButton, + EuiButtonEmpty, + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiFormRow, + EuiPanel, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import React, { + ChangeEvent, + Fragment, + FunctionComponent, + HTMLProps, + useEffect, + useRef, + useState, +} from 'react'; +import { + Capabilities, + FatalErrorsSetup, + HttpStart, + IHttpFetchError, + NotificationsStart, +} from 'src/core/public'; +import { IndexPatternsContract } from '../../../../../../../src/plugins/data/public'; +import { Space } from '../../../../../spaces/common/model/space'; +import { Feature } from '../../../../../features/public'; +import { + KibanaPrivileges, + RawKibanaPrivileges, + Role, + BuiltinESPrivileges, + isReadOnlyRole as checkIfRoleReadOnly, + isReservedRole as checkIfRoleReserved, + copyRole, + prepareRoleClone, + RoleIndexPrivilege, +} from '../../../../common/model'; +import { ROLES_PATH } from '../../management_urls'; +import { RoleValidationResult, RoleValidator } from './validate_role'; +import { DeleteRoleButton } from './delete_role_button'; +import { ElasticsearchPrivileges, KibanaPrivilegesRegion } from './privileges'; +import { ReservedRoleBadge } from './reserved_role_badge'; +import { SecurityLicense } from '../../../../common/licensing'; +import { UserAPIClient } from '../../users'; +import { DocumentationLinksService } from '../documentation_links'; +import { IndicesAPIClient } from '../indices_api_client'; +import { RolesAPIClient } from '../roles_api_client'; +import { PrivilegesAPIClient } from '../privileges_api_client'; + +interface Props { + action: 'edit' | 'clone'; + roleName?: string; + indexPatterns: IndexPatternsContract; + userAPIClient: PublicMethodsOf; + indicesAPIClient: PublicMethodsOf; + rolesAPIClient: PublicMethodsOf; + privilegesAPIClient: PublicMethodsOf; + docLinks: DocumentationLinksService; + http: HttpStart; + license: SecurityLicense; + spacesEnabled: boolean; + uiCapabilities: Capabilities; + notifications: NotificationsStart; + fatalErrors: FatalErrorsSetup; +} + +function useRunAsUsers( + userAPIClient: PublicMethodsOf, + fatalErrors: FatalErrorsSetup +) { + const [userNames, setUserNames] = useState(null); + useEffect(() => { + userAPIClient.getUsers().then( + users => setUserNames(users.map(user => user.username)), + err => fatalErrors.add(err) + ); + }, [fatalErrors, userAPIClient]); + + return userNames; +} + +function useIndexPatternsTitles( + indexPatterns: IndexPatternsContract, + fatalErrors: FatalErrorsSetup, + notifications: NotificationsStart +) { + const [indexPatternsTitles, setIndexPatternsTitles] = useState(null); + useEffect(() => { + indexPatterns + .getTitles() + .catch((err: IHttpFetchError) => { + // If user doesn't have access to the index patterns they still should be able to create new + // or edit existing role. + if (err.response?.status === 403) { + notifications.toasts.addDanger({ + title: i18n.translate('xpack.security.management.roles.noIndexPatternsPermission', { + defaultMessage: 'You need permission to access the list of available index patterns.', + }), + }); + return []; + } + + fatalErrors.add(err); + throw err; + }) + .then(setIndexPatternsTitles); + }, [fatalErrors, indexPatterns, notifications]); + + return indexPatternsTitles; +} + +function usePrivileges( + privilegesAPIClient: PublicMethodsOf, + fatalErrors: FatalErrorsSetup +) { + const [privileges, setPrivileges] = useState<[RawKibanaPrivileges, BuiltinESPrivileges] | null>( + null + ); + useEffect(() => { + Promise.all([ + privilegesAPIClient.getAll({ includeActions: true }), + privilegesAPIClient.getBuiltIn(), + ]).then( + ([kibanaPrivileges, builtInESPrivileges]) => + setPrivileges([kibanaPrivileges, builtInESPrivileges]), + err => fatalErrors.add(err) + ); + }, [privilegesAPIClient, fatalErrors]); + + return privileges; +} + +function useRole( + rolesAPIClient: PublicMethodsOf, + fatalErrors: FatalErrorsSetup, + notifications: NotificationsStart, + license: SecurityLicense, + action: string, + roleName?: string +) { + const [role, setRole] = useState(null); + useEffect(() => { + const rolePromise = roleName + ? rolesAPIClient.getRole(roleName) + : Promise.resolve({ + name: '', + elasticsearch: { cluster: [], indices: [], run_as: [] }, + kibana: [], + _unrecognized_applications: [], + } as Role); + + rolePromise + .then(fetchedRole => { + if (action === 'clone' && checkIfRoleReserved(fetchedRole)) { + backToRoleList(); + return; + } + + if (fetchedRole.elasticsearch.indices.length === 0) { + const emptyOption: RoleIndexPrivilege = { + names: [], + privileges: [], + }; + + const { + allowRoleDocumentLevelSecurity, + allowRoleFieldLevelSecurity, + } = license.getFeatures(); + + if (allowRoleFieldLevelSecurity) { + emptyOption.field_security = { + grant: ['*'], + except: [], + }; + } + + if (allowRoleDocumentLevelSecurity) { + emptyOption.query = ''; + } + + fetchedRole.elasticsearch.indices.push(emptyOption); + } + + setRole(action === 'clone' ? prepareRoleClone(fetchedRole) : copyRole(fetchedRole)); + }) + .catch((err: IHttpFetchError) => { + if (err.response?.status === 404) { + notifications.toasts.addDanger({ + title: i18n.translate('xpack.security.management.roles.roleNotFound', { + defaultMessage: 'No "{roleName}" role found.', + values: { roleName }, + }), + }); + backToRoleList(); + } else { + fatalErrors.add(err); + } + }); + }, [roleName, action, fatalErrors, rolesAPIClient, notifications, license]); + + return [role, setRole] as [Role | null, typeof setRole]; +} + +function useSpaces(http: HttpStart, fatalErrors: FatalErrorsSetup, spacesEnabled: boolean) { + const [spaces, setSpaces] = useState(null); + useEffect(() => { + (spacesEnabled ? http.get('/api/spaces/space') : Promise.resolve([])).then( + fetchedSpaces => setSpaces(fetchedSpaces), + err => fatalErrors.add(err) + ); + }, [http, fatalErrors, spacesEnabled]); + + return spaces; +} + +function useFeatures(http: HttpStart, fatalErrors: FatalErrorsSetup) { + const [features, setFeatures] = useState(null); + useEffect(() => { + http + .get('/api/features') + .catch((err: IHttpFetchError) => { + // Currently, the `/api/features` endpoint effectively requires the "Global All" kibana privilege (e.g., what + // the `kibana_user` grants), because it returns information about all registered features (#35841). It's + // possible that a user with `manage_security` will attempt to visit the role management page without the + // correct Kibana privileges. If that's the case, then they receive a partial view of the role, and the UI does + // not allow them to make changes to that role's kibana privileges. When this user visits the edit role page, + // this API endpoint will throw a 404, which causes view to fail completely. So we instead attempt to detect the + // 404 here, and respond in a way that still allows the UI to render itself. + const unauthorizedForFeatures = err.response?.status === 404; + if (unauthorizedForFeatures) { + return []; + } + + fatalErrors.add(err); + throw err; + }) + .then(setFeatures); + }, [http, fatalErrors]); + + return features; +} + +function backToRoleList() { + window.location.hash = ROLES_PATH; +} + +export const EditRolePage: FunctionComponent = ({ + userAPIClient, + indexPatterns, + rolesAPIClient, + indicesAPIClient, + privilegesAPIClient, + http, + roleName, + action, + fatalErrors, + spacesEnabled, + license, + docLinks, + uiCapabilities, + notifications, +}) => { + // We should keep the same mutable instance of Validator for every re-render since we'll + // eventually enable validation after the first time user tries to save a role. + const { current: validator } = useRef(new RoleValidator({ shouldValidate: false })); + + const [formError, setFormError] = useState(null); + const runAsUsers = useRunAsUsers(userAPIClient, fatalErrors); + const indexPatternsTitles = useIndexPatternsTitles(indexPatterns, fatalErrors, notifications); + const privileges = usePrivileges(privilegesAPIClient, fatalErrors); + const spaces = useSpaces(http, fatalErrors, spacesEnabled); + const features = useFeatures(http, fatalErrors); + const [role, setRole] = useRole( + rolesAPIClient, + fatalErrors, + notifications, + license, + action, + roleName + ); + + if (!role || !runAsUsers || !indexPatternsTitles || !privileges || !spaces || !features) { + return null; + } + + const isEditingExistingRole = !!roleName && action === 'edit'; + const isReadOnlyRole = checkIfRoleReadOnly(role); + const isReservedRole = checkIfRoleReserved(role); + + const [kibanaPrivileges, builtInESPrivileges] = privileges; + + const getFormTitle = () => { + let titleText; + const props: HTMLProps = { + tabIndex: 0, + }; + if (isReservedRole) { + titleText = ( + + ); + props['aria-describedby'] = 'reservedRoleDescription'; + } else if (isEditingExistingRole) { + titleText = ( + + ); + } else { + titleText = ( + + ); + } + + return ( + +

    + {titleText} +

    +
    + ); + }; + + const getActionButton = () => { + if (isEditingExistingRole && !isReadOnlyRole) { + return ( + + + + ); + } + + return null; + }; + + const getRoleName = () => { + return ( + + + } + helpText={ + !isReservedRole && isEditingExistingRole ? ( + + ) : ( + undefined + ) + } + {...validator.validateRoleName(role)} + > + + + + ); + }; + + const onNameChange = (e: ChangeEvent) => + setRole({ + ...role, + name: e.target.value.replace(/\s/g, '_'), + }); + + const getElasticsearchPrivileges = () => { + return ( +
    + + +
    + ); + }; + + const onRoleChange = (newRole: Role) => setRole(newRole); + + const getKibanaPrivileges = () => { + return ( +
    + + +
    + ); + }; + + const getFormButtons = () => { + if (isReadOnlyRole) { + return getReturnToRoleListButton(); + } + + return ( + + {getSaveButton()} + {getCancelButton()} + + {getActionButton()} + + ); + }; + + const getReturnToRoleListButton = () => { + return ( + + + + ); + }; + + const getSaveButton = () => { + const saveText = isEditingExistingRole ? ( + + ) : ( + + ); + + return ( + + {saveText} + + ); + }; + + const getCancelButton = () => { + return ( + + + + ); + }; + + const saveRole = async () => { + validator.enableValidation(); + + const result = validator.validateForSave(role); + if (result.isInvalid) { + setFormError(result); + } else { + setFormError(null); + + try { + await rolesAPIClient.saveRole({ role, spacesEnabled }); + } catch (error) { + notifications.toasts.addDanger(get(error, 'data.message')); + return; + } + + notifications.toasts.addSuccess( + i18n.translate( + 'xpack.security.management.editRole.roleSuccessfullySavedNotificationMessage', + { defaultMessage: 'Saved role' } + ) + ); + + backToRoleList(); + } + }; + + const handleDeleteRole = async () => { + try { + await rolesAPIClient.deleteRole(role.name); + } catch (error) { + notifications.toasts.addDanger(get(error, 'data.message')); + return; + } + + notifications.toasts.addSuccess( + i18n.translate( + 'xpack.security.management.editRole.roleSuccessfullyDeletedNotificationMessage', + { defaultMessage: 'Deleted role' } + ) + ); + + backToRoleList(); + }; + + const description = spacesEnabled ? ( + + ) : ( + + ); + + return ( +
    + + {getFormTitle()} + + + + {description} + + {isReservedRole && ( + + + +

    + +

    +
    +
    + )} + + + + {getRoleName()} + + {getElasticsearchPrivileges()} + + {getKibanaPrivileges()} + + + + {getFormButtons()} +
    +
    + ); +}; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/index.ts rename to x-pack/plugins/security/public/management/roles/edit_role/index.ts diff --git a/x-pack/legacy/plugins/security/public/lib/privilege_utils.test.ts b/x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.test.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/lib/privilege_utils.test.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.test.ts diff --git a/x-pack/legacy/plugins/security/public/lib/privilege_utils.ts b/x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.ts similarity index 93% rename from x-pack/legacy/plugins/security/public/lib/privilege_utils.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.ts index 74bde71dc421ab..3fd8536951967a 100644 --- a/x-pack/legacy/plugins/security/public/lib/privilege_utils.ts +++ b/x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RoleKibanaPrivilege } from '../../common/model'; +import { RoleKibanaPrivilege } from '../../../../common/model'; /** * Determines if the passed privilege spec defines global privileges. diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/_index.scss new file mode 100644 index 00000000000000..a1a9d038065e61 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/_index.scss @@ -0,0 +1,2 @@ +@import './privilege_feature_icon'; +@import './kibana/index'; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/_privilege_feature_icon.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/_privilege_feature_icon.scss new file mode 100644 index 00000000000000..a7f24c96a28216 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/_privilege_feature_icon.scss @@ -0,0 +1,4 @@ +.secPrivilegeFeatureIcon { + flex-shrink: 0; + margin-right: $euiSizeS; +} diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap similarity index 87% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap index 795131337c31fd..323629de7578d7 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap @@ -15,7 +15,7 @@ exports[`it renders without crashing 1`] = ` /> { + expect(shallowWithIntl()).toMatchSnapshot(); +}); + +test('it renders ClusterPrivileges', () => { + expect( + mountWithIntl().find(ClusterPrivileges) + ).toHaveLength(1); +}); + +test('it renders IndexPrivileges', () => { + expect( + mountWithIntl().find(IndexPrivileges) + ).toHaveLength(1); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx similarity index 89% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx index c0e6db3fef21c8..96249ccf3ff87e 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx @@ -7,7 +7,6 @@ import { EuiButton, EuiComboBox, - // @ts-ignore EuiDescribedFormGroup, EuiFormRow, EuiHorizontalRule, @@ -19,26 +18,26 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { Component, Fragment } from 'react'; -import { Role, BuiltinESPrivileges } from '../../../../../../../common/model'; -// @ts-ignore -import { documentationLinks } from '../../../../../../documentation_links'; -import { RoleValidator } from '../../../lib/validate_role'; +import { Role, BuiltinESPrivileges } from '../../../../../../common/model'; +import { SecurityLicense } from '../../../../../../common/licensing'; +import { IndicesAPIClient } from '../../../indices_api_client'; +import { RoleValidator } from '../../validate_role'; import { CollapsiblePanel } from '../../collapsible_panel'; import { ClusterPrivileges } from './cluster_privileges'; - import { IndexPrivileges } from './index_privileges'; +import { DocumentationLinksService } from '../../../documentation_links'; interface Props { role: Role; editable: boolean; - httpClient: any; + indicesAPIClient: PublicMethodsOf; + docLinks: DocumentationLinksService; + license: SecurityLicense; onChange: (role: Role) => void; runAsUsers: string[]; validator: RoleValidator; builtinESPrivileges: BuiltinESPrivileges; indexPatterns: string[]; - allowDocumentLevelSecurity: boolean; - allowFieldLevelSecurity: boolean; } export class ElasticsearchPrivileges extends Component { @@ -53,23 +52,22 @@ export class ElasticsearchPrivileges extends Component { public getForm = () => { const { role, - httpClient, + indicesAPIClient, + docLinks, validator, onChange, editable, indexPatterns, - allowDocumentLevelSecurity, - allowFieldLevelSecurity, + license, builtinESPrivileges, } = this.props; const indexProps = { role, - httpClient, + indicesAPIClient, validator, indexPatterns, - allowDocumentLevelSecurity, - allowFieldLevelSecurity, + license, onChange, availableIndexPrivileges: builtinESPrivileges.index, }; @@ -91,7 +89,7 @@ export class ElasticsearchPrivileges extends Component { id="xpack.security.management.editRole.elasticSearchPrivileges.manageRoleActionsDescription" defaultMessage="Manage the actions this role can perform against your cluster. " /> - {this.learnMore(documentationLinks.esClusterPrivileges)} + {this.learnMore(docLinks.getESClusterPrivilegesDocUrl())}

    } > @@ -121,7 +119,7 @@ export class ElasticsearchPrivileges extends Component { id="xpack.security.management.editRole.elasticSearchPrivileges.howToBeSubmittedOnBehalfOfOtherUsersDescription" defaultMessage="Allow requests to be submitted on the behalf of other users. " /> - {this.learnMore(documentationLinks.esRunAsPrivileges)} + {this.learnMore(docLinks.getESRunAsPrivilegesDocUrl())}

    } > @@ -165,7 +163,7 @@ export class ElasticsearchPrivileges extends Component { id="xpack.security.management.editRole.elasticSearchPrivileges.controlAccessToClusterDataDescription" defaultMessage="Control access to the data in your cluster. " /> - {this.learnMore(documentationLinks.esIndicesPrivileges)} + {this.learnMore(docLinks.getESIndicesPrivilegesDocUrl())}

    diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.test.tsx similarity index 99% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.test.tsx index 6d386fd78a11b1..5e2da513143653 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.test.tsx @@ -6,7 +6,7 @@ import { EuiButtonIcon, EuiTextArea } from '@elastic/eui'; import React from 'react'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { RoleValidator } from '../../../lib/validate_role'; +import { RoleValidator } from '../../validate_role'; import { IndexPrivilegeForm } from './index_privilege_form'; test('it renders without crashing', () => { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.tsx similarity index 98% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.tsx index bafc56dc167ea5..15e0367c2b6dc1 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.tsx @@ -19,8 +19,8 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import _ from 'lodash'; import React, { ChangeEvent, Component, Fragment } from 'react'; -import { RoleIndexPrivilege } from '../../../../../../../common/model'; -import { RoleValidator } from '../../../lib/validate_role'; +import { RoleIndexPrivilege } from '../../../../../../common/model'; +import { RoleValidator } from '../../validate_role'; const fromOption = (option: any) => option.label; const toOption = (value: string) => ({ label: value }); @@ -164,7 +164,6 @@ export class IndexPrivilegeForm extends Component { {!isReadOnlyRole && ( { - // @ts-ignore missing "compressed" prop definition { } return ( - // @ts-ignore {!this.props.isReadOnlyRole && ( { - // @ts-ignore missing "compressed" proptype new Promise(setImmediate); + +test('it renders without crashing', async () => { + const license = licenseMock.create(); + license.getFeatures.mockReturnValue({ + allowRoleFieldLevelSecurity: true, + allowRoleDocumentLevelSecurity: true, + } as any); + + const props = { + role: { + name: '', + kibana: [], + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + }, + onChange: jest.fn(), + indexPatterns: [], + editable: true, + validator: new RoleValidator(), + availableIndexPrivileges: ['all', 'read', 'write', 'index'], + indicesAPIClient: indicesAPIClientMock.create(), + license, + }; + const wrapper = shallowWithIntl(); + await flushPromises(); + expect(wrapper).toMatchSnapshot(); +}); + +test('it renders a IndexPrivilegeForm for each privilege on the role', async () => { + const license = licenseMock.create(); + license.getFeatures.mockReturnValue({ + allowRoleFieldLevelSecurity: true, + allowRoleDocumentLevelSecurity: true, + } as any); + + const props = { + role: { + name: '', + kibana: [], + elasticsearch: { + cluster: [], + indices: [ + { + names: ['foo*'], + privileges: ['all'], + query: '*', + field_security: { + grant: ['some_field'], + }, + }, + ], + run_as: [], + }, + }, + onChange: jest.fn(), + indexPatterns: [], + editable: true, + validator: new RoleValidator(), + availableIndexPrivileges: ['all', 'read', 'write', 'index'], + indicesAPIClient: indicesAPIClientMock.create(), + license, + }; + const wrapper = mountWithIntl(); + await flushPromises(); + expect(wrapper.find(IndexPrivilegeForm)).toHaveLength(1); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx similarity index 84% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx index f09084ad2bb382..2c745067fede2d 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx @@ -5,19 +5,23 @@ */ import _ from 'lodash'; import React, { Component, Fragment } from 'react'; -import { Role, RoleIndexPrivilege } from '../../../../../../../common/model'; -import { isReadOnlyRole, isRoleEnabled } from '../../../../../../lib/role_utils'; -import { getFields } from '../../../../../../objects'; -import { RoleValidator } from '../../../lib/validate_role'; +import { + Role, + RoleIndexPrivilege, + isReadOnlyRole, + isRoleEnabled, +} from '../../../../../../common/model'; +import { SecurityLicense } from '../../../../../../common/licensing'; +import { IndicesAPIClient } from '../../../indices_api_client'; +import { RoleValidator } from '../../validate_role'; import { IndexPrivilegeForm } from './index_privilege_form'; interface Props { role: Role; indexPatterns: string[]; availableIndexPrivileges: string[]; - allowDocumentLevelSecurity: boolean; - allowFieldLevelSecurity: boolean; - httpClient: any; + indicesAPIClient: PublicMethodsOf; + license: SecurityLicense; onChange: (role: Role) => void; validator: RoleValidator; } @@ -43,20 +47,16 @@ export class IndexPrivileges extends Component { public render() { const { indices = [] } = this.props.role.elasticsearch; - const { - indexPatterns, - allowDocumentLevelSecurity, - allowFieldLevelSecurity, - availableIndexPrivileges, - } = this.props; + const { indexPatterns, license, availableIndexPrivileges } = this.props; + const { allowRoleDocumentLevelSecurity, allowRoleFieldLevelSecurity } = license.getFeatures(); const props = { indexPatterns, // If editing an existing role while that has been disabled, always show the FLS/DLS fields because currently // a role is only marked as disabled if it has FLS/DLS setup (usually before the user changed to a license that // doesn't permit FLS/DLS). - allowDocumentLevelSecurity: allowDocumentLevelSecurity || !isRoleEnabled(this.props.role), - allowFieldLevelSecurity: allowFieldLevelSecurity || !isRoleEnabled(this.props.role), + allowDocumentLevelSecurity: allowRoleDocumentLevelSecurity || !isRoleEnabled(this.props.role), + allowFieldLevelSecurity: allowRoleFieldLevelSecurity || !isRoleEnabled(this.props.role), isReadOnlyRole: isReadOnlyRole(this.props.role), }; @@ -171,7 +171,7 @@ export class IndexPrivileges extends Component { try { return { - [pattern]: await getFields(this.props.httpClient, pattern), + [pattern]: await this.props.indicesAPIClient.getFields(pattern), }; } catch (e) { return { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/index.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/_index.scss new file mode 100644 index 00000000000000..19547c0e1953e0 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/_index.scss @@ -0,0 +1,2 @@ +@import './feature_table/index'; +@import './space_aware_privilege_section/index'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/lib/constants.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/constants.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/lib/constants.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/constants.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_change_all_privileges.scss similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/_index.scss rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_change_all_privileges.scss diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_index.scss new file mode 100644 index 00000000000000..6a96553742819f --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_index.scss @@ -0,0 +1 @@ +@import './change_all_privileges'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/change_all_privileges.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.tsx similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/change_all_privileges.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.tsx diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx similarity index 94% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx index 9648bf1d111bf4..dea42e16f99d42 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx @@ -3,12 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -// @ts-ignore import { EuiInMemoryTable } from '@elastic/eui'; import React from 'react'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { FeaturesPrivileges, KibanaPrivileges, Role } from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator'; +import { FeaturesPrivileges, KibanaPrivileges, Role } from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; import { FeatureTable } from './feature_table'; const defaultPrivilegeDefinition = new KibanaPrivileges({ @@ -113,7 +112,6 @@ describe('FeatureTable', () => { onChange={jest.fn()} onChangeAll={jest.fn()} spacesIndex={0} - intl={null as any} /> ); @@ -141,7 +139,6 @@ describe('FeatureTable', () => { onChange={jest.fn()} onChangeAll={jest.fn()} spacesIndex={-1} - intl={null as any} /> ); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx similarity index 91% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx index a05dc687fce4ac..8283efe23260af 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx @@ -4,28 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ +import _ from 'lodash'; +import React, { Component } from 'react'; import { - // @ts-ignore EuiButtonGroup, EuiIcon, EuiIconTip, - // @ts-ignore EuiInMemoryTable, EuiText, IconType, } from '@elastic/eui'; -import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; -import _ from 'lodash'; -import React, { Component } from 'react'; -import { Feature } from '../../../../../../../../../../../plugins/features/public'; -import { FeaturesPrivileges, KibanaPrivileges, Role } from '../../../../../../../../common/model'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { Feature } from '../../../../../../../../features/public'; +import { FeaturesPrivileges, KibanaPrivileges, Role } from '../../../../../../../common/model'; import { AllowedPrivilege, CalculatedPrivilege, PrivilegeExplanation, -} from '../../../../../../../lib/kibana_privilege_calculator'; -import { isGlobalPrivilegeDefinition } from '../../../../../../../lib/privilege_utils'; -import { NO_PRIVILEGE_VALUE } from '../../../../lib/constants'; +} from '../kibana_privilege_calculator'; +import { isGlobalPrivilegeDefinition } from '../../../privilege_utils'; +import { NO_PRIVILEGE_VALUE } from '../constants'; import { PrivilegeDisplay } from '../space_aware_privilege_section/privilege_display'; import { ChangeAllPrivilegesControl } from './change_all_privileges'; @@ -36,7 +35,6 @@ interface Props { allowedPrivileges: AllowedPrivilege; rankedFeaturePrivileges: FeaturesPrivileges; kibanaPrivileges: KibanaPrivileges; - intl: InjectedIntl; spacesIndex: number; onChange: (featureId: string, privileges: string[]) => void; onChangeAll: (privileges: string[]) => void; @@ -100,9 +98,7 @@ export class FeatureTable extends Component { const availablePrivileges = Object.values(rankedFeaturePrivileges)[0]; return ( - // @ts-ignore missing responsive from typedef { private getColumns = (availablePrivileges: string[]) => [ { field: 'feature', - name: this.props.intl.formatMessage({ - id: 'xpack.security.management.editRole.featureTable.enabledRoleFeaturesFeatureColumnTitle', - defaultMessage: 'Feature', - }), + name: i18n.translate( + 'xpack.security.management.editRole.featureTable.enabledRoleFeaturesFeatureColumnTitle', + { defaultMessage: 'Feature' } + ), render: (feature: TableFeature) => { let tooltipElement = null; if (feature.privilegesTooltip) { @@ -239,9 +235,7 @@ export class FeatureTable extends Component { }); return ( - // @ts-ignore missing name from typedef void; validator: RoleValidator; - intl: InjectedIntl; } export class KibanaPrivilegesRegion extends Component { @@ -81,7 +79,6 @@ export class KibanaPrivilegesRegion extends Component { privilegeCalculatorFactory={privilegeCalculatorFactory} onChange={onChange} editable={editable} - intl={this.props.intl} /> ); } diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/index.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/privilege_selector.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/privilege_selector.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx index 135419cc9a10d2..bda0227372c094 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/privilege_selector.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx @@ -6,7 +6,7 @@ import { EuiSelect } from '@elastic/eui'; import React, { ChangeEvent, Component } from 'react'; -import { NO_PRIVILEGE_VALUE } from '../../../../lib/constants'; +import { NO_PRIVILEGE_VALUE } from '../constants'; interface Props { ['data-test-subj']: string; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx index f97fa93294ff5b..db1e3cfd616212 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx @@ -3,13 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -// @ts-ignore + import { EuiButtonGroup, EuiButtonGroupProps, EuiComboBox, EuiSuperSelect } from '@elastic/eui'; import React from 'react'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { Feature } from '../../../../../../../../../../../plugins/features/public'; -import { KibanaPrivileges, Role } from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator'; +import { Feature } from '../../../../../../../../features/public'; +import { KibanaPrivileges, Role } from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; import { SimplePrivilegeSection } from './simple_privilege_section'; import { UnsupportedSpacePrivilegesWarning } from './unsupported_space_privileges_warning'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx similarity index 94% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx index 7768dc769a32f7..2221fc6bab2797 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx @@ -6,21 +6,24 @@ import { EuiComboBox, - // @ts-ignore EuiDescribedFormGroup, EuiFormRow, EuiSuperSelect, EuiText, } from '@elastic/eui'; -import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; +import { FormattedMessage } from '@kbn/i18n/react'; import React, { Component, Fragment } from 'react'; -import { Feature } from '../../../../../../../../../../../plugins/features/public'; -import { KibanaPrivileges, Role, RoleKibanaPrivilege } from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator'; -import { isGlobalPrivilegeDefinition } from '../../../../../../../lib/privilege_utils'; -import { copyRole } from '../../../../../../../lib/role_utils'; -import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../../../../lib/constants'; +import { Feature } from '../../../../../../../../features/public'; +import { + KibanaPrivileges, + Role, + RoleKibanaPrivilege, + copyRole, +} from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; +import { isGlobalPrivilegeDefinition } from '../../../privilege_utils'; +import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../constants'; import { FeatureTable } from '../feature_table'; import { UnsupportedSpacePrivilegesWarning } from './unsupported_space_privileges_warning'; @@ -31,7 +34,6 @@ interface Props { features: Feature[]; onChange: (role: Role) => void; editable: boolean; - intl: InjectedIntl; } interface State { @@ -230,7 +232,6 @@ export class SimplePrivilegeSection extends Component { allowedPrivileges={allowedPrivileges} rankedFeaturePrivileges={privilegeCalculator.rankedFeaturePrivileges} features={this.props.features} - intl={this.props.intl} onChange={this.onFeaturePrivilegeChange} onChangeAll={this.onChangeAllFeaturePrivileges} spacesIndex={this.props.role.kibana.findIndex(k => isGlobalPrivilegeDefinition(k))} diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts similarity index 94% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts index d412ba63403e19..428836c9f181b9 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RawKibanaPrivileges } from '../../../../../../../../../common/model'; +import { RawKibanaPrivileges } from '../../../../../../../../common/model'; export const rawKibanaPrivileges: RawKibanaPrivileges = { global: { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap similarity index 82% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap index c20a391cdb20c5..e9f2f946e98859 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap @@ -351,108 +351,6 @@ exports[` renders without crashing 1`] = ` } disabled={true} features={Array []} - intl={ - Object { - "defaultFormats": Object {}, - "defaultLocale": "en", - "formatDate": [Function], - "formatHTMLMessage": [Function], - "formatMessage": [Function], - "formatNumber": [Function], - "formatPlural": [Function], - "formatRelative": [Function], - "formatTime": [Function], - "formats": Object { - "date": Object { - "full": Object { - "day": "numeric", - "month": "long", - "weekday": "long", - "year": "numeric", - }, - "long": Object { - "day": "numeric", - "month": "long", - "year": "numeric", - }, - "medium": Object { - "day": "numeric", - "month": "short", - "year": "numeric", - }, - "short": Object { - "day": "numeric", - "month": "numeric", - "year": "2-digit", - }, - }, - "number": Object { - "currency": Object { - "style": "currency", - }, - "percent": Object { - "style": "percent", - }, - }, - "relative": Object { - "days": Object { - "units": "day", - }, - "hours": Object { - "units": "hour", - }, - "minutes": Object { - "units": "minute", - }, - "months": Object { - "units": "month", - }, - "seconds": Object { - "units": "second", - }, - "years": Object { - "units": "year", - }, - }, - "time": Object { - "full": Object { - "hour": "numeric", - "minute": "numeric", - "second": "numeric", - "timeZoneName": "short", - }, - "long": Object { - "hour": "numeric", - "minute": "numeric", - "second": "numeric", - "timeZoneName": "short", - }, - "medium": Object { - "hour": "numeric", - "minute": "numeric", - "second": "numeric", - }, - "short": Object { - "hour": "numeric", - "minute": "numeric", - }, - }, - }, - "formatters": Object { - "getDateTimeFormat": [Function], - "getMessageFormat": [Function], - "getNumberFormat": [Function], - "getPluralFormat": [Function], - "getRelativeFormat": [Function], - }, - "locale": "en", - "messages": Object {}, - "now": [Function], - "onError": [Function], - "textComponent": Symbol(react.fragment), - "timeZone": null, - } - } kibanaPrivileges={ KibanaPrivileges { "rawKibanaPrivileges": Object { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_index.scss similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_index.scss rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_index.scss diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss similarity index 87% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss index 5f9fbced5ee6ac..8f47727fdf8d62 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss @@ -9,6 +9,6 @@ .secPrivilegeMatrix__row--isBasePrivilege, .secPrivilegeMatrix__cell--isGlobalPrivilege, -.secPrivilegeTable__row--isGlobalSpace, { +.secPrivilegeTable__row--isGlobalSpace { background-color: $euiColorLightestShade; } diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/index.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx similarity index 96% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx index 62e22050132fd7..c6268e19abfd1f 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx @@ -7,7 +7,7 @@ import { EuiIconTip, EuiText, EuiToolTip } from '@elastic/eui'; import React from 'react'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { PRIVILEGE_SOURCE } from '../../../../../../../lib/kibana_privilege_calculator'; +import { PRIVILEGE_SOURCE } from '../kibana_privilege_calculator'; import { PrivilegeDisplay } from './privilege_display'; describe('PrivilegeDisplay', () => { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx similarity index 96% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx index 6af7672f6fef86..55ac99da4c8c16 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx @@ -7,11 +7,8 @@ import { EuiIcon, EuiIconTip, EuiText, IconType, PropsOf, EuiToolTip } from '@el import { FormattedMessage } from '@kbn/i18n/react'; import _ from 'lodash'; import React, { ReactNode, FC } from 'react'; -import { - PRIVILEGE_SOURCE, - PrivilegeExplanation, -} from '../../../../../../../lib/kibana_privilege_calculator'; -import { NO_PRIVILEGE_VALUE } from '../../../../lib/constants'; +import { PRIVILEGE_SOURCE, PrivilegeExplanation } from '../kibana_privilege_calculator'; +import { NO_PRIVILEGE_VALUE } from '../constants'; interface Props extends PropsOf { privilege: string | string[] | undefined; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx similarity index 89% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx index ee121caa13a2af..16aad4826ae44c 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx @@ -3,14 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -// @ts-ignore + import { EuiButtonEmpty, EuiInMemoryTable } from '@elastic/eui'; import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { Space } from '../../../../../../../../../spaces/common/model/space'; -import { Feature } from '../../../../../../../../../../../plugins/features/public'; -import { KibanaPrivileges, Role } from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../..//lib/kibana_privilege_calculator'; +import { Space } from '../../../../../../../../spaces/common/model/space'; +import { Feature } from '../../../../../../../../features/public'; +import { KibanaPrivileges, Role } from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; import { PrivilegeMatrix } from './privilege_matrix'; describe('PrivilegeMatrix', () => { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx similarity index 93% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx index 962487312c83df..b3449e32c6c917 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx @@ -8,7 +8,6 @@ import { EuiButtonEmpty, EuiIcon, EuiIconTip, - // @ts-ignore EuiInMemoryTable, EuiModal, EuiModalBody, @@ -16,18 +15,16 @@ import { EuiModalHeader, EuiModalHeaderTitle, EuiOverlayMask, - // @ts-ignore - EuiToolTip, IconType, } from '@elastic/eui'; import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; import React, { Component, Fragment } from 'react'; -import { Space } from '../../../../../../../../../spaces/common/model/space'; -import { SpaceAvatar } from '../../../../../../../../../spaces/public/space_avatar'; -import { Feature } from '../../../../../../../../../../../plugins/features/public'; -import { FeaturesPrivileges, Role } from '../../../../../../../../common/model'; -import { CalculatedPrivilege } from '../../../../../../../lib/kibana_privilege_calculator'; -import { isGlobalPrivilegeDefinition } from '../../../../../../../lib/privilege_utils'; +import { SpaceAvatar } from '../../../../../../../../../legacy/plugins/spaces/public/space_avatar'; +import { Space } from '../../../../../../../../spaces/common/model/space'; +import { Feature } from '../../../../../../../../features/public'; +import { FeaturesPrivileges, Role } from '../../../../../../../common/model'; +import { CalculatedPrivilege } from '../kibana_privilege_calculator'; +import { isGlobalPrivilegeDefinition } from '../../../privilege_utils'; import { SpacesPopoverList } from '../../../spaces_popover_list'; import { PrivilegeDisplay } from './privilege_display'; @@ -258,11 +255,9 @@ export class PrivilegeMatrix extends Component { ]; return ( - // @ts-ignore missing rowProps from typedef { return { className: item.feature.isBase ? 'secPrivilegeMatrix__row--isBasePrivilege' : '', diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx index 2b7d87f663d729..675f02a81f9e1d 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx @@ -9,8 +9,8 @@ import { merge } from 'lodash'; // @ts-ignore import { findTestSubject } from '@elastic/eui/lib/test'; import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers'; -import { KibanaPrivileges } from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator'; +import { KibanaPrivileges } from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; import { PrivilegeSpaceForm } from './privilege_space_form'; import { rawKibanaPrivileges } from './__fixtures__'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx similarity index 96% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx index 5abb87d23bb6e6..6d1f5117c52e98 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx @@ -24,17 +24,16 @@ import { } from '@elastic/eui'; import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; import React, { Component, Fragment } from 'react'; -import { Space } from '../../../../../../../../../spaces/common/model/space'; -import { Feature } from '../../../../../../../../../../../plugins/features/public'; -import { KibanaPrivileges, Role } from '../../../../../../../../common/model'; +import { Space } from '../../../../../../../../spaces/common/model/space'; +import { Feature } from '../../../../../../../../features/public'; +import { KibanaPrivileges, Role, copyRole } from '../../../../../../../common/model'; import { AllowedPrivilege, KibanaPrivilegeCalculatorFactory, PrivilegeExplanation, -} from '../../../../../../../lib/kibana_privilege_calculator'; -import { hasAssignedFeaturePrivileges } from '../../../../../../../lib/privilege_utils'; -import { copyRole } from '../../../../../../../lib/role_utils'; -import { CUSTOM_PRIVILEGE_VALUE } from '../../../../lib/constants'; +} from '../kibana_privilege_calculator'; +import { hasAssignedFeaturePrivileges } from '../../../privilege_utils'; +import { CUSTOM_PRIVILEGE_VALUE } from '../constants'; import { FeatureTable } from '../feature_table'; import { SpaceSelector } from './space_selector'; @@ -285,7 +284,6 @@ export class PrivilegeSpaceForm extends Component { calculatedPrivileges={calculatedPrivileges} allowedPrivileges={allowedPrivileges} rankedFeaturePrivileges={privilegeCalculator.rankedFeaturePrivileges} - intl={this.props.intl} onChange={this.onFeaturePrivilegesChange} onChangeAll={this.onChangeAllFeaturePrivileges} kibanaPrivileges={this.props.kibanaPrivileges} diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx similarity index 99% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx index 37ee43c5473b0d..f0a391c98c9100 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx @@ -10,8 +10,8 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { ReactWrapper } from 'enzyme'; import { PrivilegeSpaceTable } from './privilege_space_table'; import { PrivilegeDisplay } from './privilege_display'; -import { KibanaPrivileges, Role, RoleKibanaPrivilege } from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator'; +import { KibanaPrivileges, Role, RoleKibanaPrivilege } from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; import { rawKibanaPrivileges } from './__fixtures__'; interface TableRow { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx similarity index 94% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx index 65a3df9fb47a1a..1c27ec84f50dcd 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx @@ -12,22 +12,21 @@ import { EuiBasicTableColumn, } from '@elastic/eui'; import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; -import _ from 'lodash'; import React, { Component } from 'react'; -import { getSpaceColor } from '../../../../../../../../../spaces/public/space_avatar'; -import { Space } from '../../../../../../../../../spaces/common/model/space'; +import { getSpaceColor } from '../../../../../../../../../legacy/plugins/spaces/public/space_avatar'; +import { Space } from '../../../../../../../../spaces/common/model/space'; import { FeaturesPrivileges, Role, RoleKibanaPrivilege, -} from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator'; + copyRole, +} from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; import { isGlobalPrivilegeDefinition, hasAssignedFeaturePrivileges, -} from '../../../../../../../lib/privilege_utils'; -import { copyRole } from '../../../../../../../lib/role_utils'; -import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../../../../lib/constants'; +} from '../../../privilege_utils'; +import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../constants'; import { SpacesPopoverList } from '../../../spaces_popover_list'; import { PrivilegeDisplay } from './privilege_display'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx index 2756b1c4472744..e06d2a4f7dc337 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx @@ -6,9 +6,9 @@ import React from 'react'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { KibanaPrivileges } from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator'; -import { RoleValidator } from '../../../../lib/validate_role'; +import { KibanaPrivileges } from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; +import { RoleValidator } from '../../../validate_role'; import { PrivilegeMatrix } from './privilege_matrix'; import { PrivilegeSpaceForm } from './privilege_space_form'; import { PrivilegeSpaceTable } from './privilege_space_table'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx similarity index 93% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx index d324cf99c8418a..21cadfafe1790b 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx @@ -14,13 +14,12 @@ import { import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import _ from 'lodash'; import React, { Component, Fragment } from 'react'; -import { UICapabilities } from 'ui/capabilities'; -import { Space } from '../../../../../../../../../spaces/common/model/space'; -import { Feature } from '../../../../../../../../../../../plugins/features/public'; -import { KibanaPrivileges, Role } from '../../../../../../../../common/model'; -import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator'; -import { isReservedRole } from '../../../../../../../lib/role_utils'; -import { RoleValidator } from '../../../../lib/validate_role'; +import { Capabilities } from 'src/core/public'; +import { Space } from '../../../../../../../../spaces/common/model/space'; +import { Feature } from '../../../../../../../../features/public'; +import { KibanaPrivileges, Role, isReservedRole } from '../../../../../../../common/model'; +import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator'; +import { RoleValidator } from '../../../validate_role'; import { PrivilegeMatrix } from './privilege_matrix'; import { PrivilegeSpaceForm } from './privilege_space_form'; import { PrivilegeSpaceTable } from './privilege_space_table'; @@ -34,7 +33,7 @@ interface Props { editable: boolean; validator: RoleValidator; intl: InjectedIntl; - uiCapabilities: UICapabilities; + uiCapabilities: Capabilities; features: Feature[]; } diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_selector.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_selector.tsx similarity index 93% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_selector.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_selector.tsx index 0eb9cf0b0ee9d7..cfeb5b9f37d8ce 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_selector.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_selector.tsx @@ -7,8 +7,8 @@ import { EuiComboBox, EuiComboBoxOptionProps, EuiHealth, EuiHighlight } from '@elastic/eui'; import { InjectedIntl } from '@kbn/i18n/react'; import React, { Component } from 'react'; -import { Space } from '../../../../../../../../../spaces/common/model/space'; -import { getSpaceColor } from '../../../../../../../../../spaces/public/space_avatar'; +import { getSpaceColor } from '../../../../../../../../../legacy/plugins/spaces/public/space_avatar'; +import { Space } from '../../../../../../../../spaces/common/model/space'; const spaceToOption = (space?: Space, currentSelection?: 'global' | 'spaces') => { if (!space) { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/transform_error_section/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/transform_error_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/transform_error_section/index.ts rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/transform_error_section/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/transform_error_section/transform_error_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/transform_error_section/transform_error_section.tsx similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/transform_error_section/transform_error_section.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/transform_error_section/transform_error_section.tsx diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.test.tsx similarity index 96% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.test.tsx index 9b483d92cde41b..d29b442420a90c 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.test.tsx @@ -7,7 +7,7 @@ import { EuiIcon } from '@elastic/eui'; import { shallow } from 'enzyme'; import React from 'react'; -import { Role } from '../../../../../common/model'; +import { Role } from '../../../../common/model'; import { ReservedRoleBadge } from './reserved_role_badge'; const reservedRole: Role = { diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.tsx b/x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.tsx similarity index 89% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.tsx index 3d817d1e07d212..501ca7589dafde 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.tsx @@ -8,8 +8,7 @@ import React from 'react'; import { EuiIcon, EuiToolTip } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Role } from '../../../../../common/model'; -import { isReservedRole } from '../../../../lib/role_utils'; +import { Role, isReservedRole } from '../../../../common/model'; interface Props { role: Role; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_index.scss new file mode 100644 index 00000000000000..b40a32cb8df96b --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_index.scss @@ -0,0 +1 @@ +@import './spaces_popover_list'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/_spaces_popover_list.scss b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_spaces_popover_list.scss similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/_spaces_popover_list.scss rename to x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_spaces_popover_list.scss diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/index.ts rename to x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/spaces_popover_list.tsx b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/spaces_popover_list.tsx similarity index 95% rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/spaces_popover_list.tsx rename to x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/spaces_popover_list.tsx index a99e389044eaad..bb7a6db97f7c88 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/spaces_popover_list.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/spaces_popover_list.tsx @@ -14,9 +14,9 @@ import { } from '@elastic/eui'; import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react'; import React, { Component } from 'react'; -import { SpaceAvatar } from '../../../../../../../spaces/public/space_avatar'; -import { SPACE_SEARCH_COUNT_THRESHOLD } from '../../../../../../../../../plugins/spaces/common/constants'; -import { Space } from '../../../../../../../../../plugins/spaces/common/model/space'; +import { SpaceAvatar } from '../../../../../../../legacy/plugins/spaces/public/space_avatar'; +import { SPACE_SEARCH_COUNT_THRESHOLD } from '../../../../../../spaces/common'; +import { Space } from '../../../../../../spaces/common/model/space'; interface Props { spaces: Space[]; @@ -146,7 +146,6 @@ export class SpacesPopoverList extends Component { return (
    { - // @ts-ignore onSearch isn't defined on the type ({ + getFields: jest.fn(), + }), +}; diff --git a/x-pack/plugins/security/public/management/roles/indices_api_client.ts b/x-pack/plugins/security/public/management/roles/indices_api_client.ts new file mode 100644 index 00000000000000..65d9a40a776eb0 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/indices_api_client.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpStart } from 'src/core/public'; + +export class IndicesAPIClient { + constructor(private readonly http: HttpStart) {} + + async getFields(query: string) { + return ( + (await this.http.get(`/internal/security/fields/${encodeURIComponent(query)}`)) || + [] + ); + } +} diff --git a/x-pack/plugins/security/public/management/roles/privileges_api_client.mock.ts b/x-pack/plugins/security/public/management/roles/privileges_api_client.mock.ts new file mode 100644 index 00000000000000..2564914a1d3d83 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/privileges_api_client.mock.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; + * you may not use this file except in compliance with the Elastic License. + */ + +export const privilegesAPIClientMock = { + create: () => ({ + getAll: jest.fn(), + getBuiltIn: jest.fn(), + }), +}; diff --git a/x-pack/plugins/security/public/management/roles/privileges_api_client.ts b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts new file mode 100644 index 00000000000000..45bd2fd8fb3a6a --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpStart } from 'src/core/public'; +import { BuiltinESPrivileges, RawKibanaPrivileges } from '../../../common/model'; + +export class PrivilegesAPIClient { + constructor(private readonly http: HttpStart) {} + + async getAll({ includeActions }: { includeActions: boolean }) { + return await this.http.get('/api/security/privileges', { + query: { includeActions }, + }); + } + + async getBuiltIn() { + return await this.http.get('/internal/security/esPrivileges/builtin'); + } +} diff --git a/x-pack/plugins/security/public/management/roles/roles_api_client.mock.ts b/x-pack/plugins/security/public/management/roles/roles_api_client.mock.ts new file mode 100644 index 00000000000000..c4d3724c0ecb5f --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/roles_api_client.mock.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const rolesAPIClientMock = { + create: () => ({ + getRoles: jest.fn(), + getRole: jest.fn(), + deleteRole: jest.fn(), + saveRole: jest.fn(), + }), +}; diff --git a/x-pack/plugins/security/public/management/roles/roles_api_client.test.ts b/x-pack/plugins/security/public/management/roles/roles_api_client.test.ts new file mode 100644 index 00000000000000..21a4f5c9499ec1 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/roles_api_client.test.ts @@ -0,0 +1,495 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Role } from '../../../common/model'; +import { RolesAPIClient } from './roles_api_client'; +import { httpServiceMock } from '../../../../../../src/core/public/mocks'; + +describe('RolesAPIClient', () => { + async function saveRole(role: Role, spacesEnabled: boolean) { + const httpMock = httpServiceMock.createStartContract(); + const rolesAPIClient = new RolesAPIClient(httpMock); + + await rolesAPIClient.saveRole({ role, spacesEnabled }); + expect(httpMock.put).toHaveBeenCalledTimes(1); + + return JSON.parse((httpMock.put.mock.calls[0] as any)[1]?.body as any); + } + + describe('spaces disabled', () => { + it('removes placeholder index privileges', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [{ names: [], privileges: [] }], + run_as: [], + }, + kibana: [], + }; + + const result = await saveRole(role, false); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [], + }); + }); + + it('removes placeholder query entries', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [{ names: ['.kibana*'], privileges: ['all'], query: '' }], + run_as: [], + }, + kibana: [], + }; + + const result = await saveRole(role, false); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [{ names: ['.kibana*'], privileges: ['all'] }], + run_as: [], + }, + kibana: [], + }); + }); + + it('removes transient fields not required for save', async () => { + const role: Role = { + name: 'my role', + transient_metadata: { + foo: 'bar', + }, + _transform_error: ['kibana'], + metadata: { + someOtherMetadata: true, + }, + _unrecognized_applications: ['foo'], + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [], + }; + + const result = await saveRole(role, false); + + expect(result).toEqual({ + metadata: { + someOtherMetadata: true, + }, + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [], + }); + }); + + it('does not remove actual query entries', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [{ names: ['.kibana*'], privileges: ['all'], query: 'something' }], + run_as: [], + }, + kibana: [], + }; + + const result = await saveRole(role, false); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [{ names: ['.kibana*'], privileges: ['all'], query: 'something' }], + run_as: [], + }, + kibana: [], + }); + }); + + it('should remove feature privileges if a corresponding base privilege is defined', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: ['all'], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }; + + const result = await saveRole(role, false); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: ['all'], + feature: {}, + }, + ], + }); + }); + + it('should not remove feature privileges if a corresponding base privilege is not defined', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }; + + const result = await saveRole(role, false); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }); + }); + + it('should remove space privileges', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + { + spaces: ['marketing'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }; + + const result = await saveRole(role, false); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }); + }); + }); + + describe('spaces enabled', () => { + it('removes placeholder index privileges', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [{ names: [], privileges: [] }], + run_as: [], + }, + kibana: [], + }; + + const result = await saveRole(role, true); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [], + }); + }); + + it('removes placeholder query entries', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [{ names: ['.kibana*'], privileges: ['all'], query: '' }], + run_as: [], + }, + kibana: [], + }; + + const result = await saveRole(role, true); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [{ names: ['.kibana*'], privileges: ['all'] }], + run_as: [], + }, + kibana: [], + }); + }); + + it('removes transient fields not required for save', async () => { + const role: Role = { + name: 'my role', + transient_metadata: { + foo: 'bar', + }, + _transform_error: ['kibana'], + metadata: { + someOtherMetadata: true, + }, + _unrecognized_applications: ['foo'], + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [], + }; + + const result = await saveRole(role, true); + + expect(result).toEqual({ + metadata: { + someOtherMetadata: true, + }, + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [], + }); + }); + + it('does not remove actual query entries', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [{ names: ['.kibana*'], privileges: ['all'], query: 'something' }], + run_as: [], + }, + kibana: [], + }; + + const result = await saveRole(role, true); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [{ names: ['.kibana*'], privileges: ['all'], query: 'something' }], + run_as: [], + }, + kibana: [], + }); + }); + + it('should remove feature privileges if a corresponding base privilege is defined', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['foo'], + base: ['all'], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }; + + const result = await saveRole(role, true); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['foo'], + base: ['all'], + feature: {}, + }, + ], + }); + }); + + it('should not remove feature privileges if a corresponding base privilege is not defined', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['foo'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }; + + const result = await saveRole(role, true); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['foo'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }); + }); + + it('should not remove space privileges', async () => { + const role: Role = { + name: 'my role', + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + { + spaces: ['marketing'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }; + + const result = await saveRole(role, true); + + expect(result).toEqual({ + elasticsearch: { + cluster: [], + indices: [], + run_as: [], + }, + kibana: [ + { + spaces: ['*'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + { + spaces: ['marketing'], + base: [], + feature: { + feature1: ['read'], + feature2: ['write'], + }, + }, + ], + }); + }); + }); +}); diff --git a/x-pack/plugins/security/public/management/roles/roles_api_client.ts b/x-pack/plugins/security/public/management/roles/roles_api_client.ts new file mode 100644 index 00000000000000..d7e98e03a965b7 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/roles_api_client.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpStart } from 'src/core/public'; +import { Role, RoleIndexPrivilege, copyRole } from '../../../common/model'; +import { isGlobalPrivilegeDefinition } from './edit_role/privilege_utils'; + +export class RolesAPIClient { + constructor(private readonly http: HttpStart) {} + + public async getRoles() { + return await this.http.get('/api/security/role'); + } + + public async getRole(roleName: string) { + return await this.http.get(`/api/security/role/${encodeURIComponent(roleName)}`); + } + + public async deleteRole(roleName: string) { + await this.http.delete(`/api/security/role/${encodeURIComponent(roleName)}`); + } + + public async saveRole({ role, spacesEnabled }: { role: Role; spacesEnabled: boolean }) { + await this.http.put(`/api/security/role/${encodeURIComponent(role.name)}`, { + body: JSON.stringify(this.transformRoleForSave(copyRole(role), spacesEnabled)), + }); + } + + private transformRoleForSave(role: Role, spacesEnabled: boolean) { + // Remove any placeholder index privileges + const isPlaceholderPrivilege = (indexPrivilege: RoleIndexPrivilege) => + indexPrivilege.names.length === 0; + role.elasticsearch.indices = role.elasticsearch.indices.filter( + indexPrivilege => !isPlaceholderPrivilege(indexPrivilege) + ); + + // Remove any placeholder query entries + role.elasticsearch.indices.forEach(index => index.query || delete index.query); + + // If spaces are disabled, then do not persist any space privileges + if (!spacesEnabled) { + role.kibana = role.kibana.filter(isGlobalPrivilegeDefinition); + } + + role.kibana.forEach(kibanaPrivilege => { + // If a base privilege is defined, then do not persist feature privileges + if (kibanaPrivilege.base.length > 0) { + kibanaPrivilege.feature = {}; + } + }); + + delete role.name; + delete role.transient_metadata; + delete role._unrecognized_applications; + delete role._transform_error; + + return role; + } +} diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/__snapshots__/roles_grid_page.test.tsx.snap b/x-pack/plugins/security/public/management/roles/roles_grid/__snapshots__/roles_grid_page.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/__snapshots__/roles_grid_page.test.tsx.snap rename to x-pack/plugins/security/public/management/roles/roles_grid/__snapshots__/roles_grid_page.test.tsx.snap diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx new file mode 100644 index 00000000000000..37eed3357241d5 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx @@ -0,0 +1,160 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Component, Fragment } from 'react'; +import { + EuiButton, + EuiButtonEmpty, + EuiModal, + EuiModalBody, + EuiModalFooter, + EuiModalHeader, + EuiModalHeaderTitle, + EuiOverlayMask, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NotificationsStart } from 'src/core/public'; +import { RolesAPIClient } from '../../roles_api_client'; + +interface Props { + rolesToDelete: string[]; + callback: (rolesToDelete: string[], errors: string[]) => void; + onCancel: () => void; + notifications: NotificationsStart; + rolesAPIClient: PublicMethodsOf; +} + +interface State { + deleteInProgress: boolean; +} + +export class ConfirmDelete extends Component { + constructor(props: Props) { + super(props); + this.state = { + deleteInProgress: false, + }; + } + + public render() { + const { rolesToDelete } = this.props; + const moreThanOne = rolesToDelete.length > 1; + const title = i18n.translate('xpack.security.management.roles.deleteRoleTitle', { + defaultMessage: 'Delete role{value, plural, one {{roleName}} other {s}}', + values: { value: rolesToDelete.length, roleName: ` ${rolesToDelete[0]}` }, + }); + + // This is largely the same as the built-in EuiConfirmModal component, but we needed the ability + // to disable the buttons since this could be a long-running operation + + return ( + + + + + {title} + + + + + {moreThanOne ? ( + +

    + +

    +
      + {rolesToDelete.map(roleName => ( +
    • {roleName}
    • + ))} +
    +
    + ) : null} +

    + +

    +
    +
    + + + + + + + + + +
    +
    + ); + } + + private onConfirmDelete = () => { + this.setState( + { + deleteInProgress: true, + }, + () => { + this.deleteRoles(); + } + ); + }; + + private deleteRoles = async () => { + const { rolesToDelete, callback, rolesAPIClient, notifications } = this.props; + const errors: string[] = []; + const deleteOperations = rolesToDelete.map(roleName => { + const deleteRoleTask = async () => { + try { + await rolesAPIClient.deleteRole(roleName); + notifications.toasts.addSuccess( + i18n.translate( + 'xpack.security.management.roles.confirmDelete.roleSuccessfullyDeletedNotificationMessage', + { defaultMessage: 'Deleted role {roleName}', values: { roleName } } + ) + ); + } catch (e) { + errors.push(roleName); + notifications.toasts.addDanger( + i18n.translate( + 'xpack.security.management.roles.confirmDelete.roleDeletingErrorNotificationMessage', + { defaultMessage: 'Error deleting role {roleName}', values: { roleName } } + ) + ); + } + }; + + return deleteRoleTask(); + }); + + await Promise.all(deleteOperations); + + callback(rolesToDelete, errors); + }; +} diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/index.ts b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/index.ts rename to x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/index.ts b/x-pack/plugins/security/public/management/roles/roles_grid/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/index.ts rename to x-pack/plugins/security/public/management/roles/roles_grid/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/permission_denied/index.ts b/x-pack/plugins/security/public/management/roles/roles_grid/permission_denied/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/permission_denied/index.ts rename to x-pack/plugins/security/public/management/roles/roles_grid/permission_denied/index.ts diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/permission_denied/permission_denied.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/permission_denied/permission_denied.tsx similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/permission_denied/permission_denied.tsx rename to x-pack/plugins/security/public/management/roles/roles_grid/permission_denied/permission_denied.tsx diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx new file mode 100644 index 00000000000000..63ace53420612d --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiIcon } from '@elastic/eui'; +import { ReactWrapper } from 'enzyme'; +import React from 'react'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { RolesAPIClient } from '../roles_api_client'; +import { PermissionDenied } from './permission_denied'; +import { RolesGridPage } from './roles_grid_page'; + +import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { rolesAPIClientMock } from '../index.mock'; + +const mock403 = () => ({ body: { statusCode: 403 } }); + +const waitForRender = async ( + wrapper: ReactWrapper, + condition: (wrapper: ReactWrapper) => boolean +) => { + return new Promise((resolve, reject) => { + const interval = setInterval(async () => { + await Promise.resolve(); + wrapper.update(); + if (condition(wrapper)) { + resolve(); + } + }, 10); + + setTimeout(() => { + clearInterval(interval); + reject(new Error('waitForRender timeout after 2000ms')); + }, 2000); + }); +}; + +describe('', () => { + let apiClientMock: jest.Mocked>; + beforeEach(() => { + apiClientMock = rolesAPIClientMock.create(); + apiClientMock.getRoles.mockResolvedValue([ + { + name: 'test-role-1', + elasticsearch: { cluster: [], indices: [], run_as: [] }, + kibana: [{ base: [], spaces: [], feature: {} }], + }, + { + name: 'reserved-role', + elasticsearch: { cluster: [], indices: [], run_as: [] }, + kibana: [{ base: [], spaces: [], feature: {} }], + metadata: { _reserved: true }, + }, + { + name: 'disabled-role', + elasticsearch: { cluster: [], indices: [], run_as: [] }, + kibana: [{ base: [], spaces: [], feature: {} }], + transient_metadata: { enabled: false }, + }, + ]); + }); + + it(`renders reserved roles as such`, async () => { + const wrapper = mountWithIntl( + + ); + const initialIconCount = wrapper.find(EuiIcon).length; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(EuiIcon).length > initialIconCount; + }); + + expect(wrapper.find(PermissionDenied)).toHaveLength(0); + expect(wrapper.find('EuiIcon[data-test-subj="reservedRole"]')).toHaveLength(1); + expect(wrapper.find('EuiCheckbox[title="Role is reserved"]')).toHaveLength(1); + }); + + it('renders permission denied if required', async () => { + apiClientMock.getRoles.mockRejectedValue(mock403()); + + const wrapper = mountWithIntl( + + ); + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(PermissionDenied).length > 0; + }); + expect(wrapper.find(PermissionDenied)).toMatchSnapshot(); + }); + + it('renders role actions as appropriate', async () => { + const wrapper = mountWithIntl( + + ); + const initialIconCount = wrapper.find(EuiIcon).length; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(EuiIcon).length > initialIconCount; + }); + + expect(wrapper.find(PermissionDenied)).toHaveLength(0); + expect( + wrapper.find('EuiButtonIcon[data-test-subj="edit-role-action-test-role-1"]') + ).toHaveLength(1); + expect( + wrapper.find('EuiButtonIcon[data-test-subj="edit-role-action-disabled-role"]') + ).toHaveLength(1); + + expect( + wrapper.find('EuiButtonIcon[data-test-subj="clone-role-action-test-role-1"]') + ).toHaveLength(1); + expect( + wrapper.find('EuiButtonIcon[data-test-subj="clone-role-action-disabled-role"]') + ).toHaveLength(1); + }); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx similarity index 78% rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.tsx rename to x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx index 2083a93f4b33c9..7c686bef391a79 100644 --- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import _ from 'lodash'; +import React, { Component } from 'react'; import { EuiButton, EuiIcon, @@ -18,18 +20,17 @@ import { EuiButtonIcon, EuiBasicTableColumn, } from '@elastic/eui'; -import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; -import _ from 'lodash'; -import React, { Component } from 'react'; -import { toastNotifications } from 'ui/notify'; -import { Role } from '../../../../../common/model'; -import { isRoleEnabled, isReadOnlyRole, isReservedRole } from '../../../../lib/role_utils'; -import { RolesApi } from '../../../../lib/roles_api'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NotificationsStart } from 'src/core/public'; +import { Role, isRoleEnabled, isReadOnlyRole, isReservedRole } from '../../../../common/model'; +import { RolesAPIClient } from '../roles_api_client'; import { ConfirmDelete } from './confirm_delete'; import { PermissionDenied } from './permission_denied'; interface Props { - intl: InjectedIntl; + notifications: NotificationsStart; + rolesAPIClient: PublicMethodsOf; } interface State { @@ -44,7 +45,7 @@ const getRoleManagementHref = (action: 'edit' | 'clone', roleName?: string) => { return `#/management/security/roles/${action}${roleName ? `/${roleName}` : ''}`; }; -class RolesGridPageUI extends Component { +export class RolesGridPage extends Component { constructor(props: Props) { super(props); this.state = { @@ -68,7 +69,6 @@ class RolesGridPageUI extends Component { private getPageContent = () => { const { roles } = this.state; - const { intl } = this.props; return ( @@ -105,6 +105,8 @@ class RolesGridPageUI extends Component { onCancel={this.onCancelDelete} rolesToDelete={this.state.selection.map(role => role.name)} callback={this.handleDelete} + notifications={this.props.notifications} + rolesAPIClient={this.props.rolesAPIClient} /> ) : null} @@ -112,7 +114,7 @@ class RolesGridPageUI extends Component { !role.metadata || !role.metadata._reserved, @@ -155,17 +157,16 @@ class RolesGridPageUI extends Component { ); }; - private getColumnConfig = (intl: InjectedIntl) => { - const reservedRoleDesc = intl.formatMessage({ - id: 'xpack.security.management.roles.reservedColumnDescription', - defaultMessage: 'Reserved roles are built-in and cannot be edited or removed.', - }); + private getColumnConfig = () => { + const reservedRoleDesc = i18n.translate( + 'xpack.security.management.roles.reservedColumnDescription', + { defaultMessage: 'Reserved roles are built-in and cannot be edited or removed.' } + ); return [ { field: 'name', - name: intl.formatMessage({ - id: 'xpack.security.management.roles.nameColumnName', + name: i18n.translate('xpack.security.management.roles.nameColumnName', { defaultMessage: 'Role', }), sortable: true, @@ -188,8 +189,7 @@ class RolesGridPageUI extends Component { }, { field: 'metadata', - name: intl.formatMessage({ - id: 'xpack.security.management.roles.reservedColumnName', + name: i18n.translate('xpack.security.management.roles.reservedColumnName', { defaultMessage: 'Reserved', }), sortable: ({ metadata }: Role) => Boolean(metadata && metadata._reserved), @@ -197,8 +197,7 @@ class RolesGridPageUI extends Component { align: 'right', description: reservedRoleDesc, render: (metadata: Role['metadata']) => { - const label = intl.formatMessage({ - id: 'xpack.security.management.roles.reservedRoleIconLabel', + const label = i18n.translate('xpack.security.management.roles.reservedRoleIconLabel', { defaultMessage: 'Reserved role', }); @@ -210,8 +209,7 @@ class RolesGridPageUI extends Component { }, }, { - name: intl.formatMessage({ - id: 'xpack.security.management.roles.actionsColumnName', + name: i18n.translate('xpack.security.management.roles.actionsColumnName', { defaultMessage: 'Actions', }), width: '150px', @@ -219,15 +217,10 @@ class RolesGridPageUI extends Component { { available: (role: Role) => !isReadOnlyRole(role), render: (role: Role) => { - const title = intl.formatMessage( - { - id: 'xpack.security.management.roles.editRoleActionName', - defaultMessage: `Edit {roleName}`, - }, - { - roleName: role.name, - } - ); + const title = i18n.translate('xpack.security.management.roles.editRoleActionName', { + defaultMessage: `Edit {roleName}`, + values: { roleName: role.name }, + }); return ( { { available: (role: Role) => !isReservedRole(role), render: (role: Role) => { - const title = intl.formatMessage( - { - id: 'xpack.security.management.roles.cloneRoleActionName', - defaultMessage: `Clone {roleName}`, - }, - { - roleName: role.name, - } - ); + const title = i18n.translate('xpack.security.management.roles.cloneRoleActionName', { + defaultMessage: `Clone {roleName}`, + values: { roleName: role.name }, + }); return ( { private async loadRoles() { try { - const roles = await RolesApi.getRoles(); + const roles = await this.props.rolesAPIClient.getRoles(); this.setState({ roles }); } catch (e) { if (_.get(e, 'body.statusCode') === 403) { this.setState({ permissionDenied: true }); } else { - toastNotifications.addDanger( - this.props.intl.formatMessage( - { - id: 'xpack.security.management.roles.fetchingRolesErrorMessage', - defaultMessage: 'Error fetching roles: {message}', - }, - { message: _.get(e, 'body.message', '') } - ) + this.props.notifications.toasts.addDanger( + i18n.translate('xpack.security.management.roles.fetchingRolesErrorMessage', { + defaultMessage: 'Error fetching roles: {message}', + values: { message: _.get(e, 'body.message', '') }, + }) ); } } @@ -339,5 +324,3 @@ class RolesGridPageUI extends Component { this.setState({ showDeleteConfirmation: false }); }; } - -export const RolesGridPage = injectI18n(RolesGridPageUI); diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx new file mode 100644 index 00000000000000..48bc1a6580a93d --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx @@ -0,0 +1,160 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { licenseMock } from '../../../common/licensing/index.mock'; + +jest.mock('./roles_grid', () => ({ + RolesGridPage: (props: any) => `Roles Page: ${JSON.stringify(props)}`, +})); + +jest.mock('./edit_role', () => ({ + EditRolePage: (props: any) => `Role Edit Page: ${JSON.stringify(props)}`, +})); + +import { rolesManagementApp } from './roles_management_app'; + +import { coreMock } from '../../../../../../src/core/public/mocks'; + +async function mountApp(basePath: string) { + const { fatalErrors } = coreMock.createSetup(); + const container = document.createElement('div'); + const setBreadcrumbs = jest.fn(); + + const unmount = await rolesManagementApp + .create({ + license: licenseMock.create(), + fatalErrors, + getStartServices: jest.fn().mockResolvedValue([coreMock.createStart(), { data: {} }]), + }) + .mount({ basePath, element: container, setBreadcrumbs }); + + return { unmount, container, setBreadcrumbs }; +} + +describe('rolesManagementApp', () => { + it('create() returns proper management app descriptor', () => { + const { fatalErrors, getStartServices } = coreMock.createSetup(); + + expect( + rolesManagementApp.create({ + license: licenseMock.create(), + fatalErrors, + getStartServices: getStartServices as any, + }) + ).toMatchInlineSnapshot(` + Object { + "id": "roles", + "mount": [Function], + "order": 20, + "title": "Roles", + } + `); + }); + + it('mount() works for the `grid` page', async () => { + const basePath = '/some-base-path/roles'; + window.location.hash = basePath; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Roles' }]); + expect(container).toMatchInlineSnapshot(` +
    + Roles Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() works for the `create role` page', async () => { + const basePath = '/some-base-path/roles'; + window.location.hash = `${basePath}/edit`; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Roles' }, + { text: 'Create' }, + ]); + expect(container).toMatchInlineSnapshot(` +
    + Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() works for the `edit role` page', async () => { + const basePath = '/some-base-path/roles'; + const roleName = 'someRoleName'; + window.location.hash = `${basePath}/edit/${roleName}`; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Roles' }, + { href: `#/some-base-path/roles/edit/${roleName}`, text: roleName }, + ]); + expect(container).toMatchInlineSnapshot(` +
    + Role Edit Page: {"action":"edit","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() works for the `clone role` page', async () => { + const basePath = '/some-base-path/roles'; + const roleName = 'someRoleName'; + window.location.hash = `${basePath}/clone/${roleName}`; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Roles' }, + { text: 'Create' }, + ]); + expect(container).toMatchInlineSnapshot(` +
    + Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() properly encodes role name in `edit role` page link in breadcrumbs', async () => { + const basePath = '/some-base-path/roles'; + const roleName = 'some 安全性 role'; + window.location.hash = `${basePath}/edit/${roleName}`; + + const { setBreadcrumbs } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Roles' }, + { + href: '#/some-base-path/roles/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20role', + text: roleName, + }, + ]); + }); +}); diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx new file mode 100644 index 00000000000000..4e8c95b61c2f19 --- /dev/null +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; +import { CoreSetup, FatalErrorsSetup } from 'src/core/public'; +import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public'; +import { SecurityLicense } from '../../../common/licensing'; +import { PluginStartDependencies } from '../../plugin'; +import { UserAPIClient } from '../users'; +import { RolesAPIClient } from './roles_api_client'; +import { RolesGridPage } from './roles_grid'; +import { EditRolePage } from './edit_role'; +import { DocumentationLinksService } from './documentation_links'; +import { IndicesAPIClient } from './indices_api_client'; +import { PrivilegesAPIClient } from './privileges_api_client'; + +interface CreateParams { + fatalErrors: FatalErrorsSetup; + license: SecurityLicense; + getStartServices: CoreSetup['getStartServices']; +} + +export const rolesManagementApp = Object.freeze({ + id: 'roles', + create({ license, fatalErrors, getStartServices }: CreateParams) { + return { + id: this.id, + order: 20, + title: i18n.translate('xpack.security.management.rolesTitle', { defaultMessage: 'Roles' }), + async mount({ basePath, element, setBreadcrumbs }) { + const [ + { application, docLinks, http, i18n: i18nStart, injectedMetadata, notifications }, + { data }, + ] = await getStartServices(); + + const rolesBreadcrumbs = [ + { + text: i18n.translate('xpack.security.roles.breadcrumb', { defaultMessage: 'Roles' }), + href: `#${basePath}`, + }, + ]; + + const rolesAPIClient = new RolesAPIClient(http); + const RolesGridPageWithBreadcrumbs = () => { + setBreadcrumbs(rolesBreadcrumbs); + return ; + }; + + const EditRolePageWithBreadcrumbs = ({ action }: { action: 'edit' | 'clone' }) => { + const { roleName } = useParams<{ roleName?: string }>(); + + setBreadcrumbs([ + ...rolesBreadcrumbs, + action === 'edit' && roleName + ? { text: roleName, href: `#${basePath}/edit/${encodeURIComponent(roleName)}` } + : { + text: i18n.translate('xpack.security.roles.createBreadcrumb', { + defaultMessage: 'Create', + }), + }, + ]); + + return ( + + ); + }; + + render( + + + + + + + + + + + + + + + , + element + ); + + return () => { + unmountComponentAtNode(element); + }; + }, + } as RegisterManagementAppArgs; + }, +}); diff --git a/x-pack/plugins/security/public/management/users/_index.scss b/x-pack/plugins/security/public/management/users/_index.scss new file mode 100644 index 00000000000000..35df0c1b965837 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/_index.scss @@ -0,0 +1 @@ +@import './edit_user/index'; diff --git a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.test.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx similarity index 82% rename from x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.test.tsx rename to x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx index 221120532318cb..be46612767a593 100644 --- a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.test.tsx +++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx @@ -7,10 +7,12 @@ import { EuiFieldText } from '@elastic/eui'; import { ReactWrapper } from 'enzyme'; import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { User } from '../../../../common/model'; -import { UserAPIClient } from '../../../lib/api'; +import { User } from '../../../../../common/model'; import { ChangePasswordForm } from './change_password_form'; +import { coreMock } from '../../../../../../../../src/core/public/mocks'; +import { userAPIClientMock } from '../../index.mock'; + function getCurrentPasswordField(wrapper: ReactWrapper) { return wrapper.find(EuiFieldText).filter('[data-test-subj="currentPassword"]'); } @@ -23,8 +25,6 @@ function getConfirmPasswordField(wrapper: ReactWrapper) { return wrapper.find(EuiFieldText).filter('[data-test-subj="confirmNewPassword"]'); } -jest.mock('ui/kfetch'); - describe('', () => { describe('for the current user', () => { it('shows fields for current and new passwords', () => { @@ -40,7 +40,8 @@ describe('', () => { ); @@ -60,15 +61,15 @@ describe('', () => { const callback = jest.fn(); - const apiClient = new UserAPIClient(); - apiClient.changePassword = jest.fn(); + const apiClientMock = userAPIClientMock.create(); const wrapper = mountWithIntl( ); @@ -83,8 +84,8 @@ describe('', () => { wrapper.find('button[data-test-subj="changePasswordButton"]').simulate('click'); - expect(apiClient.changePassword).toHaveBeenCalledTimes(1); - expect(apiClient.changePassword).toHaveBeenCalledWith( + expect(apiClientMock.changePassword).toHaveBeenCalledTimes(1); + expect(apiClientMock.changePassword).toHaveBeenCalledWith( 'user', 'myNewPassword', 'myCurrentPassword' @@ -106,7 +107,8 @@ describe('', () => { ); diff --git a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx similarity index 96% rename from x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx rename to x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx index 61c0b77decd565..6dcf330ec6f9e1 100644 --- a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx +++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx @@ -5,10 +5,7 @@ */ import { EuiButton, - // @ts-ignore EuiButtonEmpty, - // @ts-ignore - EuiDescribedFormGroup, EuiFieldText, EuiFlexGroup, EuiFlexItem, @@ -18,15 +15,16 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { ChangeEvent, Component } from 'react'; -import { toastNotifications } from 'ui/notify'; -import { User } from '../../../../common/model'; -import { UserAPIClient } from '../../../lib/api'; +import { NotificationsStart } from 'src/core/public'; +import { User } from '../../../../../common/model'; +import { UserAPIClient } from '../..'; interface Props { user: User; isUserChangingOwnPassword: boolean; onChangePassword?: () => void; - apiClient: UserAPIClient; + apiClient: PublicMethodsOf; + notifications: NotificationsStart; } interface State { @@ -294,7 +292,7 @@ export class ChangePasswordForm extends Component { }; private handleChangePasswordSuccess = () => { - toastNotifications.addSuccess({ + this.props.notifications.toasts.addSuccess({ title: i18n.translate('xpack.security.account.changePasswordSuccess', { defaultMessage: 'Your password has been changed.', }), @@ -317,7 +315,7 @@ export class ChangePasswordForm extends Component { if (error.body && error.body.statusCode === 403) { this.setState({ currentPasswordError: true }); } else { - toastNotifications.addDanger( + this.props.notifications.toasts.addDanger( i18n.translate('xpack.security.management.users.editUser.settingPasswordErrorMessage', { defaultMessage: 'Error setting password: {message}', values: { message: _.get(error, 'body.message') }, diff --git a/x-pack/legacy/plugins/security/public/components/management/change_password_form/index.ts b/x-pack/plugins/security/public/management/users/components/change_password_form/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/components/management/change_password_form/index.ts rename to x-pack/plugins/security/public/management/users/components/change_password_form/index.ts diff --git a/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.test.tsx b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.test.tsx new file mode 100644 index 00000000000000..bcec707b03f936 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.test.tsx @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { ConfirmDeleteUsers } from './confirm_delete_users'; +import React from 'react'; + +import { coreMock } from '../../../../../../../../src/core/public/mocks'; +import { userAPIClientMock } from '../../index.mock'; + +describe('ConfirmDeleteUsers', () => { + it('renders a warning for a single user', () => { + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('EuiModalHeaderTitle').text()).toMatchInlineSnapshot(`"Delete user foo"`); + }); + + it('renders a warning for a multiple users', () => { + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('EuiModalHeaderTitle').text()).toMatchInlineSnapshot(`"Delete 3 users"`); + }); + + it('fires onCancel when the operation is cancelled', () => { + const onCancel = jest.fn(); + const wrapper = mountWithIntl( + + ); + + expect(onCancel).toBeCalledTimes(0); + + wrapper.find('EuiButtonEmpty[data-test-subj="confirmModalCancelButton"]').simulate('click'); + + expect(onCancel).toBeCalledTimes(1); + }); + + it('deletes the requested users when confirmed', () => { + const onCancel = jest.fn(); + const apiClientMock = userAPIClientMock.create(); + + const wrapper = mountWithIntl( + + ); + + wrapper.find('EuiButton[data-test-subj="confirmModalConfirmButton"]').simulate('click'); + + expect(apiClientMock.deleteUser).toBeCalledTimes(2); + expect(apiClientMock.deleteUser).toBeCalledWith('foo'); + expect(apiClientMock.deleteUser).toBeCalledWith('bar'); + }); + + it('attempts to delete all users even if some fail', () => { + const onCancel = jest.fn(); + + const apiClientMock = userAPIClientMock.create(); + apiClientMock.deleteUser.mockImplementation(user => { + if (user === 'foo') { + return Promise.reject('something terrible happened'); + } + return Promise.resolve(); + }); + + const wrapper = mountWithIntl( + + ); + + wrapper.find('EuiButton[data-test-subj="confirmModalConfirmButton"]').simulate('click'); + + expect(apiClientMock.deleteUser).toBeCalledTimes(2); + expect(apiClientMock.deleteUser).toBeCalledWith('foo'); + expect(apiClientMock.deleteUser).toBeCalledWith('bar'); + }); +}); diff --git a/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx new file mode 100644 index 00000000000000..b7269e0168d7d5 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Component, Fragment } from 'react'; +import { EuiOverlayMask, EuiConfirmModal } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NotificationsStart } from 'src/core/public'; +import { UserAPIClient } from '../..'; + +interface Props { + usersToDelete: string[]; + apiClient: PublicMethodsOf; + notifications: NotificationsStart; + onCancel: () => void; + callback?: (usersToDelete: string[], errors: string[]) => void; +} + +export class ConfirmDeleteUsers extends Component { + public render() { + const { usersToDelete, onCancel } = this.props; + const moreThanOne = usersToDelete.length > 1; + const title = moreThanOne + ? i18n.translate('xpack.security.management.users.confirmDelete.deleteMultipleUsersTitle', { + defaultMessage: 'Delete {userLength} users', + values: { userLength: usersToDelete.length }, + }) + : i18n.translate('xpack.security.management.users.confirmDelete.deleteOneUserTitle', { + defaultMessage: 'Delete user {userLength}', + values: { userLength: usersToDelete[0] }, + }); + return ( + + +
    + {moreThanOne ? ( + +

    + +

    +
      + {usersToDelete.map(username => ( +
    • {username}
    • + ))} +
    +
    + ) : null} +

    + +

    +
    +
    +
    + ); + } + + private deleteUsers = () => { + const { usersToDelete, callback, apiClient, notifications } = this.props; + const errors: string[] = []; + usersToDelete.forEach(async username => { + try { + await apiClient.deleteUser(username); + notifications.toasts.addSuccess( + i18n.translate( + 'xpack.security.management.users.confirmDelete.userSuccessfullyDeletedNotificationMessage', + { defaultMessage: 'Deleted user {username}', values: { username } } + ) + ); + } catch (e) { + errors.push(username); + notifications.toasts.addDanger( + i18n.translate( + 'xpack.security.management.users.confirmDelete.userDeletingErrorNotificationMessage', + { defaultMessage: 'Error deleting user {username}', values: { username } } + ) + ); + } + if (callback) { + callback(usersToDelete, errors); + } + }); + }; +} diff --git a/x-pack/plugins/security/public/management/users/components/confirm_delete_users/index.ts b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/index.ts new file mode 100644 index 00000000000000..fde35ab0f0d02e --- /dev/null +++ b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ConfirmDeleteUsers } from './confirm_delete_users'; diff --git a/x-pack/plugins/security/public/management/users/components/index.ts b/x-pack/plugins/security/public/management/users/components/index.ts new file mode 100644 index 00000000000000..54011a6a24cbd2 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/components/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ChangePasswordForm } from './change_password_form'; +export { ConfirmDeleteUsers } from './confirm_delete_users'; diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/_users.scss b/x-pack/plugins/security/public/management/users/edit_user/_edit_user_page.scss similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_user/_users.scss rename to x-pack/plugins/security/public/management/users/edit_user/_edit_user_page.scss diff --git a/x-pack/plugins/security/public/management/users/edit_user/_index.scss b/x-pack/plugins/security/public/management/users/edit_user/_index.scss new file mode 100644 index 00000000000000..734ba7882ba72c --- /dev/null +++ b/x-pack/plugins/security/public/management/users/edit_user/_index.scss @@ -0,0 +1 @@ +@import './edit_user_page'; diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx new file mode 100644 index 00000000000000..543d20bb92afe8 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { act } from '@testing-library/react'; +import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; +import { EditUserPage } from './edit_user_page'; +import React from 'react'; +import { User, Role } from '../../../../common/model'; +import { ReactWrapper } from 'enzyme'; + +import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { mockAuthenticatedUser } from '../../../../common/model/authenticated_user.mock'; +import { securityMock } from '../../../mocks'; +import { rolesAPIClientMock } from '../../roles/index.mock'; +import { userAPIClientMock } from '../index.mock'; + +const createUser = (username: string) => { + const user: User = { + username, + full_name: 'my full name', + email: 'foo@bar.com', + roles: ['idk', 'something'], + enabled: true, + }; + + if (username === 'reserved_user') { + user.metadata = { + _reserved: true, + }; + } + + return user; +}; + +const buildClients = () => { + const apiClient = userAPIClientMock.create(); + apiClient.getUser.mockImplementation(async (username: string) => createUser(username)); + + const rolesAPIClient = rolesAPIClientMock.create(); + rolesAPIClient.getRoles.mockImplementation(() => { + return Promise.resolve([ + { + name: 'role 1', + elasticsearch: { + cluster: ['all'], + indices: [], + run_as: [], + }, + kibana: [], + }, + { + name: 'role 2', + elasticsearch: { + cluster: [], + indices: [], + run_as: ['bar'], + }, + kibana: [], + }, + ] as Role[]); + }); + + return { apiClient, rolesAPIClient }; +}; + +function buildSecuritySetup() { + const securitySetupMock = securityMock.createSetup(); + securitySetupMock.authc.getCurrentUser.mockResolvedValue( + mockAuthenticatedUser(createUser('current_user')) + ); + return securitySetupMock; +} + +function expectSaveButton(wrapper: ReactWrapper) { + expect(wrapper.find('EuiButton[data-test-subj="userFormSaveButton"]')).toHaveLength(1); +} + +function expectMissingSaveButton(wrapper: ReactWrapper) { + expect(wrapper.find('EuiButton[data-test-subj="userFormSaveButton"]')).toHaveLength(0); +} + +describe('EditUserPage', () => { + it('allows reserved users to be viewed', async () => { + const { apiClient, rolesAPIClient } = buildClients(); + const securitySetup = buildSecuritySetup(); + const wrapper = mountWithIntl( + + ); + + await waitForRender(wrapper); + + expect(apiClient.getUser).toBeCalledTimes(1); + expect(securitySetup.authc.getCurrentUser).toBeCalledTimes(1); + + expectMissingSaveButton(wrapper); + }); + + it('allows new users to be created', async () => { + const { apiClient, rolesAPIClient } = buildClients(); + const securitySetup = buildSecuritySetup(); + const wrapper = mountWithIntl( + + ); + + await waitForRender(wrapper); + + expect(apiClient.getUser).toBeCalledTimes(0); + expect(securitySetup.authc.getCurrentUser).toBeCalledTimes(0); + + expectSaveButton(wrapper); + }); + + it('allows existing users to be edited', async () => { + const { apiClient, rolesAPIClient } = buildClients(); + const securitySetup = buildSecuritySetup(); + const wrapper = mountWithIntl( + + ); + + await waitForRender(wrapper); + + expect(apiClient.getUser).toBeCalledTimes(1); + expect(securitySetup.authc.getCurrentUser).toBeCalledTimes(1); + + expectSaveButton(wrapper); + }); +}); + +async function waitForRender(wrapper: ReactWrapper) { + await act(async () => { + await nextTick(); + wrapper.update(); + }); +} diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx similarity index 77% rename from x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.tsx rename to x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx index bbffe07485f8dc..576f3ff9e6008c 100644 --- a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx @@ -26,22 +26,23 @@ import { EuiHorizontalRule, EuiSpacer, } from '@elastic/eui'; -import { toastNotifications } from 'ui/notify'; -import { FormattedMessage, injectI18n, InjectedIntl } from '@kbn/i18n/react'; -import { SecurityPluginSetup } from '../../../../../../../../plugins/security/public'; -import { UserValidator, UserValidationResult } from '../../../../lib/validate_user'; -import { User, EditUser, Role } from '../../../../../common/model'; -import { USERS_PATH } from '../../../../views/management/management_urls'; -import { ConfirmDeleteUsers } from '../../../../components/management/users'; -import { UserAPIClient } from '../../../../lib/api'; -import { ChangePasswordForm } from '../../../../components/management/change_password_form'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NotificationsStart } from 'src/core/public'; +import { User, EditUser, Role } from '../../../../common/model'; +import { AuthenticationServiceSetup } from '../../../authentication'; +import { USERS_PATH } from '../../management_urls'; +import { RolesAPIClient } from '../../roles'; +import { ConfirmDeleteUsers, ChangePasswordForm } from '../components'; +import { UserValidator, UserValidationResult } from './validate_user'; +import { UserAPIClient } from '..'; interface Props { - username: string; - intl: InjectedIntl; - changeUrl: (path: string) => void; - apiClient: UserAPIClient; - securitySetup: SecurityPluginSetup; + username?: string; + apiClient: PublicMethodsOf; + rolesAPIClient: PublicMethodsOf; + authc: AuthenticationServiceSetup; + notifications: NotificationsStart; } interface State { @@ -56,7 +57,11 @@ interface State { formError: UserValidationResult | null; } -class EditUserPageUI extends Component { +function backToUserList() { + window.location.hash = USERS_PATH; +} + +export class EditUserPage extends Component { private validator: UserValidator; constructor(props: Props) { @@ -84,7 +89,17 @@ class EditUserPageUI extends Component { } public async componentDidMount() { - const { username, apiClient, securitySetup } = this.props; + await this.setCurrentUser(); + } + + public async componentDidUpdate(prevProps: Props) { + if (prevProps.username !== this.props.username) { + await this.setCurrentUser(); + } + } + + private async setCurrentUser() { + const { username, apiClient, rolesAPIClient, notifications, authc } = this.props; let { user, currentUser } = this.state; if (username) { try { @@ -93,26 +108,24 @@ class EditUserPageUI extends Component { password: '', confirmPassword: '', }; - currentUser = await securitySetup.authc.getCurrentUser(); + currentUser = await authc.getCurrentUser(); } catch (err) { - toastNotifications.addDanger({ - title: this.props.intl.formatMessage({ - id: 'xpack.security.management.users.editUser.errorLoadingUserTitle', + notifications.toasts.addDanger({ + title: i18n.translate('xpack.security.management.users.editUser.errorLoadingUserTitle', { defaultMessage: 'Error loading user', }), text: get(err, 'body.message') || err.message, }); - return; + return backToUserList(); } } let roles: Role[] = []; try { - roles = await apiClient.getRoles(); + roles = await rolesAPIClient.getRoles(); } catch (err) { - toastNotifications.addDanger({ - title: this.props.intl.formatMessage({ - id: 'xpack.security.management.users.editUser.errorLoadingRolesTitle', + notifications.toasts.addDanger({ + title: i18n.translate('xpack.security.management.users.editUser.errorLoadingRolesTitle', { defaultMessage: 'Error loading roles', }), text: get(err, 'body.message') || err.message, @@ -131,8 +144,7 @@ class EditUserPageUI extends Component { private handleDelete = (usernames: string[], errors: string[]) => { if (errors.length === 0) { - const { changeUrl } = this.props; - changeUrl(USERS_PATH); + backToUserList(); } }; @@ -148,7 +160,7 @@ class EditUserPageUI extends Component { this.setState({ formError: null, }); - const { changeUrl, apiClient } = this.props; + const { apiClient } = this.props; const { user, isNewUser, selectedRoles } = this.state; const userToSave: EditUser = { ...user }; if (!isNewUser) { @@ -160,26 +172,23 @@ class EditUserPageUI extends Component { }); try { await apiClient.saveUser(userToSave); - toastNotifications.addSuccess( - this.props.intl.formatMessage( + this.props.notifications.toasts.addSuccess( + i18n.translate( + 'xpack.security.management.users.editUser.userSuccessfullySavedNotificationMessage', { - id: - 'xpack.security.management.users.editUser.userSuccessfullySavedNotificationMessage', defaultMessage: 'Saved user {message}', - }, - { message: user.username } + values: { message: user.username }, + } ) ); - changeUrl(USERS_PATH); + + backToUserList(); } catch (e) { - toastNotifications.addDanger( - this.props.intl.formatMessage( - { - id: 'xpack.security.management.users.editUser.savingUserErrorMessage', - defaultMessage: 'Error saving user: {message}', - }, - { message: get(e, 'body.message', 'Unknown error') } - ) + this.props.notifications.toasts.addDanger( + i18n.translate('xpack.security.management.users.editUser.savingUserErrorMessage', { + defaultMessage: 'Error saving user: {message}', + values: { message: get(e, 'body.message', 'Unknown error') }, + }) ); } } @@ -189,8 +198,7 @@ class EditUserPageUI extends Component { return ( { /> { {user.username === 'kibana' ? ( @@ -260,6 +268,7 @@ class EditUserPageUI extends Component { isUserChangingOwnPassword={userIsLoggedInUser} onChangePassword={this.toggleChangePasswordForm} apiClient={this.props.apiClient} + notifications={this.props.notifications} /> ); @@ -352,7 +361,6 @@ class EditUserPageUI extends Component { }; public render() { - const { changeUrl, intl } = this.props; const { user, roles, @@ -417,6 +425,7 @@ class EditUserPageUI extends Component { usersToDelete={[user.username]} callback={this.handleDelete} apiClient={this.props.apiClient} + notifications={this.props.notifications} /> ) : null} @@ -425,17 +434,16 @@ class EditUserPageUI extends Component { {...this.validator.validateUsername(this.state.user)} helpText={ !isNewUser && !reserved - ? intl.formatMessage({ - id: - 'xpack.security.management.users.editUser.changingUserNameAfterCreationDescription', - defaultMessage: `Usernames can't be changed after creation.`, - }) + ? i18n.translate( + 'xpack.security.management.users.editUser.changingUserNameAfterCreationDescription', + { defaultMessage: `Usernames can't be changed after creation.` } + ) : null } - label={intl.formatMessage({ - id: 'xpack.security.management.users.editUser.usernameFormRowLabel', - defaultMessage: 'Username', - })} + label={i18n.translate( + 'xpack.security.management.users.editUser.usernameFormRowLabel', + { defaultMessage: 'Username' } + )} > { {reserved ? null : ( { { )} { @@ -513,7 +521,7 @@ class EditUserPageUI extends Component { {reserved && ( - changeUrl(USERS_PATH)}> + { - changeUrl(USERS_PATH)} - > + { ); } } - -export const EditUserPage = injectI18n(EditUserPageUI); diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/index.ts b/x-pack/plugins/security/public/management/users/edit_user/index.ts similarity index 100% rename from x-pack/legacy/plugins/security/public/views/management/edit_user/components/index.ts rename to x-pack/plugins/security/public/management/users/edit_user/index.ts diff --git a/x-pack/legacy/plugins/security/public/lib/validate_user.test.ts b/x-pack/plugins/security/public/management/users/edit_user/validate_user.test.ts similarity index 98% rename from x-pack/legacy/plugins/security/public/lib/validate_user.test.ts rename to x-pack/plugins/security/public/management/users/edit_user/validate_user.test.ts index 0535248fede88d..6050e1868a759a 100644 --- a/x-pack/legacy/plugins/security/public/lib/validate_user.test.ts +++ b/x-pack/plugins/security/public/management/users/edit_user/validate_user.test.ts @@ -5,7 +5,7 @@ */ import { UserValidator, UserValidationResult } from './validate_user'; -import { User, EditUser } from '../../common/model'; +import { User, EditUser } from '../../../../common/model'; function expectValid(result: UserValidationResult) { expect(result.isInvalid).toBe(false); diff --git a/x-pack/legacy/plugins/security/public/lib/validate_user.ts b/x-pack/plugins/security/public/management/users/edit_user/validate_user.ts similarity index 98% rename from x-pack/legacy/plugins/security/public/lib/validate_user.ts rename to x-pack/plugins/security/public/management/users/edit_user/validate_user.ts index 113aaacdcbf966..5edd96c68bf0dc 100644 --- a/x-pack/legacy/plugins/security/public/lib/validate_user.ts +++ b/x-pack/plugins/security/public/management/users/edit_user/validate_user.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { User, EditUser } from '../../common/model'; +import { User, EditUser } from '../../../../common/model'; interface UserValidatorOptions { shouldValidate?: boolean; diff --git a/x-pack/plugins/security/public/management/users/index.mock.ts b/x-pack/plugins/security/public/management/users/index.mock.ts new file mode 100644 index 00000000000000..f090f88da500de --- /dev/null +++ b/x-pack/plugins/security/public/management/users/index.mock.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { userAPIClientMock } from './user_api_client.mock'; diff --git a/x-pack/plugins/security/public/management/users/index.ts b/x-pack/plugins/security/public/management/users/index.ts new file mode 100644 index 00000000000000..c8b4d41973da6a --- /dev/null +++ b/x-pack/plugins/security/public/management/users/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { UserAPIClient } from './user_api_client'; +export { usersManagementApp } from './users_management_app'; diff --git a/x-pack/plugins/security/public/management/users/user_api_client.mock.ts b/x-pack/plugins/security/public/management/users/user_api_client.mock.ts new file mode 100644 index 00000000000000..7223f78d57fdc0 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/user_api_client.mock.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const userAPIClientMock = { + create: () => ({ + getUsers: jest.fn(), + getUser: jest.fn(), + deleteUser: jest.fn(), + saveUser: jest.fn(), + changePassword: jest.fn(), + }), +}; diff --git a/x-pack/plugins/security/public/management/users/user_api_client.ts b/x-pack/plugins/security/public/management/users/user_api_client.ts new file mode 100644 index 00000000000000..61dd09d2c5e3de --- /dev/null +++ b/x-pack/plugins/security/public/management/users/user_api_client.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpStart } from 'src/core/public'; +import { User, EditUser } from '../../../common/model'; + +const usersUrl = '/internal/security/users'; + +export class UserAPIClient { + constructor(private readonly http: HttpStart) {} + + public async getUsers() { + return await this.http.get(usersUrl); + } + + public async getUser(username: string) { + return await this.http.get(`${usersUrl}/${encodeURIComponent(username)}`); + } + + public async deleteUser(username: string) { + await this.http.delete(`${usersUrl}/${encodeURIComponent(username)}`); + } + + public async saveUser(user: EditUser) { + await this.http.post(`${usersUrl}/${encodeURIComponent(user.username)}`, { + body: JSON.stringify(user), + }); + } + + public async changePassword(username: string, password: string, currentPassword: string) { + const data: Record = { + newPassword: password, + }; + if (currentPassword) { + data.password = currentPassword; + } + + await this.http.post(`${usersUrl}/${encodeURIComponent(username)}/password`, { + body: JSON.stringify(data), + }); + } +} diff --git a/x-pack/plugins/security/public/management/users/users_grid/index.ts b/x-pack/plugins/security/public/management/users/users_grid/index.ts new file mode 100644 index 00000000000000..90e16248e19c36 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/users_grid/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { UsersGridPage } from './users_grid_page'; diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx new file mode 100644 index 00000000000000..def0649953437d --- /dev/null +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { User } from '../../../../common/model'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { UsersGridPage } from './users_grid_page'; +import React from 'react'; +import { ReactWrapper } from 'enzyme'; +import { userAPIClientMock } from '../index.mock'; +import { coreMock } from '../../../../../../../src/core/public/mocks'; + +describe('UsersGridPage', () => { + it('renders the list of users', async () => { + const apiClientMock = userAPIClientMock.create(); + apiClientMock.getUsers.mockImplementation(() => { + return Promise.resolve([ + { + username: 'foo', + email: 'foo@bar.net', + full_name: 'foo bar', + roles: ['kibana_user'], + enabled: true, + }, + { + username: 'reserved', + email: 'reserved@bar.net', + full_name: '', + roles: ['superuser'], + enabled: true, + metadata: { + _reserved: true, + }, + }, + ]); + }); + + const wrapper = mountWithIntl( + + ); + + await waitForRender(wrapper); + + expect(apiClientMock.getUsers).toBeCalledTimes(1); + expect(wrapper.find('EuiInMemoryTable')).toHaveLength(1); + expect(wrapper.find('EuiTableRow')).toHaveLength(2); + }); + + it('renders a forbidden message if user is not authorized', async () => { + const apiClient = userAPIClientMock.create(); + apiClient.getUsers.mockRejectedValue({ body: { statusCode: 403 } }); + + const wrapper = mountWithIntl( + + ); + + await waitForRender(wrapper); + + expect(apiClient.getUsers).toBeCalledTimes(1); + expect(wrapper.find('[data-test-subj="permissionDeniedMessage"]')).toHaveLength(1); + expect(wrapper.find('EuiInMemoryTable')).toHaveLength(0); + }); +}); + +async function waitForRender(wrapper: ReactWrapper) { + await Promise.resolve(); + await Promise.resolve(); + wrapper.update(); +} diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx new file mode 100644 index 00000000000000..fa15c3388fcc99 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx @@ -0,0 +1,309 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Component, Fragment } from 'react'; +import { + EuiButton, + EuiIcon, + EuiLink, + EuiFlexGroup, + EuiInMemoryTable, + EuiPageContent, + EuiTitle, + EuiPageContentHeader, + EuiPageContentHeaderSection, + EuiPageContentBody, + EuiEmptyPrompt, + EuiBasicTableColumn, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NotificationsStart } from 'src/core/public'; +import { User } from '../../../../common/model'; +import { ConfirmDeleteUsers } from '../components'; +import { UserAPIClient } from '..'; + +interface Props { + apiClient: PublicMethodsOf; + notifications: NotificationsStart; +} + +interface State { + users: User[]; + selection: User[]; + showDeleteConfirmation: boolean; + permissionDenied: boolean; + filter: string; +} + +export class UsersGridPage extends Component { + constructor(props: Props) { + super(props); + this.state = { + users: [], + selection: [], + showDeleteConfirmation: false, + permissionDenied: false, + filter: '', + }; + } + + public componentDidMount() { + this.loadUsers(); + } + + public render() { + const { users, filter, permissionDenied, showDeleteConfirmation, selection } = this.state; + if (permissionDenied) { + return ( + + + + + + } + body={ +

    + +

    + } + /> +
    +
    + ); + } + const path = '#/management/security/'; + const columns: Array> = [ + { + field: 'full_name', + name: i18n.translate('xpack.security.management.users.fullNameColumnName', { + defaultMessage: 'Full Name', + }), + sortable: true, + truncateText: true, + render: (fullName: string) => { + return
    {fullName}
    ; + }, + }, + { + field: 'username', + name: i18n.translate('xpack.security.management.users.userNameColumnName', { + defaultMessage: 'User Name', + }), + sortable: true, + truncateText: true, + render: (username: string) => ( + + {username} + + ), + }, + { + field: 'email', + name: i18n.translate('xpack.security.management.users.emailAddressColumnName', { + defaultMessage: 'Email Address', + }), + sortable: true, + truncateText: true, + render: (email: string) => { + return
    {email}
    ; + }, + }, + { + field: 'roles', + name: i18n.translate('xpack.security.management.users.rolesColumnName', { + defaultMessage: 'Roles', + }), + render: (rolenames: string[]) => { + const roleLinks = rolenames.map((rolename, index) => { + return ( + + {rolename} + {index === rolenames.length - 1 ? null : ', '} + + ); + }); + return
    {roleLinks}
    ; + }, + }, + { + field: 'metadata', + name: i18n.translate('xpack.security.management.users.reservedColumnName', { + defaultMessage: 'Reserved', + }), + sortable: ({ metadata }: User) => Boolean(metadata && metadata._reserved), + width: '100px', + align: 'right', + description: i18n.translate('xpack.security.management.users.reservedColumnDescription', { + defaultMessage: + 'Reserved users are built-in and cannot be removed. Only the password can be changed.', + }), + render: (metadata: User['metadata']) => + metadata && metadata._reserved ? ( + + ) : null, + }, + ]; + const pagination = { + initialPageSize: 20, + pageSizeOptions: [10, 20, 50, 100], + }; + + const selectionConfig = { + itemId: 'username', + selectable: (user: User) => !(user.metadata && user.metadata._reserved), + selectableMessage: (selectable: boolean) => (!selectable ? 'User is a system user' : ''), + onSelectionChange: (updatedSelection: User[]) => + this.setState({ selection: updatedSelection }), + }; + const search = { + toolsLeft: this.renderToolsLeft(), + box: { + incremental: true, + }, + onChange: (query: any) => { + this.setState({ + filter: query.queryText, + }); + }, + }; + const sorting = { + sort: { + field: 'full_name', + direction: 'asc', + }, + } as const; + const rowProps = () => { + return { + 'data-test-subj': 'userRow', + }; + }; + const usersToShow = filter + ? users.filter(({ username, roles, full_name: fullName = '', email = '' }) => { + const normalized = `${username} ${roles.join(' ')} ${fullName} ${email}`.toLowerCase(); + const normalizedQuery = filter.toLowerCase(); + return normalized.indexOf(normalizedQuery) !== -1; + }) + : users; + return ( +
    + + + + +

    + +

    +
    +
    + + + + + +
    + + {showDeleteConfirmation ? ( + user.username)} + callback={this.handleDelete} + apiClient={this.props.apiClient} + notifications={this.props.notifications} + /> + ) : null} + + { + + } + +
    +
    + ); + } + + private handleDelete = (usernames: string[], errors: string[]) => { + const { users } = this.state; + this.setState({ + selection: [], + showDeleteConfirmation: false, + users: users.filter(({ username }) => { + return !usernames.includes(username) || errors.includes(username); + }), + }); + }; + + private async loadUsers() { + try { + const users = await this.props.apiClient.getUsers(); + this.setState({ users }); + } catch (e) { + if (e.body.statusCode === 403) { + this.setState({ permissionDenied: true }); + } else { + this.props.notifications.toasts.addDanger( + i18n.translate('xpack.security.management.users.fetchingUsersErrorMessage', { + defaultMessage: 'Error fetching users: {message}', + values: { message: e.body.message }, + }) + ); + } + } + } + + private renderToolsLeft() { + const { selection } = this.state; + if (selection.length === 0) { + return; + } + const numSelected = selection.length; + return ( + this.setState({ showDeleteConfirmation: true })} + > + + + ); + } + + private onCancelDelete = () => { + this.setState({ showDeleteConfirmation: false }); + }; +} diff --git a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx new file mode 100644 index 00000000000000..48ffcfc550a849 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('./users_grid', () => ({ + UsersGridPage: (props: any) => `Users Page: ${JSON.stringify(props)}`, +})); + +jest.mock('./edit_user', () => ({ + EditUserPage: (props: any) => `User Edit Page: ${JSON.stringify(props)}`, +})); + +import { usersManagementApp } from './users_management_app'; + +import { coreMock } from '../../../../../../src/core/public/mocks'; +import { securityMock } from '../../mocks'; + +async function mountApp(basePath: string) { + const container = document.createElement('div'); + const setBreadcrumbs = jest.fn(); + + const unmount = await usersManagementApp + .create({ + authc: securityMock.createSetup().authc, + getStartServices: coreMock.createSetup().getStartServices as any, + }) + .mount({ basePath, element: container, setBreadcrumbs }); + + return { unmount, container, setBreadcrumbs }; +} + +describe('usersManagementApp', () => { + it('create() returns proper management app descriptor', () => { + expect( + usersManagementApp.create({ + authc: securityMock.createSetup().authc, + getStartServices: coreMock.createSetup().getStartServices as any, + }) + ).toMatchInlineSnapshot(` + Object { + "id": "users", + "mount": [Function], + "order": 10, + "title": "Users", + } + `); + }); + + it('mount() works for the `grid` page', async () => { + const basePath = '/some-base-path/users'; + window.location.hash = basePath; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Users' }]); + expect(container).toMatchInlineSnapshot(` +
    + Users Page: {"notifications":{"toasts":{}},"apiClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() works for the `create user` page', async () => { + const basePath = '/some-base-path/users'; + window.location.hash = `${basePath}/edit`; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Users' }, + { text: 'Create' }, + ]); + expect(container).toMatchInlineSnapshot(` +
    + User Edit Page: {"authc":{},"apiClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}}} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() works for the `edit user` page', async () => { + const basePath = '/some-base-path/users'; + const userName = 'someUserName'; + window.location.hash = `${basePath}/edit/${userName}`; + + const { setBreadcrumbs, container, unmount } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Users' }, + { href: `#/some-base-path/users/edit/${userName}`, text: userName }, + ]); + expect(container).toMatchInlineSnapshot(` +
    + User Edit Page: {"authc":{},"apiClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"username":"someUserName"} +
    + `); + + unmount(); + + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('mount() properly encodes user name in `edit user` page link in breadcrumbs', async () => { + const basePath = '/some-base-path/users'; + const username = 'some 安全性 user'; + window.location.hash = `${basePath}/edit/${username}`; + + const { setBreadcrumbs } = await mountApp(basePath); + + expect(setBreadcrumbs).toHaveBeenCalledTimes(1); + expect(setBreadcrumbs).toHaveBeenCalledWith([ + { href: `#${basePath}`, text: 'Users' }, + { + href: '#/some-base-path/users/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20user', + text: username, + }, + ]); + }); +}); diff --git a/x-pack/plugins/security/public/management/users/users_management_app.tsx b/x-pack/plugins/security/public/management/users/users_management_app.tsx new file mode 100644 index 00000000000000..9aebb396ce9a92 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/users_management_app.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; +import { CoreSetup } from 'src/core/public'; +import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public'; +import { AuthenticationServiceSetup } from '../../authentication'; +import { PluginStartDependencies } from '../../plugin'; +import { RolesAPIClient } from '../roles'; +import { UserAPIClient } from './user_api_client'; +import { UsersGridPage } from './users_grid'; +import { EditUserPage } from './edit_user'; + +interface CreateParams { + authc: AuthenticationServiceSetup; + getStartServices: CoreSetup['getStartServices']; +} + +export const usersManagementApp = Object.freeze({ + id: 'users', + create({ authc, getStartServices }: CreateParams) { + return { + id: this.id, + order: 10, + title: i18n.translate('xpack.security.management.usersTitle', { defaultMessage: 'Users' }), + async mount({ basePath, element, setBreadcrumbs }) { + const [{ http, notifications, i18n: i18nStart }] = await getStartServices(); + const usersBreadcrumbs = [ + { + text: i18n.translate('xpack.security.users.breadcrumb', { defaultMessage: 'Users' }), + href: `#${basePath}`, + }, + ]; + + const userAPIClient = new UserAPIClient(http); + const UsersGridPageWithBreadcrumbs = () => { + setBreadcrumbs(usersBreadcrumbs); + return ; + }; + + const EditUserPageWithBreadcrumbs = () => { + const { username } = useParams<{ username?: string }>(); + + setBreadcrumbs([ + ...usersBreadcrumbs, + username + ? { text: username, href: `#${basePath}/edit/${encodeURIComponent(username)}` } + : { + text: i18n.translate('xpack.security.users.createBreadcrumb', { + defaultMessage: 'Create', + }), + }, + ]); + + return ( + + ); + }; + + render( + + + + + + + + + + + + , + element + ); + + return () => { + unmountComponentAtNode(element); + }; + }, + } as RegisterManagementAppArgs; + }, +}); diff --git a/x-pack/plugins/security/public/plugin.ts b/x-pack/plugins/security/public/plugin.ts deleted file mode 100644 index 50e0b838c750fc..00000000000000 --- a/x-pack/plugins/security/public/plugin.ts +++ /dev/null @@ -1,74 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; -import { LicensingPluginSetup } from '../../licensing/public'; -import { - SessionExpired, - SessionTimeout, - ISessionTimeout, - SessionTimeoutHttpInterceptor, - UnauthorizedResponseHttpInterceptor, -} from './session'; -import { SecurityLicenseService } from '../common/licensing'; -import { SecurityNavControlService } from './nav_control'; -import { AuthenticationService } from './authentication'; - -export interface PluginSetupDependencies { - licensing: LicensingPluginSetup; -} - -export class SecurityPlugin implements Plugin { - private sessionTimeout!: ISessionTimeout; - - private navControlService!: SecurityNavControlService; - - private securityLicenseService!: SecurityLicenseService; - - public setup(core: CoreSetup, { licensing }: PluginSetupDependencies) { - const { http, notifications, injectedMetadata } = core; - const { basePath, anonymousPaths } = http; - anonymousPaths.register('/login'); - anonymousPaths.register('/logout'); - anonymousPaths.register('/logged_out'); - - const tenant = `${injectedMetadata.getInjectedVar('session.tenant', '')}`; - const sessionExpired = new SessionExpired(basePath, tenant); - http.intercept(new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths)); - this.sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant); - http.intercept(new SessionTimeoutHttpInterceptor(this.sessionTimeout, anonymousPaths)); - - this.navControlService = new SecurityNavControlService(); - this.securityLicenseService = new SecurityLicenseService(); - const { license } = this.securityLicenseService.setup({ license$: licensing.license$ }); - - const authc = new AuthenticationService().setup({ http: core.http }); - - this.navControlService.setup({ - securityLicense: license, - authc, - }); - - return { - authc, - sessionTimeout: this.sessionTimeout, - }; - } - - public start(core: CoreStart) { - this.sessionTimeout.start(); - this.navControlService.start({ core }); - } - - public stop() { - this.sessionTimeout.stop(); - this.navControlService.stop(); - this.securityLicenseService.stop(); - } -} - -export type SecurityPluginSetup = ReturnType; -export type SecurityPluginStart = ReturnType; diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx new file mode 100644 index 00000000000000..394e23cbbf646c --- /dev/null +++ b/x-pack/plugins/security/public/plugin.tsx @@ -0,0 +1,147 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; +import { + FeatureCatalogueCategory, + HomePublicPluginSetup, +} from '../../../../src/plugins/home/public'; +import { LicensingPluginSetup } from '../../licensing/public'; +import { ManagementSetup, ManagementStart } from '../../../../src/plugins/management/public'; +import { + SessionExpired, + SessionTimeout, + ISessionTimeout, + SessionTimeoutHttpInterceptor, + UnauthorizedResponseHttpInterceptor, +} from './session'; +import { SecurityLicenseService } from '../common/licensing'; +import { SecurityNavControlService } from './nav_control'; +import { AccountManagementPage } from './account_management'; +import { AuthenticationService, AuthenticationServiceSetup } from './authentication'; +import { ManagementService, UserAPIClient } from './management'; + +export interface PluginSetupDependencies { + licensing: LicensingPluginSetup; + home?: HomePublicPluginSetup; + management?: ManagementSetup; +} + +export interface PluginStartDependencies { + data: DataPublicPluginStart; + management?: ManagementStart; +} + +export class SecurityPlugin + implements + Plugin< + SecurityPluginSetup, + SecurityPluginStart, + PluginSetupDependencies, + PluginStartDependencies + > { + private sessionTimeout!: ISessionTimeout; + private readonly navControlService = new SecurityNavControlService(); + private readonly securityLicenseService = new SecurityLicenseService(); + private readonly managementService = new ManagementService(); + private authc!: AuthenticationServiceSetup; + + public setup( + core: CoreSetup, + { home, licensing, management }: PluginSetupDependencies + ) { + const { http, notifications, injectedMetadata } = core; + const { basePath, anonymousPaths } = http; + anonymousPaths.register('/login'); + anonymousPaths.register('/logout'); + anonymousPaths.register('/logged_out'); + + const tenant = `${injectedMetadata.getInjectedVar('session.tenant', '')}`; + const sessionExpired = new SessionExpired(basePath, tenant); + http.intercept(new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths)); + this.sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant); + http.intercept(new SessionTimeoutHttpInterceptor(this.sessionTimeout, anonymousPaths)); + + const { license } = this.securityLicenseService.setup({ license$: licensing.license$ }); + + this.authc = new AuthenticationService().setup({ http: core.http }); + + this.navControlService.setup({ + securityLicense: license, + authc: this.authc, + }); + + if (management) { + this.managementService.setup({ + license, + management, + authc: this.authc, + fatalErrors: core.fatalErrors, + getStartServices: core.getStartServices, + }); + } + + if (management && home) { + home.featureCatalogue.register({ + id: 'security', + title: i18n.translate('xpack.security.registerFeature.securitySettingsTitle', { + defaultMessage: 'Security Settings', + }), + description: i18n.translate('xpack.security.registerFeature.securitySettingsDescription', { + defaultMessage: + 'Protect your data and easily manage who has access to what with users and roles.', + }), + icon: 'securityApp', + path: '/app/kibana#/management/security/users', + showOnHomePage: true, + category: FeatureCatalogueCategory.ADMIN, + }); + } + + return { + authc: this.authc, + sessionTimeout: this.sessionTimeout, + }; + } + + public start(core: CoreStart, { data, management }: PluginStartDependencies) { + this.sessionTimeout.start(); + this.navControlService.start({ core }); + + if (management) { + this.managementService.start({ management }); + } + + return { + __legacyCompat: { + account_management: { + AccountManagementPage: () => ( + + + + ), + }, + }, + }; + } + + public stop() { + this.sessionTimeout.stop(); + this.navControlService.stop(); + this.securityLicenseService.stop(); + this.managementService.stop(); + } +} + +export type SecurityPluginSetup = ReturnType; +export type SecurityPluginStart = ReturnType; diff --git a/x-pack/plugins/security/public/session/session_timeout.tsx b/x-pack/plugins/security/public/session/session_timeout.tsx index e237201699b9be..bd6dbad7dbf149 100644 --- a/x-pack/plugins/security/public/session/session_timeout.tsx +++ b/x-pack/plugins/security/public/session/session_timeout.tsx @@ -104,9 +104,8 @@ export class SessionTimeout implements ISessionTimeout { */ private fetchSessionInfoAndResetTimers = async (extend = false) => { const method = extend ? 'POST' : 'GET'; - const headers = extend ? {} : { 'kbn-system-api': 'true' }; try { - const result = await this.http.fetch(SESSION_ROUTE, { method, headers }); + const result = await this.http.fetch(SESSION_ROUTE, { method, asSystemRequest: !extend }); this.handleSessionInfoAndResetTimers(result); diff --git a/x-pack/plugins/security/public/session/session_timeout_http_interceptor.test.ts b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.test.ts index ffbd625590b158..427bdb04f9c61f 100644 --- a/x-pack/plugins/security/public/session/session_timeout_http_interceptor.test.ts +++ b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.test.ts @@ -58,7 +58,7 @@ describe('response', () => { http.intercept(interceptor); fetchMock.mock('*', 200); - await http.fetch('/foo-api', { headers: { 'kbn-system-api': 'true' } }); + await http.fetch('/foo-api', { asSystemRequest: true }); expect(sessionTimeoutMock.extend).not.toHaveBeenCalled(); }); @@ -99,9 +99,9 @@ describe('responseError', () => { http.intercept(interceptor); fetchMock.mock('*', 401); - await expect( - http.fetch('/foo-api', { headers: { 'kbn-system-api': 'true' } }) - ).rejects.toMatchInlineSnapshot(`[Error: Unauthorized]`); + await expect(http.fetch('/foo-api', { asSystemRequest: true })).rejects.toMatchInlineSnapshot( + `[Error: Unauthorized]` + ); expect(sessionTimeoutMock.extend).not.toHaveBeenCalled(); }); diff --git a/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts index 8a2251f3f7f7c0..4033c04378a52f 100644 --- a/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts +++ b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts @@ -6,38 +6,34 @@ import { HttpInterceptor, - HttpErrorResponse, - IHttpResponse, + HttpInterceptorResponseError, + HttpResponse, IAnonymousPaths, } from 'src/core/public'; import { ISessionTimeout } from './session_timeout'; -const isSystemAPIRequest = (request: Request) => { - return request.headers.has('kbn-system-api'); -}; - export class SessionTimeoutHttpInterceptor implements HttpInterceptor { constructor(private sessionTimeout: ISessionTimeout, private anonymousPaths: IAnonymousPaths) {} - response(httpResponse: IHttpResponse) { + response(httpResponse: HttpResponse) { if (this.anonymousPaths.isAnonymous(window.location.pathname)) { return; } - if (isSystemAPIRequest(httpResponse.request)) { + if (httpResponse.fetchOptions.asSystemRequest) { return; } this.sessionTimeout.extend(httpResponse.request.url); } - responseError(httpErrorResponse: HttpErrorResponse) { + responseError(httpErrorResponse: HttpInterceptorResponseError) { if (this.anonymousPaths.isAnonymous(window.location.pathname)) { return; } - if (isSystemAPIRequest(httpErrorResponse.request)) { + if (httpErrorResponse.fetchOptions.asSystemRequest) { return; } diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts index a0ef2fdb86b47e..6b5eadcab74418 100644 --- a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts @@ -6,7 +6,7 @@ import { HttpInterceptor, - HttpErrorResponse, + HttpInterceptorResponseError, IHttpInterceptController, IAnonymousPaths, } from 'src/core/public'; @@ -16,7 +16,10 @@ import { SessionExpired } from './session_expired'; export class UnauthorizedResponseHttpInterceptor implements HttpInterceptor { constructor(private sessionExpired: SessionExpired, private anonymousPaths: IAnonymousPaths) {} - responseError(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptController) { + responseError( + httpErrorResponse: HttpInterceptorResponseError, + controller: IHttpInterceptController + ) { if (this.anonymousPaths.isAnonymous(window.location.pathname)) { return; } diff --git a/x-pack/plugins/security/server/routes/role_mapping/get.ts b/x-pack/plugins/security/server/routes/role_mapping/get.ts index 9cd5cf83092e18..def6fabc0e3222 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/get.ts +++ b/x-pack/plugins/security/server/routes/role_mapping/get.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -import { RoleMapping } from '../../../../../legacy/plugins/security/common/model'; +import { RoleMapping } from '../../../common/model'; import { createLicensedRouteHandler } from '../licensed_route_handler'; import { wrapError } from '../../errors'; import { RouteDefinitionParams } from '..'; diff --git a/x-pack/plugins/security/server/saved_objects/index.ts b/x-pack/plugins/security/server/saved_objects/index.ts index 556dc4fda85cf5..59547295628479 100644 --- a/x-pack/plugins/security/server/saved_objects/index.ts +++ b/x-pack/plugins/security/server/saved_objects/index.ts @@ -24,12 +24,12 @@ export function setupSavedObjects({ auditLogger, authz, savedObjects }: SetupSav const getKibanaRequest = (request: KibanaRequest | LegacyRequest) => request instanceof KibanaRequest ? request : KibanaRequest.from(request); - savedObjects.setClientFactory(({ request }) => { + savedObjects.setClientFactoryProvider(repositoryFactory => ({ request }) => { const kibanaRequest = getKibanaRequest(request); return new SavedObjectsClient( authz.mode.useRbacForRequest(kibanaRequest) - ? savedObjects.createInternalRepository() - : savedObjects.createScopedRepository(kibanaRequest) + ? repositoryFactory.createInternalRepository() + : repositoryFactory.createScopedRepository(kibanaRequest) ); }); diff --git a/x-pack/plugins/spaces/common/index.ts b/x-pack/plugins/spaces/common/index.ts index 65baa1bd991022..c1f0f8bd3ece41 100644 --- a/x-pack/plugins/spaces/common/index.ts +++ b/x-pack/plugins/spaces/common/index.ts @@ -5,5 +5,5 @@ */ export { isReservedSpace } from './is_reserved_space'; -export { MAX_SPACE_INITIALS } from './constants'; +export { MAX_SPACE_INITIALS, SPACE_SEARCH_COUNT_THRESHOLD } from './constants'; export { addSpaceIdToPath, getSpaceIdFromPath } from './lib/spaces_url_parser'; diff --git a/x-pack/plugins/spaces/server/plugin.ts b/x-pack/plugins/spaces/server/plugin.ts index 6b7699100032d1..b8ef81c05f7aa4 100644 --- a/x-pack/plugins/spaces/server/plugin.ts +++ b/x-pack/plugins/spaces/server/plugin.ts @@ -38,9 +38,6 @@ import { initInternalSpacesApi } from './routes/api/internal'; */ export interface LegacyAPI { savedObjects: SavedObjectsLegacyService; - tutorial: { - addScopedTutorialContextFactory: (factory: any) => void; - }; auditLogger: { create: (pluginId: string) => AuditLogger; }; @@ -191,9 +188,6 @@ export class Plugin { 'spaces', spacesSavedObjectsClientWrapperFactory(spacesService, types) ); - legacyAPI.tutorial.addScopedTutorialContextFactory( - createSpacesTutorialContextFactory(spacesService) - ); // Register a function with server to manage the collection of usage stats registerSpacesUsageCollector(usageCollectionSetup, { kibanaIndex: legacyAPI.legacyConfig.kibanaIndex, diff --git a/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_legacy_api.ts b/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_legacy_api.ts index cd2bcdcd5aa34b..dfeb094e34e251 100644 --- a/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_legacy_api.ts +++ b/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_legacy_api.ts @@ -104,7 +104,6 @@ export const createLegacyAPI = ({ kibanaIndex: '', }, auditLogger: {} as any, - tutorial: {} as any, xpackMain: {} as any, savedObjects: savedObjectsService, }; diff --git a/x-pack/plugins/task_manager/server/plugin.ts b/x-pack/plugins/task_manager/server/plugin.ts index 9bdd1ce6d87485..8b09f8f2b445a8 100644 --- a/x-pack/plugins/task_manager/server/plugin.ts +++ b/x-pack/plugins/task_manager/server/plugin.ts @@ -38,12 +38,13 @@ export class TaskManagerPlugin public setup(core: CoreSetup, plugins: any): TaskManagerSetupContract { const logger = this.initContext.logger.get('taskManager'); const config$ = this.initContext.config.create(); - const savedObjectsRepository = core.savedObjects.createInternalRepository(['task']); const elasticsearch = core.elasticsearch.adminClient; return { config$, registerLegacyAPI: once((__LEGACY: PluginLegacyDependencies) => { config$.subscribe(async config => { + const [{ savedObjects }] = await core.getStartServices(); + const savedObjectsRepository = savedObjects.createInternalRepository(['task']); this.legacyTaskManager$.next( createTaskManager(core, { logger, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ce3edbbb598280..ce6126e79a82b0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -77,8 +77,6 @@ }, "messages": { "common.ui.aggResponse.allDocsTitle": "すべてのドキュメント", - "common.ui.aggResponse.fieldLabel": "フィールド", - "common.ui.aggResponse.valueLabel": "値", "common.ui.aggTypes.aggNotValidLabel": "- 無効な集約 -", "common.ui.aggTypes.aggregateWith.noAggsErrorTooltip": "選択されたフィールドには互換性のある集約がありません。", "common.ui.aggTypes.aggregateWithLabel": "アグリゲーション:", @@ -452,7 +450,6 @@ "common.ui.flotCharts.thuLabel": "木", "common.ui.flotCharts.tueLabel": "火", "common.ui.flotCharts.wedLabel": "水", - "common.ui.management.breadcrumb": "管理", "common.ui.modals.cancelButtonLabel": "キャンセル", "common.ui.notify.fatalError.errorStatusMessage": "エラー {errStatus} {errStatusText}: {errMessage}", "common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP リクエストが接続に失敗しました。Kibana サーバーが実行されていて、ご使用のブラウザの接続が正常に動作していることを確認するか、システム管理者にお問い合わせください。", @@ -509,13 +506,6 @@ "common.ui.vis.editors.sidebar.tabs.optionsLabel": "オプション", "common.ui.vis.kibanaMap.leaflet.fitDataBoundsAriaLabel": "データバウンドを合わせる", "common.ui.vis.kibanaMap.zoomWarning": "ズームレベルが最大に達しました。完全にズームインするには、Elasticsearch と Kibana の {defaultDistribution} にアップグレードしてください。{ems} でより多くのズームレベルが利用できます。または、独自のマップサーバーを構成できます。詳細は { wms } または { configSettings} をご覧ください。", - "common.ui.vis.visTypes.legend.filterForValueButtonAriaLabel": "値 {legendDataLabel} でフィルタリング", - "common.ui.vis.visTypes.legend.filterOutValueButtonAriaLabel": "値 {legendDataLabel} を除外", - "common.ui.vis.visTypes.legend.loadingLabel": "読み込み中…", - "common.ui.vis.visTypes.legend.setColorScreenReaderDescription": "値 {legendDataLabel} の色を設定", - "common.ui.vis.visTypes.legend.toggleLegendButtonAriaLabel": "凡例を切り替える", - "common.ui.vis.visTypes.legend.toggleLegendButtonTitle": "凡例を切り替える", - "common.ui.vis.visTypes.legend.toggleOptionsButtonAriaLabel": "{legendDataLabel}、トグルオプション", "common.ui.vislib.colormaps.bluesText": "青", "common.ui.vislib.colormaps.greensText": "緑", "common.ui.vislib.colormaps.greenToRedText": "緑から赤", @@ -733,7 +723,6 @@ "data.filter.options.pinAllFiltersButtonLabel": "すべてピン付け", "data.filter.options.unpinAllFiltersButtonLabel": "すべてのピンを外す", "data.filter.searchBar.changeAllFiltersTitle": "すべてのフィルターの変更", - "data.indexPatterns.fetchFieldErrorTitle": "フィールドの取得中にエラーが発生", "data.indexPatterns.unableWriteLabel": "インデックスパターンを書き込めません!このインデックスパターンへの最新の変更を取得するには、ページを更新してください。", "data.indexPatterns.unknownFieldErrorMessage": "インデックスパターン「{title}」のフィールド「{name}」が不明なフィールドタイプを使用しています。", "data.indexPatterns.unknownFieldHeader": "不明なフィールドタイプ {type}", @@ -1113,307 +1102,6 @@ "kbn.advancedSettings.visualization.tileMap.wmsDefaultsTitle": "デフォルトの WMS プロパティ", "kbn.advancedSettings.visualizeEnableLabsText": "ユーザーが実験的なビジュアライゼーションを作成、表示、編集できるようになります。無効の場合、\n ユーザーは本番準備が整ったビジュアライゼーションのみを利用できます。", "kbn.advancedSettings.visualizeEnableLabsTitle": "実験的なビジュアライゼーションを有効にする", - "kbn.common.tutorials.auditbeat.cloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.auditbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.auditbeat.premInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.auditbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.auditbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.auditbeatCloudInstructions.config.debTitle": "構成の変更", - "kbn.common.tutorials.auditbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.auditbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.auditbeatCloudInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTitle": "構成の変更", - "kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.auditbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.auditbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.auditbeatInstructions.config.debTitle": "構成の変更", - "kbn.common.tutorials.auditbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.auditbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.auditbeatInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.auditbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.auditbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.auditbeatInstructions.config.rpmTitle": "構成の変更", - "kbn.common.tutorials.auditbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.auditbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.auditbeatInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.auditbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.auditbeatInstructions.install.debTextPre": "Auditbeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.auditbeatInstructions.install.debTitle": "Auditbeat のダウンロードとインストール", - "kbn.common.tutorials.auditbeatInstructions.install.osxTextPre": "Auditbeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.auditbeatInstructions.install.osxTitle": "Auditbeat のダウンロードとインストール", - "kbn.common.tutorials.auditbeatInstructions.install.rpmTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.auditbeatInstructions.install.rpmTextPre": "Auditbeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.auditbeatInstructions.install.rpmTitle": "Auditbeat のダウンロードとインストール", - "kbn.common.tutorials.auditbeatInstructions.install.windowsTextPost": "{auditbeatPath} ファイルの {propertyName} を Elasticsearch のインストールに設定します。", - "kbn.common.tutorials.auditbeatInstructions.install.windowsTextPre": "Auditbeat は初めてですか?[入門ガイド]({guideLinkUrl}) をご覧ください。\n 1.[ダウンロード]({auditbeatLinkUrl}) ページから Auditbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Auditbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Auditbeat を Windows サービスとしてインストールします。", - "kbn.common.tutorials.auditbeatInstructions.install.windowsTitle": "Auditbeat のダウンロードとインストール", - "kbn.common.tutorials.auditbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.auditbeatInstructions.start.debTitle": "Auditbeat を起動", - "kbn.common.tutorials.auditbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.auditbeatInstructions.start.osxTitle": "Auditbeat を起動", - "kbn.common.tutorials.auditbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.auditbeatInstructions.start.rpmTitle": "Auditbeat を起動", - "kbn.common.tutorials.auditbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.auditbeatInstructions.start.windowsTitle": "Auditbeat を起動", - "kbn.common.tutorials.auditbeatStatusCheck.buttonLabel": "データを確認してください", - "kbn.common.tutorials.auditbeatStatusCheck.errorText": "まだデータを受信していません", - "kbn.common.tutorials.auditbeatStatusCheck.successText": "データを受信しました", - "kbn.common.tutorials.auditbeatStatusCheck.text": "Auditbeat からデータを受け取ったことを確認してください。", - "kbn.common.tutorials.auditbeatStatusCheck.title": "ステータス", - "kbn.common.tutorials.filebeat.cloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.filebeat.premCloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.filebeat.premInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.filebeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.filebeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.filebeatCloudInstructions.config.debTitle": "構成の変更", - "kbn.common.tutorials.filebeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.filebeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.filebeatCloudInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.filebeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.filebeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.filebeatCloudInstructions.config.rpmTitle": "構成の変更", - "kbn.common.tutorials.filebeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.filebeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.filebeatCloudInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.filebeatEnableInstructions.debTextPost": "「/etc/filebeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", - "kbn.common.tutorials.filebeatEnableInstructions.debTitle": "{moduleName} モジュールを有効にし構成します", - "kbn.common.tutorials.filebeatEnableInstructions.osxTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", - "kbn.common.tutorials.filebeatEnableInstructions.osxTextPre": "インストールディレクトリから次のファイルを実行します:", - "kbn.common.tutorials.filebeatEnableInstructions.osxTitle": "{moduleName} モジュールを有効にし構成します", - "kbn.common.tutorials.filebeatEnableInstructions.rpmTextPost": "「/etc/filebeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", - "kbn.common.tutorials.filebeatEnableInstructions.rpmTitle": "{moduleName} モジュールを有効にし構成します", - "kbn.common.tutorials.filebeatEnableInstructions.windowsTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", - "kbn.common.tutorials.filebeatEnableInstructions.windowsTextPre": "「{path}」フォルダから次のファイルを実行します:", - "kbn.common.tutorials.filebeatEnableInstructions.windowsTitle": "{moduleName} モジュールを有効にし構成します", - "kbn.common.tutorials.filebeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.filebeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.filebeatInstructions.config.debTitle": "構成の変更", - "kbn.common.tutorials.filebeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.filebeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.filebeatInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.filebeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.filebeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.filebeatInstructions.config.rpmTitle": "構成の変更", - "kbn.common.tutorials.filebeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.filebeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.filebeatInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.filebeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.filebeatInstructions.install.debTextPre": "Filebeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.filebeatInstructions.install.debTitle": "Filebeat のダウンロードとインストール", - "kbn.common.tutorials.filebeatInstructions.install.osxTextPre": "Filebeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.filebeatInstructions.install.osxTitle": "Filebeat のダウンロードとインストール", - "kbn.common.tutorials.filebeatInstructions.install.rpmTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.filebeatInstructions.install.rpmTextPre": "Filebeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", - "kbn.common.tutorials.filebeatInstructions.install.rpmTitle": "Filebeat のダウンロードとインストール", - "kbn.common.tutorials.filebeatInstructions.install.windowsTextPost": "{filebeatPath} ファイルの {propertyName} を Elasticsearch のインストールに設定します。", - "kbn.common.tutorials.filebeatInstructions.install.windowsTextPre": "Filebeat は初めてですか?[入門ガイド]({guideLinkUrl}) をご覧ください。\n 1.[ダウンロード]({filebeatLinkUrl}) ページから Filebeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Filebeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Filebeat を Windows サービスとしてインストールします。", - "kbn.common.tutorials.filebeatInstructions.install.windowsTitle": "Filebeat のダウンロードとインストール", - "kbn.common.tutorials.filebeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.filebeatInstructions.start.debTitle": "Filebeat を起動します", - "kbn.common.tutorials.filebeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.filebeatInstructions.start.osxTitle": "Filebeat を起動します", - "kbn.common.tutorials.filebeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.filebeatInstructions.start.rpmTitle": "Filebeat を起動します", - "kbn.common.tutorials.filebeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.filebeatInstructions.start.windowsTitle": "Filebeat を起動します", - "kbn.common.tutorials.filebeatStatusCheck.buttonLabel": "データを確認してください", - "kbn.common.tutorials.filebeatStatusCheck.errorText": "モジュールからまだデータを受け取っていません", - "kbn.common.tutorials.filebeatStatusCheck.successText": "このモジュールからデータを受け取りました", - "kbn.common.tutorials.filebeatStatusCheck.text": "Filebeat の「{moduleName}」モジュールからデータを受け取ったことを確認してください。", - "kbn.common.tutorials.filebeatStatusCheck.title": "モジュールステータス", - "kbn.common.tutorials.functionbeat.cloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.functionbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.functionbeat.premInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.functionbeatAWSInstructions.textPost": "「」と「」がアカウント 認証情報で、「us-east-1」が希望の地域です。", - "kbn.common.tutorials.functionbeatAWSInstructions.textPre": "環境で AWS アカウント認証情報を設定します。", - "kbn.common.tutorials.functionbeatAWSInstructions.title": "AWS 認証情報の設定", - "kbn.common.tutorials.functionbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.functionbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.functionbeatCloudInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.functionbeatEnableOnPremInstructions.defaultTextPost": "「」が投入するロググループの名前で、「」が Functionbeat デプロイのステージングに使用されるが有効な S3 バケット名です。", - "kbn.common.tutorials.functionbeatEnableOnPremInstructions.defaultTitle": "Cloudwatch ロググループの構成", - "kbn.common.tutorials.functionbeatEnableOnPremInstructionsOSXLinux.textPre": "「functionbeat.yml」ファイルで設定を変更します。", - "kbn.common.tutorials.functionbeatEnableOnPremInstructionsWindows.textPre": "{path} ファイルで設定を変更します。", - "kbn.common.tutorials.functionbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.functionbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.functionbeatInstructions.config.osxTitle": "Elastic クラスターの構成", - "kbn.common.tutorials.functionbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.functionbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.functionbeatInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.functionbeatInstructions.deploy.osxTextPre": "これにより Functionbeat が Lambda 関数としてインストールされます「setup」コマンドで Elasticsearch の構成を確認し、Kibana インデックスパターンを読み込みます。通常このコマンドを省いても大丈夫です。", - "kbn.common.tutorials.functionbeatInstructions.deploy.osxTitle": "Functionbeat を AWS Lambda にデプロイ", - "kbn.common.tutorials.functionbeatInstructions.deploy.windowsTextPre": "これにより Functionbeat が Lambda 関数としてインストールされます「setup」コマンドで Elasticsearch の構成を確認し、Kibana インデックスパターンを読み込みます。通常このコマンドを省いても大丈夫です。", - "kbn.common.tutorials.functionbeatInstructions.deploy.windowsTitle": "Functionbeat を AWS Lambda にデプロイ", - "kbn.common.tutorials.functionbeatInstructions.install.linuxTextPre": "Functionbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.functionbeatInstructions.install.linuxTitle": "Functionbeat のダウンロードとインストール", - "kbn.common.tutorials.functionbeatInstructions.install.osxTextPre": "Functionbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.functionbeatInstructions.install.osxTitle": "Functionbeat のダウンロードとインストール", - "kbn.common.tutorials.functionbeatInstructions.install.windowsTextPre": "Functionbeat は初めてですか?[入門ガイド]({functionbeatLink}) をご覧ください。\n 1.[ダウンロード]({elasticLink}) ページから Functionbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.{directoryName} ディレクトリの名前を「Functionbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトから、Functionbeat ディレクトリに移動します:", - "kbn.common.tutorials.functionbeatInstructions.install.windowsTitle": "Functionbeat のダウンロードとインストール", - "kbn.common.tutorials.functionbeatStatusCheck.buttonLabel": "データを確認してください", - "kbn.common.tutorials.functionbeatStatusCheck.errorText": "Functionbeat からまだデータを受け取っていません", - "kbn.common.tutorials.functionbeatStatusCheck.successText": "Functionbeat からデータを受け取りました", - "kbn.common.tutorials.functionbeatStatusCheck.text": "Functionbeat からデータを受け取ったことを確認してください。", - "kbn.common.tutorials.functionbeatStatusCheck.title": "Functionbeat ステータス", - "kbn.common.tutorials.heartbeat.cloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.heartbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.heartbeat.premInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.heartbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.heartbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.heartbeatCloudInstructions.config.debTitle": "構成の変更", - "kbn.common.tutorials.heartbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.heartbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.heartbeatCloudInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTitle": "構成の変更", - "kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.debTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.defaultTextPost": "Heartbeat のモニターの設定の詳細は、[Heartbeat 設定ドキュメント]({configureLink}) をご覧ください。", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.defaultTitle": "設定の変更 - モニターの追加", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.osxTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.rpmTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.windowsTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.debTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.defaultTextPost": "{hostTemplate} は監視対象の URL です。Heartbeat のモニターの設定の詳細は、[Heartbeat 設定ドキュメント]({configureLink}) をご覧ください。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.defaultTitle": "設定の変更 - モニターの追加", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.osxTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.rpmTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.windowsTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "kbn.common.tutorials.heartbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.heartbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.heartbeatInstructions.config.debTitle": "構成の変更", - "kbn.common.tutorials.heartbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.heartbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.heartbeatInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.heartbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.heartbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.heartbeatInstructions.config.rpmTitle": "構成の変更", - "kbn.common.tutorials.heartbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.heartbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.heartbeatInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.heartbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({link}) をご覧ください。", - "kbn.common.tutorials.heartbeatInstructions.install.debTextPre": "Heartbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.heartbeatInstructions.install.debTitle": "Heartbeat のダウンロードとインストール", - "kbn.common.tutorials.heartbeatInstructions.install.osxTextPre": "Heartbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.heartbeatInstructions.install.osxTitle": "Heartbeat のダウンロードとインストール", - "kbn.common.tutorials.heartbeatInstructions.install.rpmTextPre": "Heartbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.heartbeatInstructions.install.rpmTitle": "Heartbeat のダウンロードとインストール", - "kbn.common.tutorials.heartbeatInstructions.install.windowsTextPre": "Heartbeat は初めてですか?[入門ガイド]({heartbeatLink}) をご覧ください。\n 1.[ダウンロード]({elasticLink}) ページから Heartbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Heartbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Heartbeat を Windows サービスとしてインストールします。", - "kbn.common.tutorials.heartbeatInstructions.install.windowsTitle": "Heartbeat のダウンロードとインストール", - "kbn.common.tutorials.heartbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", - "kbn.common.tutorials.heartbeatInstructions.start.debTitle": "Heartbeat を起動します", - "kbn.common.tutorials.heartbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", - "kbn.common.tutorials.heartbeatInstructions.start.osxTitle": "Heartbeat を起動します", - "kbn.common.tutorials.heartbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", - "kbn.common.tutorials.heartbeatInstructions.start.rpmTitle": "Heartbeat を起動します", - "kbn.common.tutorials.heartbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", - "kbn.common.tutorials.heartbeatInstructions.start.windowsTitle": "Heartbeat を起動します", - "kbn.common.tutorials.heartbeatStatusCheck.buttonLabel": "データを確認してください", - "kbn.common.tutorials.heartbeatStatusCheck.errorText": "Heartbeat からまだデータを受け取っていません", - "kbn.common.tutorials.heartbeatStatusCheck.successText": "Heartbeat からデータを受け取りました", - "kbn.common.tutorials.heartbeatStatusCheck.text": "Heartbeat からデータを受け取ったことを確認してください。", - "kbn.common.tutorials.heartbeatStatusCheck.title": "Heartbeat のステータス", - "kbn.common.tutorials.logstashInstructions.install.java.osxTextPre": "[こちら]({link}) のインストール手順に従ってください。", - "kbn.common.tutorials.logstashInstructions.install.java.osxTitle": "Java Runtime Environment のダウンロードとインストール", - "kbn.common.tutorials.logstashInstructions.install.java.windowsTextPre": "[こちら]({link}) のインストール手順に従ってください。", - "kbn.common.tutorials.logstashInstructions.install.java.windowsTitle": "Java Runtime Environment のダウンロードとインストール", - "kbn.common.tutorials.logstashInstructions.install.logstash.osxTextPre": "Logstash は初めてですか? [入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.logstashInstructions.install.logstash.osxTitle": "Logstash のダウンロードとインストール", - "kbn.common.tutorials.logstashInstructions.install.logstash.windowsTextPre": "Logstash は初めてですか? [入門ガイド]({logstashLink}) をご覧ください。\n 1. Logstash Windows zip ファイルを [ダウンロード]({elasticLink}) します。\n 2.zip ファイルのコンテンツを展開します。", - "kbn.common.tutorials.logstashInstructions.install.logstash.windowsTitle": "Logstash のダウンロードとインストール", - "kbn.common.tutorials.metricbeat.cloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.metricbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.metricbeat.premInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.metricbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.metricbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.metricbeatCloudInstructions.config.debTitle": "構成の変更", - "kbn.common.tutorials.metricbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.metricbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.metricbeatCloudInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTitle": "構成の変更", - "kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.metricbeatEnableInstructions.debTextPost": "「/etc/metricbeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", - "kbn.common.tutorials.metricbeatEnableInstructions.debTitle": "{moduleName} モジュールを有効にし構成します", - "kbn.common.tutorials.metricbeatEnableInstructions.osxTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", - "kbn.common.tutorials.metricbeatEnableInstructions.osxTextPre": "インストールディレクトリから次のファイルを実行します:", - "kbn.common.tutorials.metricbeatEnableInstructions.osxTitle": "{moduleName} モジュールを有効にし構成します", - "kbn.common.tutorials.metricbeatEnableInstructions.rpmTextPost": "「/etc/metricbeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", - "kbn.common.tutorials.metricbeatEnableInstructions.rpmTitle": "{moduleName} モジュールを有効にし構成します", - "kbn.common.tutorials.metricbeatEnableInstructions.windowsTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", - "kbn.common.tutorials.metricbeatEnableInstructions.windowsTextPre": "「{path}」フォルダから次のファイルを実行します:", - "kbn.common.tutorials.metricbeatEnableInstructions.windowsTitle": "{moduleName} モジュールを有効にし構成します", - "kbn.common.tutorials.metricbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.metricbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.metricbeatInstructions.config.debTitle": "構成の変更", - "kbn.common.tutorials.metricbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.metricbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.metricbeatInstructions.config.osxTitle": "構成の変更", - "kbn.common.tutorials.metricbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.metricbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.metricbeatInstructions.config.rpmTitle": "構成の変更", - "kbn.common.tutorials.metricbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.metricbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.metricbeatInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.metricbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({link}) をご覧ください。", - "kbn.common.tutorials.metricbeatInstructions.install.debTextPre": "Metricbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.metricbeatInstructions.install.debTitle": "Metricbeat のダウンロードとインストール", - "kbn.common.tutorials.metricbeatInstructions.install.osxTextPre": "Metricbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.metricbeatInstructions.install.osxTitle": "Metricbeat のダウンロードとインストール", - "kbn.common.tutorials.metricbeatInstructions.install.rpmTextPre": "Metricbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", - "kbn.common.tutorials.metricbeatInstructions.install.rpmTitle": "Metricbeat のダウンロードとインストール", - "kbn.common.tutorials.metricbeatInstructions.install.windowsTextPost": "{path} ファイルの「output.elasticsearch」を Elasticsearch のインストールに設定します。", - "kbn.common.tutorials.metricbeatInstructions.install.windowsTextPre": "Metricbeat は初めてですか?[入門ガイド]({metricbeatLink}) をご覧ください。\n 1.[ダウンロード]({elasticLink}) ページから Metricbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Metricbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Metricbeat を Windows サービスとしてインストールします。", - "kbn.common.tutorials.metricbeatInstructions.install.windowsTitle": "Metricbeat のダウンロードとインストール", - "kbn.common.tutorials.metricbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.metricbeatInstructions.start.debTitle": "Metricbeat を起動します", - "kbn.common.tutorials.metricbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.metricbeatInstructions.start.osxTitle": "Metricbeat を起動します", - "kbn.common.tutorials.metricbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.metricbeatInstructions.start.rpmTitle": "Metricbeat を起動します", - "kbn.common.tutorials.metricbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.metricbeatInstructions.start.windowsTitle": "Metricbeat を起動します", - "kbn.common.tutorials.metricbeatStatusCheck.buttonLabel": "データを確認してください", - "kbn.common.tutorials.metricbeatStatusCheck.errorText": "モジュールからまだデータを受け取っていません", - "kbn.common.tutorials.metricbeatStatusCheck.successText": "このモジュールからデータを受け取りました", - "kbn.common.tutorials.metricbeatStatusCheck.text": "Metricbeat の「{moduleName}」モジュールからデータを受け取ったことを確認してください", - "kbn.common.tutorials.metricbeatStatusCheck.title": "モジュールステータス", - "kbn.common.tutorials.premCloudInstructions.option1.textPre": "[Elastic Cloud] ({link}) にアクセスします。アカウントをお持ちでない場合は新規登録してください。14 日間の無料トライアルがご利用いただけます。\n\nElastic Cloud コンソールにログインします\n\nElastic Cloud コンソールで次の手順を実行し、クラスターを作成します。\n 1.「デプロイを作成」、「デプロイ名」の順にクリックします\n 2.必要に応じて他のデプロイオプションを変更します (デフォルトも使い始めるのに有効です)\n 3.「デプロイを作成」をクリックします\n 4.デプロイの作成が完了するまで待ちます\n 5.新規クラウド Kibana インスタンスにアクセスし、Kibana ホームの手順に従います。", - "kbn.common.tutorials.premCloudInstructions.option1.title": "オプション 1:Elastic Cloud でお試しください", - "kbn.common.tutorials.premCloudInstructions.option2.textPre": "この Kibana インスタンスをマネージド Elasticsearch インスタンスに対して実行している場合は、手動セットアップを行います。.\n\n「Elasticsearch」エンドポイントを {urlTemplate} として保存し、クラスターの「パスワード」を {passwordTemplate} として保存します。", - "kbn.common.tutorials.premCloudInstructions.option2.title": "オプション 2:Kibana を Cloud インスタンスに接続", - "kbn.common.tutorials.winlogbeat.cloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.winlogbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.winlogbeat.premInstructions.gettingStarted.title": "はじめに", - "kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", - "kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.winlogbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "kbn.common.tutorials.winlogbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "kbn.common.tutorials.winlogbeatInstructions.config.windowsTitle": "構成の変更", - "kbn.common.tutorials.winlogbeatInstructions.install.windowsTextPost": "{path} ファイルの「output.elasticsearch」を Elasticsearch のインストールに設定します。", - "kbn.common.tutorials.winlogbeatInstructions.install.windowsTextPre": "Winlogbeat は初めてですか?[入門ガイド]({winlogbeatLink}) をご覧ください。\n 1.[ダウンロード]({elasticLink}) ページから Winlogbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.{directoryName} ディレクトリの名前を「Winlogbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Winlogbeat を Windows サービスとしてインストールします。", - "kbn.common.tutorials.winlogbeatInstructions.install.windowsTitle": "Winlogbeat のダウンロードとインストール", - "kbn.common.tutorials.winlogbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", - "kbn.common.tutorials.winlogbeatInstructions.start.windowsTitle": "Winlogbeat を起動", - "kbn.common.tutorials.winlogbeatStatusCheck.buttonLabel": "データを確認してください", - "kbn.common.tutorials.winlogbeatStatusCheck.errorText": "まだデータを受信していません", - "kbn.common.tutorials.winlogbeatStatusCheck.successText": "データを受信しました", - "kbn.common.tutorials.winlogbeatStatusCheck.text": "Winlogbeat からデータを受け取ったことを確認してください。", - "kbn.common.tutorials.winlogbeatStatusCheck.title": "モジュールステータス", "kbn.context.breadcrumb": "{indexPatternTitle}#{docId} のコンテキスト", "kbn.context.failedToLoadAnchorDocumentDescription": "別ののドキュメントの読み込みに失敗しました", "kbn.context.failedToLoadAnchorDocumentErrorDescription": "別のドキュメントの読み込みに失敗しました。", @@ -1896,8 +1584,6 @@ "kbn.management.landing.header": "Kibana {version} 管理", "kbn.management.landing.subhead": "インデックス、インデックスパターン、保存されたオブジェクト、Kibana の設定、その他を管理します。", "kbn.management.landing.text": "すべてのツールの一覧は、左のメニューにあります。", - "kbn.management.managementDescription": "Elastic Stack の管理を行うセンターコンソールです。", - "kbn.management.managementLabel": "管理", "kbn.management.objects.confirmModalOptions.deleteButtonLabel": "削除", "kbn.management.objects.confirmModalOptions.modalDescription": "削除されたオブジェクトは復元できません", "kbn.management.objects.confirmModalOptions.modalTitle": "保存された Kibana オブジェクトを削除しますか?", @@ -2062,366 +1748,6 @@ "kbn.management.settings.searchBarAriaLabel": "高度な設定を検索", "kbn.management.settings.sectionLabel": "高度な設定", "kbn.managementTitle": "管理", - "kbn.server.tutorials.aerospikeMetrics.artifacts.application.label": "ディスカバリ", - "kbn.server.tutorials.aerospikeMetrics.longDescription": "「aerospike」Metricbeat モジュールは、Aerospike から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.aerospikeMetrics.nameTitle": "Aerospike メトリック", - "kbn.server.tutorials.aerospikeMetrics.shortDescription": "Aerospike サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.apacheLogs.artifacts.dashboards.linkLabel": "Apache ログダッシュボード", - "kbn.server.tutorials.apacheLogs.longDescription": "apache Filebeat モジュールが、Apache 2 HTTP サーバーにより作成されたアクセスとエラーのログをパースします。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.apacheLogs.nameTitle": "Apache ログ", - "kbn.server.tutorials.apacheLogs.shortDescription": "Apache HTTP サーバーが作成したアクセスとエラーのログを収集しパースします。", - "kbn.server.tutorials.apacheMetrics.artifacts.dashboards.linkLabel": "Apache メトリックダッシュボード", - "kbn.server.tutorials.apacheMetrics.longDescription": "「apache」Metricbeat モジュールは、Apache 2 HTTP サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.apacheMetrics.nameTitle": "Apache メトリック", - "kbn.server.tutorials.apacheMetrics.shortDescription": "Apache 2 HTTP サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.apm.apmAgents.statusCheck.btnLabel": "エージェントステータスを確認", - "kbn.server.tutorials.apm.apmAgents.statusCheck.errorMessage": "エージェントからまだデータを受け取っていません", - "kbn.server.tutorials.apm.apmAgents.statusCheck.successMessage": "1 つまたは複数のエージェントからデータを受け取りました", - "kbn.server.tutorials.apm.apmAgents.statusCheck.text": "アプリケーションが実行されていてエージェントがデータを送信していることを確認してください。", - "kbn.server.tutorials.apm.apmAgents.statusCheck.title": "エージェントステータス", - "kbn.server.tutorials.apm.apmAgents.title": "APM エージェント", - "kbn.server.tutorials.apm.apmServer.statusCheck.btnLabel": "APM Server ステータスを確認", - "kbn.server.tutorials.apm.apmServer.statusCheck.errorMessage": "APM Server がまだ Elasticsearch に接続されていません", - "kbn.server.tutorials.apm.apmServer.statusCheck.successMessage": "APM Server が正常にセットアップされました", - "kbn.server.tutorials.apm.apmServer.statusCheck.text": "APM エージェントの導入を開始する前に、APM Server が実行されていることを確認してください。", - "kbn.server.tutorials.apm.apmServer.statusCheck.title": "APM Server ステータス", - "kbn.server.tutorials.apm.apmServer.title": "APM Server", - "kbn.server.tutorials.apm.djangoClient.configure.commands.addAgentComment": "インストールされたアプリにエージェントを追加します", - "kbn.server.tutorials.apm.djangoClient.configure.commands.addTracingMiddlewareComment": "パフォーマンスメトリックを送信するには、追跡ミドルウェアを追加します:", - "kbn.server.tutorials.apm.djangoClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_、スペース", - "kbn.server.tutorials.apm.djangoClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", - "kbn.server.tutorials.apm.djangoClient.configure.commands.setRequiredServiceNameComment": "必要なサーバー名を設定します。使用できる文字:", - "kbn.server.tutorials.apm.djangoClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", - "kbn.server.tutorials.apm.djangoClient.configure.textPost": "高度な用途に関しては [ドキュメンテーション]({documentationLink}) を参照してください。", - "kbn.server.tutorials.apm.djangoClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「SERVICE_NAME」に基づきプログラムに従って作成されます。", - "kbn.server.tutorials.apm.djangoClient.configure.title": "エージェントの構成", - "kbn.server.tutorials.apm.djangoClient.install.textPre": "Python 用の APM エージェントを依存関係としてインストールします。", - "kbn.server.tutorials.apm.djangoClient.install.title": "APM エージェントのインストール", - "kbn.server.tutorials.apm.dotNetClient.configureAgent.textPost": "エージェントに「IConfiguration」インスタンスが渡されていない場合、(例: 非 ASP.NET Core アプリケーションの場合)、エージェントを環境変数で構成することもできます。\n 高度な用途に関しては [ドキュメンテーション]({documentationLink}) を参照してください。", - "kbn.server.tutorials.apm.dotNetClient.configureAgent.title": "appsettings.json ファイルの例:", - "kbn.server.tutorials.apm.dotNetClient.configureApplication.textPost": "「IConfiguration」インスタンスを渡すのはオプションで、これにより、エージェントはこの「IConfiguration」インスタンス (例: 「appsettings.json」ファイル) から構成を読み込みます。", - "kbn.server.tutorials.apm.dotNetClient.configureApplication.textPre": "「Elastic.Apm.NetCoreAll」パッケージの ASP.NET Core の場合、「Startup.cs」ファイル内の「Configure」メソドの「UseElasticApm」メソドを呼び出します。", - "kbn.server.tutorials.apm.dotNetClient.configureApplication.title": "エージェントをアプリケーションに追加", - "kbn.server.tutorials.apm.dotNetClient.download.textPre": "[NuGet]({allNuGetPackagesLink}) から .NET アプリケーションにエージェントパッケージを追加してください。用途の異なる複数の NuGet パッケージがあります。\n\nEntity Framework Core の ASP.NET Core アプリケーションの場合は、[Elastic.Apm.NetCoreAll]({netCoreAllApmPackageLink}) パッケージをダウンロードしてください。このパッケージは、自動的にすべてのエージェントコンポーネントをアプリケーションに追加します。\n\n 依存性を最低限に抑えたい場合、ASP.NET Core の監視のみに [Elastic.Apm.AspNetCore]({aspNetCorePackageLink}) パッケージ、または Entity Framework Core の監視のみに [Elastic.Apm.EfCore]({efCorePackageLink}) パッケージを使用することができます。\n\n 手動インストルメンテーションのみにパブリック Agent API を使用する場合は、[Elastic.Apm]({elasticApmPackageLink}) パッケージを使用してください。", - "kbn.server.tutorials.apm.dotNetClient.download.title": "APM エージェントのダウンロード", - "kbn.server.tutorials.apm.downloadServer.title": "APM Server をダウンロードして展開します", - "kbn.server.tutorials.apm.downloadServerRpm": "32 ビットパッケージをお探しですか?[ダウンロードページ]({downloadPageLink}) をご覧ください。", - "kbn.server.tutorials.apm.downloadServerTitle": "32 ビットパッケージをお探しですか?[ダウンロードページ]({downloadPageLink}) をご覧ください。", - "kbn.server.tutorials.apm.editConfig.textPre": "Elastic Stack の X-Pack セキュアバージョンをご使用の場合、「apm-server.yml」構成ファイルで認証情報を指定する必要があります。", - "kbn.server.tutorials.apm.editConfig.title": "構成の変更", - "kbn.server.tutorials.apm.elasticCloud.textPre": "APM サーバーを有効にするには、[the Elastic Cloud console](https://cloud.elastic.co/deployments?q={cloudId}) に移動し、展開設定で APM を有効にします。有効にした後、このページを更新してください。", - "kbn.server.tutorials.apm.elasticCloudInstructions.title": "APM エージェント", - "kbn.server.tutorials.apm.flaskClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_、スペース", - "kbn.server.tutorials.apm.flaskClient.configure.commands.configureElasticApmComment": "またはアプリケーションの設定で ELASTIC_APM を使用するよう構成します。", - "kbn.server.tutorials.apm.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment": "環境変数を使用して初期化します", - "kbn.server.tutorials.apm.flaskClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", - "kbn.server.tutorials.apm.flaskClient.configure.commands.setRequiredServiceNameComment": "必要なサーバー名を設定します。使用できる文字:", - "kbn.server.tutorials.apm.flaskClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", - "kbn.server.tutorials.apm.flaskClient.configure.textPost": "高度な用途に関しては [ドキュメンテーション]({documentationLink}) を参照してください。", - "kbn.server.tutorials.apm.flaskClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「SERVICE_NAME」に基づきプログラムに従って作成されます。", - "kbn.server.tutorials.apm.flaskClient.configure.title": "エージェントの構成", - "kbn.server.tutorials.apm.flaskClient.install.textPre": "Python 用の APM エージェントを依存関係としてインストールします。", - "kbn.server.tutorials.apm.flaskClient.install.title": "APM エージェントのインストール", - "kbn.server.tutorials.apm.goClient.configure.commands.initializeUsingEnvironmentVariablesComment": "環境変数を使用して初期化します:", - "kbn.server.tutorials.apm.goClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", - "kbn.server.tutorials.apm.goClient.configure.commands.setServiceNameComment": "サービス名を設定します。使用できる文字は # a-z、A-Z、0-9、-、_、スペースです。", - "kbn.server.tutorials.apm.goClient.configure.commands.usedExecutableNameComment": "ELASTIC_APM_SERVICE_NAME が指定されていない場合、実行可能な名前が使用されます。", - "kbn.server.tutorials.apm.goClient.configure.commands.useIfApmRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", - "kbn.server.tutorials.apm.goClient.configure.textPost": "高度な構成に関しては [ドキュメンテーション]({documentationLink}) を参照してください。", - "kbn.server.tutorials.apm.goClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは実行ファイル名または「ELASTIC_APM_SERVICE_NAME」の環境変数に基づきプログラムに従って作成されます。", - "kbn.server.tutorials.apm.goClient.configure.title": "エージェントの構成", - "kbn.server.tutorials.apm.goClient.install.textPre": "Go の APM エージェントパッケージをインストールします。", - "kbn.server.tutorials.apm.goClient.install.title": "APM エージェントのインストール", - "kbn.server.tutorials.apm.goClient.instrument.textPost": "Go のソースコードのインストルメンテーションの詳細ガイドは、[ドキュメンテーション]({documentationLink}) をご参照ください。", - "kbn.server.tutorials.apm.goClient.instrument.textPre": "提供されたインストルメンテーションモジュールの 1 つ、またはトレーサー API を直接使用して、Go アプリケーションにインストルメンテーションを設定します。", - "kbn.server.tutorials.apm.goClient.instrument.title": "アプリケーションのインストルメンテーション", - "kbn.server.tutorials.apm.introduction": "アプリケーション内から詳細なパフォーマンスメトリックやエラーを集めます。", - "kbn.server.tutorials.apm.javaClient.download.textPre": "[Maven Central]({mavenCentralLink}) からエージェントジャーをダウンロード。アプリケーションにエージェントを依存関係として追加**しない**でください。", - "kbn.server.tutorials.apm.javaClient.download.title": "APM エージェントのダウンロード", - "kbn.server.tutorials.apm.javaClient.startApplication.textPost": "構成オプションと高度な用途に関しては、[ドキュメンテーション]({documentationLink}) をご覧ください。", - "kbn.server.tutorials.apm.javaClient.startApplication.textPre": "「-javaagent」フラグを追加してエージェントをシステムプロパティで構成します。\n\n * 必要なサービス名を設定します (使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)\n * カスタム APM Server URL を設定します (デフォルト: {customApmServerUrl})\n * アプリケーションのベースパッケージを設定します", - "kbn.server.tutorials.apm.javaClient.startApplication.title": "javaagent フラグのアプリケーションの起動", - "kbn.server.tutorials.apm.jsClient.enableRealUserMonitoring.textPre": "[ドキュメンテーション({documentationLink}) をご覧ください。", - "kbn.server.tutorials.apm.jsClient.enableRealUserMonitoring.title": "APM Server の Real User 監視エージェントを有効にする", - "kbn.server.tutorials.apm.nodeClient.configure.commands.addThisToTheFileTopComment": "アプリに読み込まれたファイルの一番上にこれを追加します", - "kbn.server.tutorials.apm.nodeClient.configure.commands.allowedCharactersComment": "使用できる文字は # a-z、A-Z、0-9、-、_、スペースです", - "kbn.server.tutorials.apm.nodeClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", - "kbn.server.tutorials.apm.nodeClient.configure.commands.setRequiredServiceNameComment": "package.json からサービス名を上書きします", - "kbn.server.tutorials.apm.nodeClient.configure.commands.useIfApmRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", - "kbn.server.tutorials.apm.nodeClient.configure.textPost": "[Babel/ES モジュール]({babelEsModulesLink}) との使用を含む高度な用途に関しては、 [ドキュメンテーション]({documentationLink}) をご覧ください。", - "kbn.server.tutorials.apm.nodeClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「serviceName」に基づきプログラムに従って作成されます。このエージェントは様々なフレームワークをサポートしていますが、カスタムスタックで使用することもできます。", - "kbn.server.tutorials.apm.nodeClient.configure.title": "エージェントの構成", - "kbn.server.tutorials.apm.nodeClient.install.textPre": "Node.js 用の APM エージェントをアプリケーションに依存関係としてインストール。", - "kbn.server.tutorials.apm.nodeClient.install.title": "APM エージェントのインストール", - "kbn.server.tutorials.apm.rackClient.configure.commands.optionalComment": "オプション、デフォルトで config/elastic_apm.yml になります", - "kbn.server.tutorials.apm.rackClient.configure.commands.requiredComment": "必要", - "kbn.server.tutorials.apm.rackClient.configure.textPre": "Rack または対応フレームワーク (Sinatra など) の場合は、アプリのミドルウェアを含めてエージェントを起動してください。", - "kbn.server.tutorials.apm.rackClient.configure.title": "エージェントの構成", - "kbn.server.tutorials.apm.rackClient.createConfig.commands.defaultsToTheNameOfRackAppClassComment": "デフォルトで Rack アプリのクラスになります。", - "kbn.server.tutorials.apm.rackClient.createConfig.commands.setCustomApmServerComment": "カスタム APM Server URL (デフォルト: {defaultServerUrl})", - "kbn.server.tutorials.apm.rackClient.createConfig.commands.setServiceNameComment": "サービス名を設定します - 使用できる文字は a-z、A-Z、0-9、-、_、スペースです。", - "kbn.server.tutorials.apm.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", - "kbn.server.tutorials.apm.rackClient.createConfig.textPost": "構成オプションと高度な用途に関しては、[ドキュメンテーション]({documentationLink}) をご覧ください。\n\n", - "kbn.server.tutorials.apm.rackClient.createConfig.textPre": "構成ファイル {configFile} を作成します:", - "kbn.server.tutorials.apm.rackClient.createConfig.title": "構成ファイルの作成", - "kbn.server.tutorials.apm.rackClient.install.textPre": "Gemfile にエージェントを追加します", - "kbn.server.tutorials.apm.rackClient.install.title": "APM エージェントのインストール", - "kbn.server.tutorials.apm.railsClient.configure.textPost": "構成オプションと高度な用途に関しては、[ドキュメンテーション]({documentationLink}) をご覧ください。\n\n", - "kbn.server.tutorials.apm.railsClient.configure.textPre": "APM はアプリの起動時に自動的に起動します。構成ファイル {configFile} を作成してエージェントを構成します", - "kbn.server.tutorials.apm.railsClient.configure.title": "エージェントの構成", - "kbn.server.tutorials.apm.railsClient.install.textPre": "Gemfile にエージェントを追加します", - "kbn.server.tutorials.apm.railsClient.install.title": "APM エージェントのインストール", - "kbn.server.tutorials.apm.specProvider.artifacts.application.label": "APM を起動", - "kbn.server.tutorials.apm.specProvider.artifacts.dashboards.linkLabel": "APM ダッシュボード", - "kbn.server.tutorials.apm.specProvider.longDescription": "アプリケーションパフォーマンスモニタリング (APM) は、アプリケーション内から詳細なパフォーマンスメトリックやエラーを集めます。何千ものアプリケーションのパフォーマンスをリアルタイムで監視できます。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.apm.specProvider.name": "APM", - "kbn.server.tutorials.apm.specProvider.savedObjectsInstallMsg": "APM UI の機能には APM インデックスパターンが必要なものがあります。", - "kbn.server.tutorials.apm.startServer.textPre": "サーバーは、Elasticsearch アプリケーションのパフォーマンスメトリックを処理し保存します。", - "kbn.server.tutorials.apm.startServer.title": "APM Server の起動", - "kbn.server.tutorials.apm.windowsServerInstructions.textPost": "注:システムでスクリプトの実行が無効な場合、スクリプトを実行するために現在のセッションの実行ポリシーの設定が必要となります。例: {command}。", - "kbn.server.tutorials.apm.windowsServerInstructions.textPre": "1.[ダウンロードページ]({downloadPageLink}) から APM Server Windows zip ファイルをダウンロードします。\n2.zip ファイルのコンテンツを {zipFileExtractFolder} に解凍します。\n3.「{apmServerDirectory}」ディレクトリの名前を「APM-Server」に変更します。\n4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n5.PowerShell プロンプトで次のコマンドを実行し、APM Server を Windows サービスとしてインストールします。", - "kbn.server.tutorials.auditbeat.artifacts.dashboards.linkLabel": "SIEM アプリ", - "kbn.server.tutorials.auditbeat.longDescription": "Auditbeat を使用してホストから監査データを収集します。これらにはプロセス、ユーザー、ログイン、ソケット情報、ファイルアクセス、その他が含まれます。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.auditbeat.nameTitle": "Auditbeat", - "kbn.server.tutorials.auditbeat.shortDescription": "ホストから監査データを収集します。", - "kbn.server.tutorials.awsMetrics.artifacts.dashboards.linkLabel": "AWS メトリックダッシュボード", - "kbn.server.tutorials.awsMetrics.longDescription": "「aws」Metricbeat モジュールが、AWS API と Cloudwatch から監視メトリックを取得します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.awsMetrics.nameTitle": "AWS メトリック", - "kbn.server.tutorials.awsMetrics.shortDescription": "AWS API と Cloudwatch からの EC2 インスタンスの監視メトリックです。", - "kbn.server.tutorials.cephMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.cephMetrics.longDescription": "「ceph」Metricbeat モジュールは、Ceph から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.cephMetrics.nameTitle": "Ceph メトリック", - "kbn.server.tutorials.cephMetrics.shortDescription": "Ceph サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.ciscoLogs.artifacts.dashboards.linkLabel": "SIEM アプリ", - "kbn.server.tutorials.ciscoLogs.longDescription": "これは Cisco ネットワークデバイスのログ用のモジュールです。現在、同期された、またはファイルから読み込まれた Cisco ASA ファイアウォールログの「asa」ファイルセットをサポートしています。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.ciscoLogs.nameTitle": "Cisco", - "kbn.server.tutorials.ciscoLogs.shortDescription": "Cisco ASA ファイアウォールからのログを収集・解析します。", - "kbn.server.tutorials.cloudwatchLogs.longDescription": "Functionbeat を AWS Lambda 関数として実行するようデプロイし、Cloudwatch ログを収集します。 [詳細({learnMoreLink})。", - "kbn.server.tutorials.cloudwatchLogs.nameTitle": "Cloudwatch ログ", - "kbn.server.tutorials.cloudwatchLogs.shortDescription": "Functionbeat で Cloudwatch ログを収集します。", - "kbn.server.tutorials.corednsLogs.artifacts.dashboards.linkLabel": "CoreDNS ログダッシュボード", - "kbn.server.tutorials.corednsLogs.longDescription": "「coredns」Filebeat モジュールは、[CoreDNS](https://coredns.io/manual/toc/) からログを収集します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.corednsLogs.nameTitle": "CoreDNS ログ", - "kbn.server.tutorials.corednsLogs.shortDescription": "Coredns により作成されたログを収集します。", - "kbn.server.tutorials.corednsMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.corednsMetrics.longDescription": "「coredns」Metricbeat モジュールが、CoreDNS から監視メトリックを取得します。[詳細({learnMoreLink})。", - "kbn.server.tutorials.corednsMetrics.nameTitle": "CoreDNS メトリック", - "kbn.server.tutorials.corednsMetrics.shortDescription": "CoreDNS サーバーから監視メトリックを取得します。", - "kbn.server.tutorials.couchbaseMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.couchbaseMetrics.longDescription": "「couchbase」Metricbeat モジュールは、Couchbase から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.couchbaseMetrics.nameTitle": "Couchbase メトリック", - "kbn.server.tutorials.couchbaseMetrics.shortDescription": "Couchbase から内部メトリックを取得します。", - "kbn.server.tutorials.couchdbMetrics.artifacts.dashboards.linkLabel": "CouchDB メトリックダッシュボード", - "kbn.server.tutorials.couchdbMetrics.longDescription": "「couchdb」Metricbeat モジュールが、CouchDB から監視メトリックを取得します。[詳細] ({learnMoreLink})。", - "kbn.server.tutorials.couchdbMetrics.nameTitle": "CouchDB メトリック", - "kbn.server.tutorials.couchdbMetrics.shortDescription": "CouchdB サーバーから監視メトリックを取得します。", - "kbn.server.tutorials.dockerMetrics.artifacts.dashboards.linkLabel": "Docker メトリックダッシュボード", - "kbn.server.tutorials.dockerMetrics.longDescription": "「docker」 Metricbeat モジュールは、Docker サーバーからメトリックを取得します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.dockerMetrics.nameTitle": "Docker メトリック", - "kbn.server.tutorials.dockerMetrics.shortDescription": "Docker コンテナーに関するメトリックを取得します。", - "kbn.server.tutorials.dropwizardMetrics.artifacts.application.label": "ディスカバリ", - "kbn.server.tutorials.dropwizardMetrics.longDescription": "「dropwizard」 Metricbeat モジュールは、Dropwizard Java アプリケーション から内部メトリックを取得します。[詳細[]({learnMoreLink})。", - "kbn.server.tutorials.dropwizardMetrics.nameTitle": "Dropwizard メトリック", - "kbn.server.tutorials.dropwizardMetrics.shortDescription": "Dropwizard Java アプリケーションから内部メトリックを取得します。", - "kbn.server.tutorials.elasticsearchLogs.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.elasticsearchLogs.longDescription": "「elasticsearch」Filebeat モジュールが、Elasticsearch により作成されたログをパースします。[詳細({learnMoreLink})。", - "kbn.server.tutorials.elasticsearchLogs.nameTitle": "Elasticsearch ログ", - "kbn.server.tutorials.elasticsearchLogs.shortDescription": "Elasticsearch により作成されたログを収集しパースします。", - "kbn.server.tutorials.elasticsearchMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.elasticsearchMetrics.longDescription": "「elasticsearch」Metricbeat モジュールは、Elasticsearch から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.elasticsearchMetrics.nameTitle": "Elasticsearch メトリック", - "kbn.server.tutorials.elasticsearchMetrics.shortDescription": "Elasticsearch から内部メトリックを取得します。", - "kbn.server.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel": "SIEM アプリ", - "kbn.server.tutorials.envoyproxyLogs.longDescription": "これは [Envoy proxy access log](https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log) 用の Filebeatモジュールです。Kubernetes でのスタンドアロンのデプロイメントと Envoy プロキシデプロイメントの両方をサポートします。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.envoyproxyLogs.nameTitle": "Envoyproxy", - "kbn.server.tutorials.envoyproxyLogs.shortDescription": "Envoy プロキシからのログを収集・解析します。", - "kbn.server.tutorials.etcdMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.etcdMetrics.longDescription": "「etcd」Metricbeat モジュールは、Etcd から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.etcdMetrics.nameTitle": "Etcd メトリック", - "kbn.server.tutorials.etcdMetrics.shortDescription": "Etcd サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.golangMetrics.artifacts.dashboards.linkLabel": "Golang メトリックダッシュボード", - "kbn.server.tutorials.golangMetrics.longDescription": "「{moduleName}」Metricbeat モジュールは、Golang アプリから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.golangMetrics.nameTitle": "Golang メトリック", - "kbn.server.tutorials.golangMetrics.shortDescription": "Golang アプリから内部メトリックを取得します。", - "kbn.server.tutorials.haproxyMetrics.artifacts.application.label": "ディスカバリ", - "kbn.server.tutorials.haproxyMetrics.longDescription": "「haproxy」Metricbeat モジュールは、HAProxy アプリから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.haproxyMetrics.nameTitle": "HAProxy メトリック", - "kbn.server.tutorials.haproxyMetrics.shortDescription": "HAProxy サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.iisLogs.artifacts.dashboards.linkLabel": "IIS ログダッシュボード", - "kbn.server.tutorials.iisLogs.longDescription": "「iis」Filebeat モジュールが、Nginx HTTP サーバーにより作成されたアクセスとエラーのログをパースします。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.iisLogs.nameTitle": "IIS ログ", - "kbn.server.tutorials.iisLogs.shortDescription": "IIS HTTP サーバーにより作成されたアクセスとエラーのログを収集しパースします。", - "kbn.server.tutorials.iptablesLogs.artifacts.dashboards.linkLabel": "SIEM アプリ", - "kbn.server.tutorials.iptablesLogs.longDescription": "これは iptables と ip6tables ログ用のモジュールです。同期でネットワーク上で受信したログや、ファイルからのログを解析します。また、ルールセット名、ルール番号、トラフィックに実行されたアクション (許可/拒否) を含む、Ubiquiti ファイアウォールにより追加された接頭辞も認識できます。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.iptablesLogs.nameTitle": "Iptables / Ubiquiti", - "kbn.server.tutorials.iptablesLogs.shortDescription": "iptables と ip6tables ログ、または Ubiqiti からのログを収集・解析します。", - "kbn.server.tutorials.kafkaLogs.artifacts.dashboards.linkLabel": "Kafka ログダッシュボード", - "kbn.server.tutorials.kafkaLogs.longDescription": "「kafka」Filebeat モジュールは、Kafka が作成したログをパースします。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.kafkaLogs.nameTitle": "Kafka ログ", - "kbn.server.tutorials.kafkaLogs.shortDescription": "Kafka が作成したログを収集しパースします。", - "kbn.server.tutorials.kafkaMetrics.artifacts.application.label": "ディスカバリ", - "kbn.server.tutorials.kafkaMetrics.longDescription": "「kafka」Metricbeat モジュールは、Kafka から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.kafkaMetrics.nameTitle": "Kafka メトリック", - "kbn.server.tutorials.kafkaMetrics.shortDescription": "Kafka サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.kibanaMetrics.artifacts.application.label": "ディスカバリ", - "kbn.server.tutorials.kibanaMetrics.longDescription": "「kibana」Metricbeat モジュールは、Kibana から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.kibanaMetrics.nameTitle": "Kibana メトリック", - "kbn.server.tutorials.kibanaMetrics.shortDescription": "Kibana から内部メトリックを取得します。", - "kbn.server.tutorials.kubernetesMetrics.artifacts.dashboards.linkLabel": "Kubernetes メトリックダッシュボード", - "kbn.server.tutorials.kubernetesMetrics.longDescription": "「kubernetes」Metricbeat モジュールは、Kubernetes API からメトリックを取得します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.kubernetesMetrics.nameTitle": "Kubernetes メトリック", - "kbn.server.tutorials.kubernetesMetrics.shortDescription": "Kubernetes からメトリックを取得します。", - "kbn.server.tutorials.logstashLogs.artifacts.dashboards.linkLabel": "Logstash ログダッシュボード", - "kbn.server.tutorials.logstashLogs.longDescription": "「logstash」Filebeat モジュールが、Logstash 自体により作成されたデバッグとスローログをパースします。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.logstashLogs.nameTitle": "Logstash ログ", - "kbn.server.tutorials.logstashLogs.shortDescription": "Logstash 自体により作成されたデバッグとスローログをパースします。", - "kbn.server.tutorials.logstashMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.logstashMetrics.longDescription": "「{moduleName}」Metricbeat モジュールは、Logstash サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.logstashMetrics.nameTitle": "Logstash メトリック", - "kbn.server.tutorials.logstashMetrics.shortDescription": "Logstash サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.memcachedMetrics.artifacts.application.label": "ディスカバリ", - "kbn.server.tutorials.memcachedMetrics.longDescription": "「memcached」Metricbeat モジュールは、Memcached から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.memcachedMetrics.nameTitle": "Memcached メトリック", - "kbn.server.tutorials.memcachedMetrics.shortDescription": "Memcached サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.mongodbMetrics.artifacts.dashboards.linkLabel": "MongoDB メトリックダッシュボード", - "kbn.server.tutorials.mongodbMetrics.longDescription": "「mongodb」Metricbeat モジュールは、MongoDB サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.mongodbMetrics.nameTitle": "MongoDB メトリック", - "kbn.server.tutorials.mongodbMetrics.shortDescription": "MongoDB から内部メトリックを取得します。", - "kbn.server.tutorials.mssqlMetrics.artifacts.dashboards.linkLabel": "Microsoft SQL Server メトリックダッシュボード", - "kbn.server.tutorials.mssqlMetrics.longDescription": "「mssql」Metricbeat モジュールが、Microsoft SQL Server インスタンスからの監視、ログ、パフォーマンスメトリックを取得します。 詳細({learnMoreLink})。", - "kbn.server.tutorials.mssqlMetrics.nameTitle": "Microsoft SQL Server メトリック", - "kbn.server.tutorials.mssqlMetrics.shortDescription": "Microsoft SQL Server インスタンスから監視メトリックを取得します。", - "kbn.server.tutorials.muninMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.muninMetrics.longDescription": "「munin」Metricbeat モジュールは、Munin から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.muninMetrics.nameTitle": "Munin メトリック", - "kbn.server.tutorials.muninMetrics.shortDescription": "Munin サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.mysqlLogs.artifacts.dashboards.linkLabel": "MySQL ログダッシュボード", - "kbn.server.tutorials.mysqlLogs.longDescription": "「mysql」Filebeat モジュールは、MySQL が作成したエラーとスローログをパースします。[詳細]({learnMoreLink}).", - "kbn.server.tutorials.mysqlLogs.nameTitle": "MySQL ログ", - "kbn.server.tutorials.mysqlLogs.shortDescription": "MySQL が作成したエラーとスローログを収集しパースします。", - "kbn.server.tutorials.mysqlMetrics.artifacts.dashboards.linkLabel": "MySQL メトリックダッシュボード", - "kbn.server.tutorials.mysqlMetrics.longDescription": "「mysql」Metricbeat モジュールは、MySQL サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.mysqlMetrics.nameTitle": "MySQL メトリック", - "kbn.server.tutorials.mysqlMetrics.shortDescription": "MySQL から内部メトリックを取得します。", - "kbn.server.tutorials.natsLogs.artifacts.dashboards.linkLabel": "Nats ログダッシュボード", - "kbn.server.tutorials.natsLogs.longDescription": "「nats」Filebeat モジュールが、Nats により作成されたログをパースします。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.natsLogs.nameTitle": "Nats ログ", - "kbn.server.tutorials.natsLogs.shortDescription": "Nats により作成されたログを収集しパースします。", - "kbn.server.tutorials.natsMetrics.artifacts.dashboards.linkLabel": "Nats メトリックダッシュボード", - "kbn.server.tutorials.natsMetrics.longDescription": "「nats」Metricbeat モジュールが、Nats から監視メトリックを取得します。[詳細({learnMoreLink})。", - "kbn.server.tutorials.natsMetrics.nameTitle": "Nats メトリック", - "kbn.server.tutorials.natsMetrics.shortDescription": "Nats サーバーから監視メトリックを取得します。", - "kbn.server.tutorials.netflow.common.config.elasticCloud.osxTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートで、{password} は {elastic} ユーザーのパスワードです。", - "kbn.server.tutorials.netflow.common.config.elasticCloud.osxTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", - "kbn.server.tutorials.netflow.common.config.elasticCloud.osxTitle": "構成の変更", - "kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートで、{password} は {elastic} ユーザーのパスワードです。", - "kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", - "kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTitle": "構成の変更", - "kbn.server.tutorials.netflow.common.config.onPrem.osxTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートです。", - "kbn.server.tutorials.netflow.common.config.onPrem.osxTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", - "kbn.server.tutorials.netflow.common.config.onPrem.osxTitle": "構成の変更", - "kbn.server.tutorials.netflow.common.config.onPrem.windowsTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートです。", - "kbn.server.tutorials.netflow.common.config.onPrem.windowsTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", - "kbn.server.tutorials.netflow.common.config.onPrem.windowsTitle": "構成の変更", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートで、{esUrl} は Elastic Cloud で実行中の Elasticsearch の URL で、{password} は {elastic} ユーザーのパスワードです。", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTitle": "構成の変更", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートで、{esUrl} は Elastic Cloud で実行中の Elasticsearch の URL で、{password} は {elastic} ユーザーのパスワードです。", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTitle": "構成の変更", - "kbn.server.tutorials.netflow.common.setup.osxTextPost": "{setupOption} オプションは Elasticsearch で {netflowPrefix} インデックスパターンを作成し、Kibana ダッシュボードとビジュアライゼーションをインポートします。後の実行時には既存のダッシュボードに上書きしないよう、このオプションを省略します。", - "kbn.server.tutorials.netflow.common.setup.osxTextPre": "実行:", - "kbn.server.tutorials.netflow.common.setup.osxTitle": "Netflow モジュールを実行", - "kbn.server.tutorials.netflow.common.setup.windowsTextPost": "{setupOption} オプションは Elasticsearch で {netflowPrefix} インデックスパターンを作成し、Kibana ダッシュボードとビジュアライゼーションをインポートします。後の実行時には既存のダッシュボードに上書きしないよう、このオプションを省略します。", - "kbn.server.tutorials.netflow.common.setup.windowsTextPre": "実行:", - "kbn.server.tutorials.netflow.common.setup.windowsTitle": "Netflow モジュールの実行", - "kbn.server.tutorials.netflow.elasticCloudInstructions.title": "はじめに", - "kbn.server.tutorials.netflow.onPremElasticCloudInstructions.title": "はじめに", - "kbn.server.tutorials.netflow.onPremInstructions.title": "はじめに", - "kbn.server.tutorials.netflow.tutorialLongDescription": "Logstash NetFlow モジュールは、ネットワークフローデータを収集してパースしたり、イベントを Elasticsearch でインデックスしたり、Kibana ダッシュボードをインストールしたりできます。このモジュールは Netflow バージョン 5 と 9 をサポートしています。[詳細]({linkUrl})。", - "kbn.server.tutorials.netflow.tutorialShortDescription": "Netflow エクスポーターが送信した Netflow の記録を収集します。", - "kbn.server.tutorials.nginxLogs.artifacts.dashboards.linkLabel": "Nginx ログダッシュボード", - "kbn.server.tutorials.nginxLogs.longDescription": "「nginx」Filebeat モジュールは、Nginx HTTP サーバーが作成したアクセスとエラーのログをパースします。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.nginxLogs.nameTitle": "Nginx ログ", - "kbn.server.tutorials.nginxLogs.shortDescription": "Nginx HTTP サーバーが作成したアクセスとエラーのログを収集しパースします。", - "kbn.server.tutorials.nginxMetrics.artifacts.dashboards.linkLabel": "Nginx メトリックダッシュボード", - "kbn.server.tutorials.nginxMetrics.longDescription": "「nginx」Metricbeat モジュールは、Nginx サーバーから内部メトリックを取得します。このモジュールは {statusModuleLink} が作成したウェブページからサーバーステータスデータを取得します。Nginx で {statusModuleLink} が有効にする必要があります。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.nginxMetrics.nameTitle": "Nginx メトリック", - "kbn.server.tutorials.nginxMetrics.shortDescription": "Nginx HTTP サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.osqueryLogs.artifacts.dashboards.linkLabel": "Osquery ログダッシュボード", - "kbn.server.tutorials.osqueryLogs.longDescription": "「osquery」Filebeat モジュールは、「osqueryd」が作成した JSON 結果ページを収集します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.osqueryLogs.nameTitle": "Osquery ログ", - "kbn.server.tutorials.osqueryLogs.shortDescription": "osqueryd により作成されたログを収集します。", - "kbn.server.tutorials.phpFpmMetrics.longDescription": "「php_fpm」Metricbeat モジュールは、PHP-FPM サーバーから内部メトリックを取得します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.phpFpmMetrics.nameTitle": "PHP-FPM メトリック", - "kbn.server.tutorials.phpFpmMetrics.shortDescription": "PHP-FPM から内部メトリックを取得します。", - "kbn.server.tutorials.postgresqlLogs.artifacts.dashboards.linkLabel": "PostgreSQL ログダッシュボード", - "kbn.server.tutorials.postgresqlLogs.longDescription": "「postgresql」Filebeat モジュールが、PostgreSQL により作成されたエラーとスローログをパースします。[詳細]({learnMoreLink}).", - "kbn.server.tutorials.postgresqlLogs.nameTitle": "PostgreSQL ログ", - "kbn.server.tutorials.postgresqlLogs.shortDescription": "PostgreSQL により作成されたエラーとスローログを収集しパースします。", - "kbn.server.tutorials.postgresqlMetrics.longDescription": "「postgresql」Metricbeat モジュールは、PostgreSQL サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.postgresqlMetrics.nameTitle": "PostgreSQL メトリック", - "kbn.server.tutorials.postgresqlMetrics.shortDescription": "PostgreSQL から内部メトリックを取得します。", - "kbn.server.tutorials.prometheusMetrics.artifacts.application.label": "ディスカバリ", - "kbn.server.tutorials.prometheusMetrics.longDescription": "「{moduleName}」Metricbeat モジュールは、Prometheus エンドポイントからメトリックを取得します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.prometheusMetrics.nameTitle": "Prometheus メトリック", - "kbn.server.tutorials.prometheusMetrics.shortDescription": "Prometheus エクスポーターからメトリックを取得します。.", - "kbn.server.tutorials.rabbitmqMetrics.artifacts.dashboards.linkLabel": "RabbitMQ メトリックダッシュボード", - "kbn.server.tutorials.rabbitmqMetrics.longDescription": "「rabbitmq」Metricbeat モジュールは、RabbitMQ サーバーから内部メトリックを取得します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.rabbitmqMetrics.nameTitle": "RabbitMQ メトリック", - "kbn.server.tutorials.rabbitmqMetrics.shortDescription": "RabbitMQ サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.redisLogs.artifacts.dashboards.linkLabel": "Redis ログダッシュボード", - "kbn.server.tutorials.redisLogs.longDescription": "「redis」Filebeat モジュールは、Redis が作成したエラーとスローログをパースします。Redis がエラーログを作成するには、Redis 構成ファイルの「logfile」オプションが「redis-server.log」に設定されていることを確認してください。スローログは「SLOWLOG」コマンドで Redis から直接読み込まれます。Redis がスローログを記録するには、「slowlog-log-slower-than」オプションが設定されていることを確認してください。「slowlog」ファイルセットは実験的な機能のためご注意ください。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.redisLogs.nameTitle": "Redis ログ", - "kbn.server.tutorials.redisLogs.shortDescription": "Redis が作成したエラーとスローログを収集しパースします。", - "kbn.server.tutorials.redisMetrics.artifacts.dashboards.linkLabel": "Redis メトリックダッシュボード", - "kbn.server.tutorials.redisMetrics.longDescription": "「redis」Metricbeat モジュールは、Redis サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.redisMetrics.nameTitle": "Redis メトリック", - "kbn.server.tutorials.redisMetrics.shortDescription": "Redis から内部メトリックを取得します。", - "kbn.server.tutorials.suricataLogs.artifacts.dashboards.linkLabel": "Suricata ログダッシュボード", - "kbn.server.tutorials.suricataLogs.longDescription": "「suricata」Filebeat モジュールは、[Suricata Eve JSON アウトプット](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html) からログを収集します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.suricataLogs.nameTitle": "Suricata ログ", - "kbn.server.tutorials.suricataLogs.shortDescription": "Suricata IDS/IPS/NSM が作成したログを収集します。", - "kbn.server.tutorials.systemLogs.artifacts.dashboards.linkLabel": "システムログダッシュボード", - "kbn.server.tutorials.systemLogs.longDescription": "「system」Filebeat モジュールは、一般的な Unix/Linux ベースのディストリビューションのシステムログサービスが作成したログを収集しパースします。このモジュールは Windows では利用できません。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.systemLogs.nameTitle": "システムログ", - "kbn.server.tutorials.systemLogs.shortDescription": "ローカル Syslog サーバーが作成したログを収集しパースします。", - "kbn.server.tutorials.systemMetrics.artifacts.dashboards.linkLabel": "システムメトリックダッシュボード", - "kbn.server.tutorials.systemMetrics.longDescription": "「system」Metricbeat モジュールは、ホストから CPU、メモリー、ネットワーク、ディスクの統計を収集します。システム全体の統計とプロセスやファイルシステムごとの統計を収集します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.systemMetrics.nameTitle": "システムメトリック", - "kbn.server.tutorials.systemMetrics.shortDescription": "ホストから CPU、メモリー、ネットワーク、ディスクの統計を収集します。", - "kbn.server.tutorials.traefikLogs.artifacts.dashboards.linkLabel": "Traefik ログダッシュボード", - "kbn.server.tutorials.traefikLogs.longDescription": "「traefik」Filebeat モジュールが、Traefik により作成されたアクセスログをパースします。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.traefikLogs.nameTitle": "Traefik ログ", - "kbn.server.tutorials.traefikLogs.shortDescription": "Traefik Proxy により作成されたアクセスログを収集しパースします。", - "kbn.server.tutorials.uptimeMonitors.artifacts.dashboards.linkLabel": "アップタイムアプリ", - "kbn.server.tutorials.uptimeMonitors.longDescription": "アクティブなプロービングでサービスの稼働状況を監視します。 Heartbeat が URL のリストに基づき、シンプ:にたずねます:生きてる?と [詳細]({learnMoreLink})。", - "kbn.server.tutorials.uptimeMonitors.nameTitle": "アップタイムモニター", - "kbn.server.tutorials.uptimeMonitors.shortDescription": "サービスの稼働状況を監視します。", - "kbn.server.tutorials.uwsgiMetrics.artifacts.dashboards.linkLabel": "uWSGI メトリックダッシュボード", - "kbn.server.tutorials.uwsgiMetrics.longDescription": "「uwsgi」Metricbeat モジュールは、uWSGI サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.uwsgiMetrics.nameTitle": "uWSGI メトリック", - "kbn.server.tutorials.uwsgiMetrics.shortDescription": "uWSGI サーバーから内部メトリックを取得します。", - "kbn.server.tutorials.vsphereMetrics.artifacts.application.label": "ディスカバリ", - "kbn.server.tutorials.vsphereMetrics.longDescription": "「vsphere」Metricbeat モジュールは、vSphere クラスターから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.vsphereMetrics.nameTitle": "vSphere メトリック", - "kbn.server.tutorials.vsphereMetrics.shortDescription": "vSphere から内部メトリックを取得します。", - "kbn.server.tutorials.windowsEventLogs.artifacts.application.label": "SIEM アプリ", - "kbn.server.tutorials.windowsEventLogs.longDescription": "Winlogbeat を使用して Windows Event Log からのログを収集します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.windowsEventLogs.nameTitle": "Windows Event Log", - "kbn.server.tutorials.windowsEventLogs.shortDescription": "Windows Event Log からイベントを取得します。", - "kbn.server.tutorials.windowsMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.windowsMetrics.longDescription": "「windows」Metricbeat モジュールは、Windows から内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.windowsMetrics.nameTitle": "Windows メトリック", - "kbn.server.tutorials.windowsMetrics.shortDescription": "Windows から内部メトリックを取得します。", - "kbn.server.tutorials.zeekLogs.artifacts.dashboards.linkLabel": "Zeek ログダッシュボード", - "kbn.server.tutorials.zeekLogs.longDescription": "「zeek」Filebeat モジュールが、[Zeek](https://www.zeek.org//documentation/index.html) からログを収集します。[詳細]({learnMoreLink})。", - "kbn.server.tutorials.zeekLogs.nameTitle": "Zeek ログ", - "kbn.server.tutorials.zeekLogs.shortDescription": "Zeek/Bro により作成されたログを収集します。", - "kbn.server.tutorials.zookeeperMetrics.artifacts.application.label": "ディスカバー", - "kbn.server.tutorials.zookeeperMetrics.longDescription": "「{moduleName}」Metricbeat モジュールは、Zookeeper サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", - "kbn.server.tutorials.zookeeperMetrics.nameTitle": "Zookeeper メトリック", - "kbn.server.tutorials.zookeeperMetrics.shortDescription": "Zookeeper サーバーから内部メトリックを取得します。", "kbn.settings.advancedSettings.voiceAnnouncement.searchResultScreenReaderMessage": "{query} を検索しました。{sectionLenght, plural, one {# セクション} other {# セクション}}に{optionLenght, plural, one {# オプション} other { # オプション}}があります。", "kbn.topNavMenu.openInspectorButtonLabel": "検査", "kbn.topNavMenu.refreshButtonLabel": "更新", @@ -2483,183 +1809,747 @@ "kbn.visualize.wizard.step1Breadcrumb": "作成", "kbn.visualize.wizard.step2Breadcrumb": "作成", "kbn.visualizeTitle": "可視化", - "kbnVislibVisTypes.area.areaDescription": "折れ線グラフの下の数量を強調します。", - "kbnVislibVisTypes.area.areaTitle": "エリア", - "kbnVislibVisTypes.area.countText": "カウント", - "kbnVislibVisTypes.area.groupTitle": "系列を分割", - "kbnVislibVisTypes.area.metricsTitle": "Y 軸", - "kbnVislibVisTypes.area.radiusTitle": "点のサイズ", - "kbnVislibVisTypes.area.segmentTitle": "X 軸", - "kbnVislibVisTypes.area.splitTitle": "チャートを分割", - "kbnVislibVisTypes.area.tabs.metricsAxesTitle": "メトリックと軸", - "kbnVislibVisTypes.area.tabs.panelSettingsTitle": "パネル設定", - "kbnVislibVisTypes.axisModes.normalText": "標準", - "kbnVislibVisTypes.axisModes.percentageText": "パーセンテージ", - "kbnVislibVisTypes.axisModes.silhouetteText": "シルエット", - "kbnVislibVisTypes.axisModes.wiggleText": "振動", - "kbnVislibVisTypes.categoryAxis.rotate.angledText": "傾斜", - "kbnVislibVisTypes.categoryAxis.rotate.horizontalText": "横", - "kbnVislibVisTypes.categoryAxis.rotate.verticalText": "縦", - "kbnVislibVisTypes.chartModes.normalText": "標準", - "kbnVislibVisTypes.chartModes.stackedText": "スタック", - "kbnVislibVisTypes.chartTypes.areaText": "エリア", - "kbnVislibVisTypes.chartTypes.barText": "バー", - "kbnVislibVisTypes.chartTypes.lineText": "折れ線", - "kbnVislibVisTypes.controls.colorRanges.errorText": "各範囲は前の範囲よりも大きくなければなりません。", - "kbnVislibVisTypes.controls.colorSchema.colorSchemaLabel": "カラー図表", - "kbnVislibVisTypes.controls.colorSchema.howToChangeColorsDescription": "それぞれの色は凡例で変更できます。", - "kbnVislibVisTypes.controls.colorSchema.resetColorsButtonLabel": "色をリセット", - "kbnVislibVisTypes.controls.colorSchema.reverseColorSchemaLabel": "図表を反転", - "kbnVislibVisTypes.controls.gaugeOptions.alignmentLabel": "アラインメント", - "kbnVislibVisTypes.controls.gaugeOptions.autoExtendRangeLabel": "範囲を自動拡張", - "kbnVislibVisTypes.controls.gaugeOptions.displayWarningsLabel": "警告を表示", - "kbnVislibVisTypes.controls.gaugeOptions.extendRangeTooltip": "範囲をデータの最高値に広げます。", - "kbnVislibVisTypes.controls.gaugeOptions.gaugeTypeLabel": "ゲージタイプ", - "kbnVislibVisTypes.controls.gaugeOptions.labelsTitle": "ラベル", - "kbnVislibVisTypes.controls.gaugeOptions.percentageModeLabel": "パーセンテージモード", - "kbnVislibVisTypes.controls.gaugeOptions.rangesTitle": "範囲", - "kbnVislibVisTypes.controls.gaugeOptions.showLabelsLabel": "ラベルを表示", - "kbnVislibVisTypes.controls.gaugeOptions.showLegendLabel": "凡例を表示", - "kbnVislibVisTypes.controls.gaugeOptions.showScaleLabel": "縮尺を表示", - "kbnVislibVisTypes.controls.gaugeOptions.styleTitle": "スタイル", - "kbnVislibVisTypes.controls.gaugeOptions.subTextLabel": "サブラベル", - "kbnVislibVisTypes.controls.gaugeOptions.switchWarningsTooltip": "警告のオン・オフを切り替えます。オンにすると、すべてのラベルを表示できない際に警告が表示されます。", - "kbnVislibVisTypes.controls.heatmapOptions.colorLabel": "色", - "kbnVislibVisTypes.controls.heatmapOptions.colorScaleLabel": "カラースケール", - "kbnVislibVisTypes.controls.heatmapOptions.colorsNumberLabel": "色の数", - "kbnVislibVisTypes.controls.heatmapOptions.labelsTitle": "ラベル", - "kbnVislibVisTypes.controls.heatmapOptions.overwriteAutomaticColorLabel": "自動からーを上書きする", - "kbnVislibVisTypes.controls.heatmapOptions.percentageModeLabel": "パーセンテージモード", - "kbnVislibVisTypes.controls.heatmapOptions.rotateLabel": "回転", - "kbnVislibVisTypes.controls.heatmapOptions.scaleToDataBoundsLabel": "データバウンドに合わせる", - "kbnVislibVisTypes.controls.heatmapOptions.showLabelsTitle": "ラベルを表示", - "kbnVislibVisTypes.controls.heatmapOptions.useCustomRangesLabel": "カスタム範囲を使用", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.alignLabel": "配置", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.filterLabelsLabel": "フィルターラベル", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.labelsTitle": "ラベル", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.positionLabel": "配置", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.showLabel": "表示", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.showLabelsLabel": "ラベルを表示", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.xAxisTitle": "X 軸", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.dontShowLabel": "非表示", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.gridText": "グリッド", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.xAxisLinesLabel": "X 軸線を表示", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.yAxisLinesDisabledTooltip": "ヒストグラムに X 軸線は表示できません。", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.yAxisLinesLabel": "Y 軸線を表示", - "kbnVislibVisTypes.controls.pointSeries.series.chartTypeLabel": "チャートタイプ", - "kbnVislibVisTypes.controls.pointSeries.series.lineModeLabel": "線のモード", - "kbnVislibVisTypes.controls.pointSeries.series.lineWidthLabel": "線の幅", - "kbnVislibVisTypes.controls.pointSeries.series.metricsTitle": "メトリック", - "kbnVislibVisTypes.controls.pointSeries.series.modeLabel": "モード", - "kbnVislibVisTypes.controls.pointSeries.series.newAxisLabel": "新規軸…", - "kbnVislibVisTypes.controls.pointSeries.series.showDotsLabel": "点を表示", - "kbnVislibVisTypes.controls.pointSeries.series.showLineLabel": "線を表示", - "kbnVislibVisTypes.controls.pointSeries.series.valueAxisLabel": "値軸", - "kbnVislibVisTypes.controls.pointSeries.seriesAccordionAriaLabel": "{agg} オプションを切り替える", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.addButtonTooltip": "Y 軸を追加します", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.customExtentsLabel": "カスタム範囲", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.maxLabel": "最高", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.minErrorMessage": "最低値は最高値よりも低く設定する必要があります", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.minLabel": "最低", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.minNeededScaleText": "ログスケールが選択されている場合、最低値は 0 よりも大きいものである必要があります", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.modeLabel": "モード", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.positionLabel": "配置", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.removeButtonTooltip": "Y 軸を削除します", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleToDataBounds.boundsMargin": "境界マージン", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin": "境界マージンは 0 以上でなければなりません", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleToDataBoundsLabel": "データバウンドに合わせる", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleTypeLabel": "スケールタイプ", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.setAxisExtentsLabel": "軸の範囲の設定", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.showLabel": "表示", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.titleLabel": "タイトル", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.toggleCustomExtendsAriaLabel": "カスタム範囲を切り替える", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.toggleOptionsAriaLabel": "{axisName} オプションを切り替える", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.yAxisTitle": "Y 軸", - "kbnVislibVisTypes.controls.rangeErrorMessage": "値は {min} と {max} の間でなければなりません", - "kbnVislibVisTypes.controls.truncateLabel": "切り捨て", - "kbnVislibVisTypes.controls.vislibBasicOptions.legendPositionLabel": "凡例の配置", - "kbnVislibVisTypes.controls.vislibBasicOptions.showTooltipLabel": "ツールヒントを表示", - "kbnVislibVisTypes.editors.heatmap.basicSettingsTitle": "基本設定", - "kbnVislibVisTypes.editors.heatmap.heatmapSettingsTitle": "ヒートマップ設定", - "kbnVislibVisTypes.editors.heatmap.highlightLabel": "ハイライト範囲", - "kbnVislibVisTypes.vislib.heatmap.maxBucketsText": "定義された数列が多すぎます ({nr}).構成されている最高値は {max} です。", - "kbnVislibVisTypes.editors.heatmap.highlightLabelTooltip": "チャートのカーソルを当てた部分と凡例の対応するラベルをハイライトします。", - "kbnVislibVisTypes.editors.pie.donutLabel": "ドーナッツ", - "kbnVislibVisTypes.editors.pie.labelsSettingsTitle": "ラベル設定", - "kbnVislibVisTypes.editors.pie.pieSettingsTitle": "パイ設定", - "kbnVislibVisTypes.editors.pie.showLabelsLabel": "ラベルを表示", - "kbnVislibVisTypes.editors.pie.showTopLevelOnlyLabel": "トップレベルのみ表示", - "kbnVislibVisTypes.editors.pie.showValuesLabel": "値を表示", - "kbnVislibVisTypes.editors.pointSeries.currentTimeMarkerLabel": "現在時刻マーカー", - "kbnVislibVisTypes.editors.pointSeries.orderBucketsBySumLabel": "バケットを合計で並べ替え", - "kbnVislibVisTypes.editors.pointSeries.settingsTitle": "設定", - "kbnVislibVisTypes.editors.pointSeries.showLabels": "チャートに値を表示", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.colorLabel": "ラインカラー", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.showLabel": "しきい線を表示", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.styleLabel": "ラインスタイル", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.valueLabel": "しきい値", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.widthLabel": "線の幅", - "kbnVislibVisTypes.editors.pointSeries.thresholdLineSettingsTitle": "しきい線", - "kbnVislibVisTypes.functions.pie.help": "パイビジュアライゼーション", - "kbnVislibVisTypes.functions.vislib.help": "Vislib ビジュアライゼーション", - "kbnVislibVisTypes.gauge.alignmentAutomaticTitle": "自動", - "kbnVislibVisTypes.gauge.alignmentHorizontalTitle": "横", - "kbnVislibVisTypes.gauge.alignmentVerticalTitle": "縦", - "kbnVislibVisTypes.gauge.gaugeDescription": "ゲージはメトリックのステータスを示します。メトリックの値としきい値との関連性を示すのに使用します。", - "kbnVislibVisTypes.gauge.gaugeTitle": "ゲージ", - "kbnVislibVisTypes.gauge.gaugeTypes.arcText": "弧形", - "kbnVislibVisTypes.gauge.gaugeTypes.circleText": "円", - "kbnVislibVisTypes.gauge.groupTitle": "グループを分割", - "kbnVislibVisTypes.gauge.metricTitle": "メトリック", - "kbnVislibVisTypes.goal.goalDescription": "ゴールチャートは、最終目標にどれだけ近いかを示します。", - "kbnVislibVisTypes.goal.goalTitle": "ゴール", - "kbnVislibVisTypes.goal.groupTitle": "グループを分割", - "kbnVislibVisTypes.goal.metricTitle": "メトリック", - "kbnVislibVisTypes.heatmap.groupTitle": "Y 軸", - "kbnVislibVisTypes.heatmap.heatmapDescription": "マトリックス内のセルに影をつける。", - "kbnVislibVisTypes.heatmap.heatmapTitle": "ヒートマップ", - "kbnVislibVisTypes.heatmap.metricTitle": "値", - "kbnVislibVisTypes.heatmap.segmentTitle": "X 軸", - "kbnVislibVisTypes.heatmap.splitTitle": "チャートを分割", - "kbnVislibVisTypes.histogram.groupTitle": "系列を分割", - "kbnVislibVisTypes.histogram.histogramDescription": "連続変数を各軸に割り当てる。", - "kbnVislibVisTypes.histogram.histogramTitle": "縦棒", - "kbnVislibVisTypes.histogram.metricTitle": "Y 軸", - "kbnVislibVisTypes.histogram.radiusTitle": "点のサイズ", - "kbnVislibVisTypes.histogram.segmentTitle": "X 軸", - "kbnVislibVisTypes.histogram.splitTitle": "チャートを分割", - "kbnVislibVisTypes.horizontalBar.groupTitle": "系列を分割", - "kbnVislibVisTypes.horizontalBar.horizontalBarDescription": "連続変数を各軸に割り当てる。", - "kbnVislibVisTypes.horizontalBar.horizontalBarTitle": "横棒", - "kbnVislibVisTypes.horizontalBar.metricTitle": "Y 軸", - "kbnVislibVisTypes.horizontalBar.radiusTitle": "点のサイズ", - "kbnVislibVisTypes.horizontalBar.segmentTitle": "X 軸", - "kbnVislibVisTypes.horizontalBar.splitTitle": "チャートを分割", - "kbnVislibVisTypes.interpolationModes.smoothedText": "スムーズ", - "kbnVislibVisTypes.interpolationModes.steppedText": "ステップ", - "kbnVislibVisTypes.interpolationModes.straightText": "直線", - "kbnVislibVisTypes.legendPositions.bottomText": "一番下", - "kbnVislibVisTypes.legendPositions.leftText": "左", - "kbnVislibVisTypes.legendPositions.rightText": "右", - "kbnVislibVisTypes.legendPositions.topText": "一番上", - "kbnVislibVisTypes.line.groupTitle": "系列を分割", - "kbnVislibVisTypes.line.lineDescription": "トレンドを強調します。", - "kbnVislibVisTypes.line.lineTitle": "折れ線", - "kbnVislibVisTypes.line.metricTitle": "Y 軸", - "kbnVislibVisTypes.line.radiusTitle": "点のサイズ", - "kbnVislibVisTypes.line.segmentTitle": "X 軸", - "kbnVislibVisTypes.line.splitTitle": "チャートを分割", - "kbnVislibVisTypes.pie.metricTitle": "サイズのスライス", - "kbnVislibVisTypes.pie.pieDescription": "全体に対する内訳を表現する。", - "kbnVislibVisTypes.pie.pieTitle": "パイ", - "kbnVislibVisTypes.pie.segmentTitle": "スライスの分割", - "kbnVislibVisTypes.pie.splitTitle": "チャートを分割", - "kbnVislibVisTypes.scaleTypes.linearText": "直線", - "kbnVislibVisTypes.scaleTypes.logText": "ログ", - "kbnVislibVisTypes.scaleTypes.squareRootText": "平方根", - "kbnVislibVisTypes.thresholdLine.style.dashedText": "鎖線", - "kbnVislibVisTypes.thresholdLine.style.dotdashedText": "点線", - "kbnVislibVisTypes.thresholdLine.style.fullText": "完全", + "home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.auditbeat.premInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.auditbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.auditbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.auditbeatCloudInstructions.config.debTitle": "構成の変更", + "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.auditbeatCloudInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.auditbeatCloudInstructions.config.rpmTitle": "構成の変更", + "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.auditbeatCloudInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.auditbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.auditbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.auditbeatInstructions.config.debTitle": "構成の変更", + "home.tutorials.common.auditbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.auditbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.auditbeatInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.auditbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.auditbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.auditbeatInstructions.config.rpmTitle": "構成の変更", + "home.tutorials.common.auditbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.auditbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.auditbeatInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.auditbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl}) をご覧ください。", + "home.tutorials.common.auditbeatInstructions.install.debTextPre": "Auditbeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", + "home.tutorials.common.auditbeatInstructions.install.debTitle": "Auditbeat のダウンロードとインストール", + "home.tutorials.common.auditbeatInstructions.install.osxTextPre": "Auditbeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", + "home.tutorials.common.auditbeatInstructions.install.osxTitle": "Auditbeat のダウンロードとインストール", + "home.tutorials.common.auditbeatInstructions.install.rpmTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl}) をご覧ください。", + "home.tutorials.common.auditbeatInstructions.install.rpmTextPre": "Auditbeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", + "home.tutorials.common.auditbeatInstructions.install.rpmTitle": "Auditbeat のダウンロードとインストール", + "home.tutorials.common.auditbeatInstructions.install.windowsTextPost": "{auditbeatPath} ファイルの {propertyName} を Elasticsearch のインストールに設定します。", + "home.tutorials.common.auditbeatInstructions.install.windowsTextPre": "Auditbeat は初めてですか?[入門ガイド]({guideLinkUrl}) をご覧ください。\n 1.[ダウンロード]({auditbeatLinkUrl}) ページから Auditbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Auditbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Auditbeat を Windows サービスとしてインストールします。", + "home.tutorials.common.auditbeatInstructions.install.windowsTitle": "Auditbeat のダウンロードとインストール", + "home.tutorials.common.auditbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.auditbeatInstructions.start.debTitle": "Auditbeat を起動", + "home.tutorials.common.auditbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.auditbeatInstructions.start.osxTitle": "Auditbeat を起動", + "home.tutorials.common.auditbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.auditbeatInstructions.start.rpmTitle": "Auditbeat を起動", + "home.tutorials.common.auditbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.auditbeatInstructions.start.windowsTitle": "Auditbeat を起動", + "home.tutorials.common.auditbeatStatusCheck.buttonLabel": "データを確認してください", + "home.tutorials.common.auditbeatStatusCheck.errorText": "まだデータを受信していません", + "home.tutorials.common.auditbeatStatusCheck.successText": "データを受信しました", + "home.tutorials.common.auditbeatStatusCheck.text": "Auditbeat からデータを受け取ったことを確認してください。", + "home.tutorials.common.auditbeatStatusCheck.title": "ステータス", + "home.tutorials.common.filebeat.cloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.filebeat.premCloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.filebeat.premInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.filebeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.filebeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.filebeatCloudInstructions.config.debTitle": "構成の変更", + "home.tutorials.common.filebeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.filebeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.filebeatCloudInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.filebeatCloudInstructions.config.rpmTitle": "構成の変更", + "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.filebeatCloudInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.filebeatEnableInstructions.debTextPost": "「/etc/filebeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", + "home.tutorials.common.filebeatEnableInstructions.debTitle": "{moduleName} モジュールを有効にし構成します", + "home.tutorials.common.filebeatEnableInstructions.osxTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", + "home.tutorials.common.filebeatEnableInstructions.osxTextPre": "インストールディレクトリから次のファイルを実行します:", + "home.tutorials.common.filebeatEnableInstructions.osxTitle": "{moduleName} モジュールを有効にし構成します", + "home.tutorials.common.filebeatEnableInstructions.rpmTextPost": "「/etc/filebeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", + "home.tutorials.common.filebeatEnableInstructions.rpmTitle": "{moduleName} モジュールを有効にし構成します", + "home.tutorials.common.filebeatEnableInstructions.windowsTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", + "home.tutorials.common.filebeatEnableInstructions.windowsTextPre": "「{path}」フォルダから次のファイルを実行します:", + "home.tutorials.common.filebeatEnableInstructions.windowsTitle": "{moduleName} モジュールを有効にし構成します", + "home.tutorials.common.filebeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.filebeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.filebeatInstructions.config.debTitle": "構成の変更", + "home.tutorials.common.filebeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.filebeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.filebeatInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.filebeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.filebeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.filebeatInstructions.config.rpmTitle": "構成の変更", + "home.tutorials.common.filebeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.filebeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.filebeatInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.filebeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl}) をご覧ください。", + "home.tutorials.common.filebeatInstructions.install.debTextPre": "Filebeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", + "home.tutorials.common.filebeatInstructions.install.debTitle": "Filebeat のダウンロードとインストール", + "home.tutorials.common.filebeatInstructions.install.osxTextPre": "Filebeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", + "home.tutorials.common.filebeatInstructions.install.osxTitle": "Filebeat のダウンロードとインストール", + "home.tutorials.common.filebeatInstructions.install.rpmTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl}) をご覧ください。", + "home.tutorials.common.filebeatInstructions.install.rpmTextPre": "Filebeat は初めてですか?[入門ガイド]({linkUrl}) をご覧ください。", + "home.tutorials.common.filebeatInstructions.install.rpmTitle": "Filebeat のダウンロードとインストール", + "home.tutorials.common.filebeatInstructions.install.windowsTextPost": "{filebeatPath} ファイルの {propertyName} を Elasticsearch のインストールに設定します。", + "home.tutorials.common.filebeatInstructions.install.windowsTextPre": "Filebeat は初めてですか?[入門ガイド]({guideLinkUrl}) をご覧ください。\n 1.[ダウンロード]({filebeatLinkUrl}) ページから Filebeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Filebeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Filebeat を Windows サービスとしてインストールします。", + "home.tutorials.common.filebeatInstructions.install.windowsTitle": "Filebeat のダウンロードとインストール", + "home.tutorials.common.filebeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.filebeatInstructions.start.debTitle": "Filebeat を起動します", + "home.tutorials.common.filebeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.filebeatInstructions.start.osxTitle": "Filebeat を起動します", + "home.tutorials.common.filebeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.filebeatInstructions.start.rpmTitle": "Filebeat を起動します", + "home.tutorials.common.filebeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.filebeatInstructions.start.windowsTitle": "Filebeat を起動します", + "home.tutorials.common.filebeatStatusCheck.buttonLabel": "データを確認してください", + "home.tutorials.common.filebeatStatusCheck.errorText": "モジュールからまだデータを受け取っていません", + "home.tutorials.common.filebeatStatusCheck.successText": "このモジュールからデータを受け取りました", + "home.tutorials.common.filebeatStatusCheck.text": "Filebeat の「{moduleName}」モジュールからデータを受け取ったことを確認してください。", + "home.tutorials.common.filebeatStatusCheck.title": "モジュールステータス", + "home.tutorials.common.functionbeat.cloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.functionbeat.premCloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.functionbeat.premInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.functionbeatAWSInstructions.textPost": "「」と「」がアカウント 認証情報で、「us-east-1」が希望の地域です。", + "home.tutorials.common.functionbeatAWSInstructions.textPre": "環境で AWS アカウント認証情報を設定します。", + "home.tutorials.common.functionbeatAWSInstructions.title": "AWS 認証情報の設定", + "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.functionbeatCloudInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.functionbeatCloudInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTextPost": "「」が投入するロググループの名前で、「」が Functionbeat デプロイのステージングに使用されるが有効な S3 バケット名です。", + "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTitle": "Cloudwatch ロググループの構成", + "home.tutorials.common.functionbeatEnableOnPremInstructionsOSXLinux.textPre": "「functionbeat.yml」ファイルで設定を変更します。", + "home.tutorials.common.functionbeatEnableOnPremInstructionsWindows.textPre": "{path} ファイルで設定を変更します。", + "home.tutorials.common.functionbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.functionbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.functionbeatInstructions.config.osxTitle": "Elastic クラスターの構成", + "home.tutorials.common.functionbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.functionbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.functionbeatInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.functionbeatInstructions.deploy.osxTextPre": "これにより Functionbeat が Lambda 関数としてインストールされます「setup」コマンドで Elasticsearch の構成を確認し、Kibana インデックスパターンを読み込みます。通常このコマンドを省いても大丈夫です。", + "home.tutorials.common.functionbeatInstructions.deploy.osxTitle": "Functionbeat を AWS Lambda にデプロイ", + "home.tutorials.common.functionbeatInstructions.deploy.windowsTextPre": "これにより Functionbeat が Lambda 関数としてインストールされます「setup」コマンドで Elasticsearch の構成を確認し、Kibana インデックスパターンを読み込みます。通常このコマンドを省いても大丈夫です。", + "home.tutorials.common.functionbeatInstructions.deploy.windowsTitle": "Functionbeat を AWS Lambda にデプロイ", + "home.tutorials.common.functionbeatInstructions.install.linuxTextPre": "Functionbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.functionbeatInstructions.install.linuxTitle": "Functionbeat のダウンロードとインストール", + "home.tutorials.common.functionbeatInstructions.install.osxTextPre": "Functionbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.functionbeatInstructions.install.osxTitle": "Functionbeat のダウンロードとインストール", + "home.tutorials.common.functionbeatInstructions.install.windowsTextPre": "Functionbeat は初めてですか?[入門ガイド]({functionbeatLink}) をご覧ください。\n 1.[ダウンロード]({elasticLink}) ページから Functionbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.{directoryName} ディレクトリの名前を「Functionbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトから、Functionbeat ディレクトリに移動します:", + "home.tutorials.common.functionbeatInstructions.install.windowsTitle": "Functionbeat のダウンロードとインストール", + "home.tutorials.common.functionbeatStatusCheck.buttonLabel": "データを確認してください", + "home.tutorials.common.functionbeatStatusCheck.errorText": "Functionbeat からまだデータを受け取っていません", + "home.tutorials.common.functionbeatStatusCheck.successText": "Functionbeat からデータを受け取りました", + "home.tutorials.common.functionbeatStatusCheck.text": "Functionbeat からデータを受け取ったことを確認してください。", + "home.tutorials.common.functionbeatStatusCheck.title": "Functionbeat ステータス", + "home.tutorials.common.heartbeat.cloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.heartbeat.premCloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.heartbeat.premInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.heartbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.heartbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.heartbeatCloudInstructions.config.debTitle": "構成の変更", + "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.heartbeatCloudInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.heartbeatCloudInstructions.config.rpmTitle": "構成の変更", + "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.heartbeatCloudInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.heartbeatEnableCloudInstructions.debTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", + "home.tutorials.common.heartbeatEnableCloudInstructions.defaultTextPost": "Heartbeat のモニターの設定の詳細は、[Heartbeat 設定ドキュメント]({configureLink}) をご覧ください。", + "home.tutorials.common.heartbeatEnableCloudInstructions.defaultTitle": "設定の変更 - モニターの追加", + "home.tutorials.common.heartbeatEnableCloudInstructions.osxTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", + "home.tutorials.common.heartbeatEnableCloudInstructions.rpmTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", + "home.tutorials.common.heartbeatEnableCloudInstructions.windowsTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.debTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTextPost": "{hostTemplate} は監視対象の URL です。Heartbeat のモニターの設定の詳細は、[Heartbeat 設定ドキュメント]({configureLink}) をご覧ください。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTitle": "設定の変更 - モニターの追加", + "home.tutorials.common.heartbeatEnableOnPremInstructions.osxTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.rpmTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.windowsTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", + "home.tutorials.common.heartbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.heartbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.heartbeatInstructions.config.debTitle": "構成の変更", + "home.tutorials.common.heartbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.heartbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.heartbeatInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.heartbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.heartbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.heartbeatInstructions.config.rpmTitle": "構成の変更", + "home.tutorials.common.heartbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.heartbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.heartbeatInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.heartbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({link}) をご覧ください。", + "home.tutorials.common.heartbeatInstructions.install.debTextPre": "Heartbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.heartbeatInstructions.install.debTitle": "Heartbeat のダウンロードとインストール", + "home.tutorials.common.heartbeatInstructions.install.osxTextPre": "Heartbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.heartbeatInstructions.install.osxTitle": "Heartbeat のダウンロードとインストール", + "home.tutorials.common.heartbeatInstructions.install.rpmTextPre": "Heartbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.heartbeatInstructions.install.rpmTitle": "Heartbeat のダウンロードとインストール", + "home.tutorials.common.heartbeatInstructions.install.windowsTextPre": "Heartbeat は初めてですか?[入門ガイド]({heartbeatLink}) をご覧ください。\n 1.[ダウンロード]({elasticLink}) ページから Heartbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Heartbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Heartbeat を Windows サービスとしてインストールします。", + "home.tutorials.common.heartbeatInstructions.install.windowsTitle": "Heartbeat のダウンロードとインストール", + "home.tutorials.common.heartbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", + "home.tutorials.common.heartbeatInstructions.start.debTitle": "Heartbeat を起動します", + "home.tutorials.common.heartbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", + "home.tutorials.common.heartbeatInstructions.start.osxTitle": "Heartbeat を起動します", + "home.tutorials.common.heartbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", + "home.tutorials.common.heartbeatInstructions.start.rpmTitle": "Heartbeat を起動します", + "home.tutorials.common.heartbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", + "home.tutorials.common.heartbeatInstructions.start.windowsTitle": "Heartbeat を起動します", + "home.tutorials.common.heartbeatStatusCheck.buttonLabel": "データを確認してください", + "home.tutorials.common.heartbeatStatusCheck.errorText": "Heartbeat からまだデータを受け取っていません", + "home.tutorials.common.heartbeatStatusCheck.successText": "Heartbeat からデータを受け取りました", + "home.tutorials.common.heartbeatStatusCheck.text": "Heartbeat からデータを受け取ったことを確認してください。", + "home.tutorials.common.heartbeatStatusCheck.title": "Heartbeat のステータス", + "home.tutorials.common.logstashInstructions.install.java.osxTextPre": "[こちら]({link}) のインストール手順に従ってください。", + "home.tutorials.common.logstashInstructions.install.java.osxTitle": "Java Runtime Environment のダウンロードとインストール", + "home.tutorials.common.logstashInstructions.install.java.windowsTextPre": "[こちら]({link}) のインストール手順に従ってください。", + "home.tutorials.common.logstashInstructions.install.java.windowsTitle": "Java Runtime Environment のダウンロードとインストール", + "home.tutorials.common.logstashInstructions.install.logstash.osxTextPre": "Logstash は初めてですか? [入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.logstashInstructions.install.logstash.osxTitle": "Logstash のダウンロードとインストール", + "home.tutorials.common.logstashInstructions.install.logstash.windowsTextPre": "Logstash は初めてですか? [入門ガイド]({logstashLink}) をご覧ください。\n 1. Logstash Windows zip ファイルを [ダウンロード]({elasticLink}) します。\n 2.zip ファイルのコンテンツを展開します。", + "home.tutorials.common.logstashInstructions.install.logstash.windowsTitle": "Logstash のダウンロードとインストール", + "home.tutorials.common.metricbeat.cloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.metricbeat.premCloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.metricbeat.premInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.metricbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.metricbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.metricbeatCloudInstructions.config.debTitle": "構成の変更", + "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.metricbeatCloudInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.metricbeatCloudInstructions.config.rpmTitle": "構成の変更", + "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.metricbeatCloudInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.metricbeatEnableInstructions.debTextPost": "「/etc/metricbeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", + "home.tutorials.common.metricbeatEnableInstructions.debTitle": "{moduleName} モジュールを有効にし構成します", + "home.tutorials.common.metricbeatEnableInstructions.osxTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", + "home.tutorials.common.metricbeatEnableInstructions.osxTextPre": "インストールディレクトリから次のファイルを実行します:", + "home.tutorials.common.metricbeatEnableInstructions.osxTitle": "{moduleName} モジュールを有効にし構成します", + "home.tutorials.common.metricbeatEnableInstructions.rpmTextPost": "「/etc/metricbeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", + "home.tutorials.common.metricbeatEnableInstructions.rpmTitle": "{moduleName} モジュールを有効にし構成します", + "home.tutorials.common.metricbeatEnableInstructions.windowsTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", + "home.tutorials.common.metricbeatEnableInstructions.windowsTextPre": "「{path}」フォルダから次のファイルを実行します:", + "home.tutorials.common.metricbeatEnableInstructions.windowsTitle": "{moduleName} モジュールを有効にし構成します", + "home.tutorials.common.metricbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.metricbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.metricbeatInstructions.config.debTitle": "構成の変更", + "home.tutorials.common.metricbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.metricbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.metricbeatInstructions.config.osxTitle": "構成の変更", + "home.tutorials.common.metricbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.metricbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.metricbeatInstructions.config.rpmTitle": "構成の変更", + "home.tutorials.common.metricbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.metricbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.metricbeatInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.metricbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({link}) をご覧ください。", + "home.tutorials.common.metricbeatInstructions.install.debTextPre": "Metricbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.metricbeatInstructions.install.debTitle": "Metricbeat のダウンロードとインストール", + "home.tutorials.common.metricbeatInstructions.install.osxTextPre": "Metricbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.metricbeatInstructions.install.osxTitle": "Metricbeat のダウンロードとインストール", + "home.tutorials.common.metricbeatInstructions.install.rpmTextPre": "Metricbeat は初めてですか?[入門ガイド]({link}) をご覧ください。", + "home.tutorials.common.metricbeatInstructions.install.rpmTitle": "Metricbeat のダウンロードとインストール", + "home.tutorials.common.metricbeatInstructions.install.windowsTextPost": "{path} ファイルの「output.elasticsearch」を Elasticsearch のインストールに設定します。", + "home.tutorials.common.metricbeatInstructions.install.windowsTextPre": "Metricbeat は初めてですか?[入門ガイド]({metricbeatLink}) をご覧ください。\n 1.[ダウンロード]({elasticLink}) ページから Metricbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Metricbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Metricbeat を Windows サービスとしてインストールします。", + "home.tutorials.common.metricbeatInstructions.install.windowsTitle": "Metricbeat のダウンロードとインストール", + "home.tutorials.common.metricbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.metricbeatInstructions.start.debTitle": "Metricbeat を起動します", + "home.tutorials.common.metricbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.metricbeatInstructions.start.osxTitle": "Metricbeat を起動します", + "home.tutorials.common.metricbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.metricbeatInstructions.start.rpmTitle": "Metricbeat を起動します", + "home.tutorials.common.metricbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.metricbeatInstructions.start.windowsTitle": "Metricbeat を起動します", + "home.tutorials.common.metricbeatStatusCheck.buttonLabel": "データを確認してください", + "home.tutorials.common.metricbeatStatusCheck.errorText": "モジュールからまだデータを受け取っていません", + "home.tutorials.common.metricbeatStatusCheck.successText": "このモジュールからデータを受け取りました", + "home.tutorials.common.metricbeatStatusCheck.text": "Metricbeat の「{moduleName}」モジュールからデータを受け取ったことを確認してください", + "home.tutorials.common.metricbeatStatusCheck.title": "モジュールステータス", + "home.tutorials.common.premCloudInstructions.option1.textPre": "[Elastic Cloud] ({link}) にアクセスします。アカウントをお持ちでない場合は新規登録してください。14 日間の無料トライアルがご利用いただけます。\n\nElastic Cloud コンソールにログインします\n\nElastic Cloud コンソールで次の手順を実行し、クラスターを作成します。\n 1.「デプロイを作成」、「デプロイ名」の順にクリックします\n 2.必要に応じて他のデプロイオプションを変更します (デフォルトも使い始めるのに有効です)\n 3.「デプロイを作成」をクリックします\n 4.デプロイの作成が完了するまで待ちます\n 5.新規クラウド Kibana インスタンスにアクセスし、Kibana ホームの手順に従います。", + "home.tutorials.common.premCloudInstructions.option1.title": "オプション 1:Elastic Cloud でお試しください", + "home.tutorials.common.premCloudInstructions.option2.textPre": "この Kibana インスタンスをマネージド Elasticsearch インスタンスに対して実行している場合は、手動セットアップを行います。.\n\n「Elasticsearch」エンドポイントを {urlTemplate} として保存し、クラスターの「パスワード」を {passwordTemplate} として保存します。", + "home.tutorials.common.premCloudInstructions.option2.title": "オプション 2:Kibana を Cloud インスタンスに接続", + "home.tutorials.common.winlogbeat.cloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.winlogbeat.premCloudInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.winlogbeat.premInstructions.gettingStarted.title": "はじめに", + "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", + "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.winlogbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", + "home.tutorials.common.winlogbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", + "home.tutorials.common.winlogbeatInstructions.config.windowsTitle": "構成の変更", + "home.tutorials.common.winlogbeatInstructions.install.windowsTextPost": "{path} ファイルの「output.elasticsearch」を Elasticsearch のインストールに設定します。", + "home.tutorials.common.winlogbeatInstructions.install.windowsTextPre": "Winlogbeat は初めてですか?[入門ガイド]({winlogbeatLink}) をご覧ください。\n 1.[ダウンロード]({elasticLink}) ページから Winlogbeat Windows zip ファイルをダウンロードします。\n 2.zip ファイルのコンテンツを {folderPath} に解凍します。\n 3.{directoryName} ディレクトリの名前を「Winlogbeat」に変更します。\n 4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Winlogbeat を Windows サービスとしてインストールします。", + "home.tutorials.common.winlogbeatInstructions.install.windowsTitle": "Winlogbeat のダウンロードとインストール", + "home.tutorials.common.winlogbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードが既にセットアップされている場合、このコマンドは省略します。", + "home.tutorials.common.winlogbeatInstructions.start.windowsTitle": "Winlogbeat を起動", + "home.tutorials.common.winlogbeatStatusCheck.buttonLabel": "データを確認してください", + "home.tutorials.common.winlogbeatStatusCheck.errorText": "まだデータを受信していません", + "home.tutorials.common.winlogbeatStatusCheck.successText": "データを受信しました", + "home.tutorials.common.winlogbeatStatusCheck.text": "Winlogbeat からデータを受け取ったことを確認してください。", + "home.tutorials.common.winlogbeatStatusCheck.title": "モジュールステータス", + "home.tutorials.aerospikeMetrics.artifacts.application.label": "ディスカバリ", + "home.tutorials.aerospikeMetrics.longDescription": "「aerospike」Metricbeat モジュールは、Aerospike から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.aerospikeMetrics.nameTitle": "Aerospike メトリック", + "home.tutorials.aerospikeMetrics.shortDescription": "Aerospike サーバーから内部メトリックを取得します。", + "home.tutorials.apacheLogs.artifacts.dashboards.linkLabel": "Apache ログダッシュボード", + "home.tutorials.apacheLogs.longDescription": "apache Filebeat モジュールが、Apache 2 HTTP サーバーにより作成されたアクセスとエラーのログをパースします。[詳細]({learnMoreLink})。", + "home.tutorials.apacheLogs.nameTitle": "Apache ログ", + "home.tutorials.apacheLogs.shortDescription": "Apache HTTP サーバーが作成したアクセスとエラーのログを収集しパースします。", + "home.tutorials.apacheMetrics.artifacts.dashboards.linkLabel": "Apache メトリックダッシュボード", + "home.tutorials.apacheMetrics.longDescription": "「apache」Metricbeat モジュールは、Apache 2 HTTP サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.apacheMetrics.nameTitle": "Apache メトリック", + "home.tutorials.apacheMetrics.shortDescription": "Apache 2 HTTP サーバーから内部メトリックを取得します。", + "home.tutorials.auditbeat.artifacts.dashboards.linkLabel": "SIEM アプリ", + "home.tutorials.auditbeat.longDescription": "Auditbeat を使用してホストから監査データを収集します。これらにはプロセス、ユーザー、ログイン、ソケット情報、ファイルアクセス、その他が含まれます。[詳細]({learnMoreLink})。", + "home.tutorials.auditbeat.nameTitle": "Auditbeat", + "home.tutorials.auditbeat.shortDescription": "ホストから監査データを収集します。", + "home.tutorials.awsMetrics.artifacts.dashboards.linkLabel": "AWS メトリックダッシュボード", + "home.tutorials.awsMetrics.longDescription": "「aws」Metricbeat モジュールが、AWS API と Cloudwatch から監視メトリックを取得します。[詳細]({learnMoreLink})。", + "home.tutorials.awsMetrics.nameTitle": "AWS メトリック", + "home.tutorials.awsMetrics.shortDescription": "AWS API と Cloudwatch からの EC2 インスタンスの監視メトリックです。", + "home.tutorials.cephMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.cephMetrics.longDescription": "「ceph」Metricbeat モジュールは、Ceph から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.cephMetrics.nameTitle": "Ceph メトリック", + "home.tutorials.cephMetrics.shortDescription": "Ceph サーバーから内部メトリックを取得します。", + "home.tutorials.ciscoLogs.artifacts.dashboards.linkLabel": "SIEM アプリ", + "home.tutorials.ciscoLogs.longDescription": "これは Cisco ネットワークデバイスのログ用のモジュールです。現在、同期された、またはファイルから読み込まれた Cisco ASA ファイアウォールログの「asa」ファイルセットをサポートしています。[詳細]({learnMoreLink})。", + "home.tutorials.ciscoLogs.nameTitle": "Cisco", + "home.tutorials.ciscoLogs.shortDescription": "Cisco ASA ファイアウォールからのログを収集・解析します。", + "home.tutorials.cloudwatchLogs.longDescription": "Functionbeat を AWS Lambda 関数として実行するようデプロイし、Cloudwatch ログを収集します。 [詳細({learnMoreLink})。", + "home.tutorials.cloudwatchLogs.nameTitle": "Cloudwatch ログ", + "home.tutorials.cloudwatchLogs.shortDescription": "Functionbeat で Cloudwatch ログを収集します。", + "home.tutorials.corednsLogs.artifacts.dashboards.linkLabel": "CoreDNS ログダッシュボード", + "home.tutorials.corednsLogs.longDescription": "「coredns」Filebeat モジュールは、[CoreDNS](https://coredns.io/manual/toc/) からログを収集します。[詳細]({learnMoreLink})。", + "home.tutorials.corednsLogs.nameTitle": "CoreDNS ログ", + "home.tutorials.corednsLogs.shortDescription": "Coredns により作成されたログを収集します。", + "home.tutorials.corednsMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.corednsMetrics.longDescription": "「coredns」Metricbeat モジュールが、CoreDNS から監視メトリックを取得します。[詳細({learnMoreLink})。", + "home.tutorials.corednsMetrics.nameTitle": "CoreDNS メトリック", + "home.tutorials.corednsMetrics.shortDescription": "CoreDNS サーバーから監視メトリックを取得します。", + "home.tutorials.couchbaseMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.couchbaseMetrics.longDescription": "「couchbase」Metricbeat モジュールは、Couchbase から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.couchbaseMetrics.nameTitle": "Couchbase メトリック", + "home.tutorials.couchbaseMetrics.shortDescription": "Couchbase から内部メトリックを取得します。", + "home.tutorials.couchdbMetrics.artifacts.dashboards.linkLabel": "CouchDB メトリックダッシュボード", + "home.tutorials.couchdbMetrics.longDescription": "「couchdb」Metricbeat モジュールが、CouchDB から監視メトリックを取得します。[詳細] ({learnMoreLink})。", + "home.tutorials.couchdbMetrics.nameTitle": "CouchDB メトリック", + "home.tutorials.couchdbMetrics.shortDescription": "CouchdB サーバーから監視メトリックを取得します。", + "home.tutorials.dockerMetrics.artifacts.dashboards.linkLabel": "Docker メトリックダッシュボード", + "home.tutorials.dockerMetrics.longDescription": "「docker」 Metricbeat モジュールは、Docker サーバーからメトリックを取得します。[詳細]({learnMoreLink})。", + "home.tutorials.dockerMetrics.nameTitle": "Docker メトリック", + "home.tutorials.dockerMetrics.shortDescription": "Docker コンテナーに関するメトリックを取得します。", + "home.tutorials.dropwizardMetrics.artifacts.application.label": "ディスカバリ", + "home.tutorials.dropwizardMetrics.longDescription": "「dropwizard」 Metricbeat モジュールは、Dropwizard Java アプリケーション から内部メトリックを取得します。[詳細[]({learnMoreLink})。", + "home.tutorials.dropwizardMetrics.nameTitle": "Dropwizard メトリック", + "home.tutorials.dropwizardMetrics.shortDescription": "Dropwizard Java アプリケーションから内部メトリックを取得します。", + "home.tutorials.elasticsearchLogs.artifacts.application.label": "ディスカバー", + "home.tutorials.elasticsearchLogs.longDescription": "「elasticsearch」Filebeat モジュールが、Elasticsearch により作成されたログをパースします。[詳細({learnMoreLink})。", + "home.tutorials.elasticsearchLogs.nameTitle": "Elasticsearch ログ", + "home.tutorials.elasticsearchLogs.shortDescription": "Elasticsearch により作成されたログを収集しパースします。", + "home.tutorials.elasticsearchMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.elasticsearchMetrics.longDescription": "「elasticsearch」Metricbeat モジュールは、Elasticsearch から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.elasticsearchMetrics.nameTitle": "Elasticsearch メトリック", + "home.tutorials.elasticsearchMetrics.shortDescription": "Elasticsearch から内部メトリックを取得します。", + "home.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel": "SIEM アプリ", + "home.tutorials.envoyproxyLogs.longDescription": "これは [Envoy proxy access log](https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log) 用の Filebeatモジュールです。Kubernetes でのスタンドアロンのデプロイメントと Envoy プロキシデプロイメントの両方をサポートします。[詳細]({learnMoreLink})。", + "home.tutorials.envoyproxyLogs.nameTitle": "Envoyproxy", + "home.tutorials.envoyproxyLogs.shortDescription": "Envoy プロキシからのログを収集・解析します。", + "home.tutorials.etcdMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.etcdMetrics.longDescription": "「etcd」Metricbeat モジュールは、Etcd から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.etcdMetrics.nameTitle": "Etcd メトリック", + "home.tutorials.etcdMetrics.shortDescription": "Etcd サーバーから内部メトリックを取得します。", + "home.tutorials.golangMetrics.artifacts.dashboards.linkLabel": "Golang メトリックダッシュボード", + "home.tutorials.golangMetrics.longDescription": "「{moduleName}」Metricbeat モジュールは、Golang アプリから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.golangMetrics.nameTitle": "Golang メトリック", + "home.tutorials.golangMetrics.shortDescription": "Golang アプリから内部メトリックを取得します。", + "home.tutorials.haproxyMetrics.artifacts.application.label": "ディスカバリ", + "home.tutorials.haproxyMetrics.longDescription": "「haproxy」Metricbeat モジュールは、HAProxy アプリから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.haproxyMetrics.nameTitle": "HAProxy メトリック", + "home.tutorials.haproxyMetrics.shortDescription": "HAProxy サーバーから内部メトリックを取得します。", + "home.tutorials.iisLogs.artifacts.dashboards.linkLabel": "IIS ログダッシュボード", + "home.tutorials.iisLogs.longDescription": "「iis」Filebeat モジュールが、Nginx HTTP サーバーにより作成されたアクセスとエラーのログをパースします。[詳細]({learnMoreLink})。", + "home.tutorials.iisLogs.nameTitle": "IIS ログ", + "home.tutorials.iisLogs.shortDescription": "IIS HTTP サーバーにより作成されたアクセスとエラーのログを収集しパースします。", + "home.tutorials.iptablesLogs.artifacts.dashboards.linkLabel": "SIEM アプリ", + "home.tutorials.iptablesLogs.longDescription": "これは iptables と ip6tables ログ用のモジュールです。同期でネットワーク上で受信したログや、ファイルからのログを解析します。また、ルールセット名、ルール番号、トラフィックに実行されたアクション (許可/拒否) を含む、Ubiquiti ファイアウォールにより追加された接頭辞も認識できます。[詳細]({learnMoreLink})。", + "home.tutorials.iptablesLogs.nameTitle": "Iptables / Ubiquiti", + "home.tutorials.iptablesLogs.shortDescription": "iptables と ip6tables ログ、または Ubiqiti からのログを収集・解析します。", + "home.tutorials.kafkaLogs.artifacts.dashboards.linkLabel": "Kafka ログダッシュボード", + "home.tutorials.kafkaLogs.longDescription": "「kafka」Filebeat モジュールは、Kafka が作成したログをパースします。[詳細]({learnMoreLink})。", + "home.tutorials.kafkaLogs.nameTitle": "Kafka ログ", + "home.tutorials.kafkaLogs.shortDescription": "Kafka が作成したログを収集しパースします。", + "home.tutorials.kafkaMetrics.artifacts.application.label": "ディスカバリ", + "home.tutorials.kafkaMetrics.longDescription": "「kafka」Metricbeat モジュールは、Kafka から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.kafkaMetrics.nameTitle": "Kafka メトリック", + "home.tutorials.kafkaMetrics.shortDescription": "Kafka サーバーから内部メトリックを取得します。", + "home.tutorials.kibanaMetrics.artifacts.application.label": "ディスカバリ", + "home.tutorials.kibanaMetrics.longDescription": "「kibana」Metricbeat モジュールは、Kibana から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.kibanaMetrics.nameTitle": "Kibana メトリック", + "home.tutorials.kibanaMetrics.shortDescription": "Kibana から内部メトリックを取得します。", + "home.tutorials.kubernetesMetrics.artifacts.dashboards.linkLabel": "Kubernetes メトリックダッシュボード", + "home.tutorials.kubernetesMetrics.longDescription": "「kubernetes」Metricbeat モジュールは、Kubernetes API からメトリックを取得します。[詳細]({learnMoreLink})。", + "home.tutorials.kubernetesMetrics.nameTitle": "Kubernetes メトリック", + "home.tutorials.kubernetesMetrics.shortDescription": "Kubernetes からメトリックを取得します。", + "home.tutorials.logstashLogs.artifacts.dashboards.linkLabel": "Logstash ログダッシュボード", + "home.tutorials.logstashLogs.longDescription": "「logstash」Filebeat モジュールが、Logstash 自体により作成されたデバッグとスローログをパースします。[詳細]({learnMoreLink})。", + "home.tutorials.logstashLogs.nameTitle": "Logstash ログ", + "home.tutorials.logstashLogs.shortDescription": "Logstash 自体により作成されたデバッグとスローログをパースします。", + "home.tutorials.logstashMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.logstashMetrics.longDescription": "「{moduleName}」Metricbeat モジュールは、Logstash サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.logstashMetrics.nameTitle": "Logstash メトリック", + "home.tutorials.logstashMetrics.shortDescription": "Logstash サーバーから内部メトリックを取得します。", + "home.tutorials.memcachedMetrics.artifacts.application.label": "ディスカバリ", + "home.tutorials.memcachedMetrics.longDescription": "「memcached」Metricbeat モジュールは、Memcached から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.memcachedMetrics.nameTitle": "Memcached メトリック", + "home.tutorials.memcachedMetrics.shortDescription": "Memcached サーバーから内部メトリックを取得します。", + "home.tutorials.mongodbMetrics.artifacts.dashboards.linkLabel": "MongoDB メトリックダッシュボード", + "home.tutorials.mongodbMetrics.longDescription": "「mongodb」Metricbeat モジュールは、MongoDB サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.mongodbMetrics.nameTitle": "MongoDB メトリック", + "home.tutorials.mongodbMetrics.shortDescription": "MongoDB から内部メトリックを取得します。", + "home.tutorials.mssqlMetrics.artifacts.dashboards.linkLabel": "Microsoft SQL Server メトリックダッシュボード", + "home.tutorials.mssqlMetrics.longDescription": "「mssql」Metricbeat モジュールが、Microsoft SQL Server インスタンスからの監視、ログ、パフォーマンスメトリックを取得します。 詳細({learnMoreLink})。", + "home.tutorials.mssqlMetrics.nameTitle": "Microsoft SQL Server メトリック", + "home.tutorials.mssqlMetrics.shortDescription": "Microsoft SQL Server インスタンスから監視メトリックを取得します。", + "home.tutorials.muninMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.muninMetrics.longDescription": "「munin」Metricbeat モジュールは、Munin から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.muninMetrics.nameTitle": "Munin メトリック", + "home.tutorials.muninMetrics.shortDescription": "Munin サーバーから内部メトリックを取得します。", + "home.tutorials.mysqlLogs.artifacts.dashboards.linkLabel": "MySQL ログダッシュボード", + "home.tutorials.mysqlLogs.longDescription": "「mysql」Filebeat モジュールは、MySQL が作成したエラーとスローログをパースします。[詳細]({learnMoreLink}).", + "home.tutorials.mysqlLogs.nameTitle": "MySQL ログ", + "home.tutorials.mysqlLogs.shortDescription": "MySQL が作成したエラーとスローログを収集しパースします。", + "home.tutorials.mysqlMetrics.artifacts.dashboards.linkLabel": "MySQL メトリックダッシュボード", + "home.tutorials.mysqlMetrics.longDescription": "「mysql」Metricbeat モジュールは、MySQL サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.mysqlMetrics.nameTitle": "MySQL メトリック", + "home.tutorials.mysqlMetrics.shortDescription": "MySQL から内部メトリックを取得します。", + "home.tutorials.natsLogs.artifacts.dashboards.linkLabel": "Nats ログダッシュボード", + "home.tutorials.natsLogs.longDescription": "「nats」Filebeat モジュールが、Nats により作成されたログをパースします。[詳細]({learnMoreLink})。", + "home.tutorials.natsLogs.nameTitle": "Nats ログ", + "home.tutorials.natsLogs.shortDescription": "Nats により作成されたログを収集しパースします。", + "home.tutorials.natsMetrics.artifacts.dashboards.linkLabel": "Nats メトリックダッシュボード", + "home.tutorials.natsMetrics.longDescription": "「nats」Metricbeat モジュールが、Nats から監視メトリックを取得します。[詳細({learnMoreLink})。", + "home.tutorials.natsMetrics.nameTitle": "Nats メトリック", + "home.tutorials.natsMetrics.shortDescription": "Nats サーバーから監視メトリックを取得します。", + "home.tutorials.netflow.common.config.elasticCloud.osxTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートで、{password} は {elastic} ユーザーのパスワードです。", + "home.tutorials.netflow.common.config.elasticCloud.osxTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", + "home.tutorials.netflow.common.config.elasticCloud.osxTitle": "構成の変更", + "home.tutorials.netflow.common.config.elasticCloud.windowsTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートで、{password} は {elastic} ユーザーのパスワードです。", + "home.tutorials.netflow.common.config.elasticCloud.windowsTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", + "home.tutorials.netflow.common.config.elasticCloud.windowsTitle": "構成の変更", + "home.tutorials.netflow.common.config.onPrem.osxTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートです。", + "home.tutorials.netflow.common.config.onPrem.osxTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", + "home.tutorials.netflow.common.config.onPrem.osxTitle": "構成の変更", + "home.tutorials.netflow.common.config.onPrem.windowsTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートです。", + "home.tutorials.netflow.common.config.onPrem.windowsTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", + "home.tutorials.netflow.common.config.onPrem.windowsTitle": "構成の変更", + "home.tutorials.netflow.common.config.onPremElasticCloud.osxTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートで、{esUrl} は Elastic Cloud で実行中の Elasticsearch の URL で、{password} は {elastic} ユーザーのパスワードです。", + "home.tutorials.netflow.common.config.onPremElasticCloud.osxTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", + "home.tutorials.netflow.common.config.onPremElasticCloud.osxTitle": "構成の変更", + "home.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPost": "{udpPort} は Logstash が Netflow データを受信する UDP ポートで、{esUrl} は Elastic Cloud で実行中の Elasticsearch の URL で、{password} は {elastic} ユーザーのパスワードです。", + "home.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPre": "{logstashConfigPath} を編集して構成パラメーターを設定します。", + "home.tutorials.netflow.common.config.onPremElasticCloud.windowsTitle": "構成の変更", + "home.tutorials.netflow.common.setup.osxTextPost": "{setupOption} オプションは Elasticsearch で {netflowPrefix} インデックスパターンを作成し、Kibana ダッシュボードとビジュアライゼーションをインポートします。後の実行時には既存のダッシュボードに上書きしないよう、このオプションを省略します。", + "home.tutorials.netflow.common.setup.osxTextPre": "実行:", + "home.tutorials.netflow.common.setup.osxTitle": "Netflow モジュールを実行", + "home.tutorials.netflow.common.setup.windowsTextPost": "{setupOption} オプションは Elasticsearch で {netflowPrefix} インデックスパターンを作成し、Kibana ダッシュボードとビジュアライゼーションをインポートします。後の実行時には既存のダッシュボードに上書きしないよう、このオプションを省略します。", + "home.tutorials.netflow.common.setup.windowsTextPre": "実行:", + "home.tutorials.netflow.common.setup.windowsTitle": "Netflow モジュールの実行", + "home.tutorials.netflow.elasticCloudInstructions.title": "はじめに", + "home.tutorials.netflow.onPremElasticCloudInstructions.title": "はじめに", + "home.tutorials.netflow.onPremInstructions.title": "はじめに", + "home.tutorials.netflow.tutorialLongDescription": "Logstash NetFlow モジュールは、ネットワークフローデータを収集してパースしたり、イベントを Elasticsearch でインデックスしたり、Kibana ダッシュボードをインストールしたりできます。このモジュールは Netflow バージョン 5 と 9 をサポートしています。[詳細]({linkUrl})。", + "home.tutorials.netflow.tutorialShortDescription": "Netflow エクスポーターが送信した Netflow の記録を収集します。", + "home.tutorials.nginxLogs.artifacts.dashboards.linkLabel": "Nginx ログダッシュボード", + "home.tutorials.nginxLogs.longDescription": "「nginx」Filebeat モジュールは、Nginx HTTP サーバーが作成したアクセスとエラーのログをパースします。[詳細]({learnMoreLink})。", + "home.tutorials.nginxLogs.nameTitle": "Nginx ログ", + "home.tutorials.nginxLogs.shortDescription": "Nginx HTTP サーバーが作成したアクセスとエラーのログを収集しパースします。", + "home.tutorials.nginxMetrics.artifacts.dashboards.linkLabel": "Nginx メトリックダッシュボード", + "home.tutorials.nginxMetrics.longDescription": "「nginx」Metricbeat モジュールは、Nginx サーバーから内部メトリックを取得します。このモジュールは {statusModuleLink} が作成したウェブページからサーバーステータスデータを取得します。Nginx で {statusModuleLink} が有効にする必要があります。[詳細]({learnMoreLink})。", + "home.tutorials.nginxMetrics.nameTitle": "Nginx メトリック", + "home.tutorials.nginxMetrics.shortDescription": "Nginx HTTP サーバーから内部メトリックを取得します。", + "home.tutorials.osqueryLogs.artifacts.dashboards.linkLabel": "Osquery ログダッシュボード", + "home.tutorials.osqueryLogs.longDescription": "「osquery」Filebeat モジュールは、「osqueryd」が作成した JSON 結果ページを収集します。[詳細]({learnMoreLink})。", + "home.tutorials.osqueryLogs.nameTitle": "Osquery ログ", + "home.tutorials.osqueryLogs.shortDescription": "osqueryd により作成されたログを収集します。", + "home.tutorials.phpFpmMetrics.longDescription": "「php_fpm」Metricbeat モジュールは、PHP-FPM サーバーから内部メトリックを取得します。[詳細]({learnMoreLink})。", + "home.tutorials.phpFpmMetrics.nameTitle": "PHP-FPM メトリック", + "home.tutorials.phpFpmMetrics.shortDescription": "PHP-FPM から内部メトリックを取得します。", + "home.tutorials.postgresqlLogs.artifacts.dashboards.linkLabel": "PostgreSQL ログダッシュボード", + "home.tutorials.postgresqlLogs.longDescription": "「postgresql」Filebeat モジュールが、PostgreSQL により作成されたエラーとスローログをパースします。[詳細]({learnMoreLink}).", + "home.tutorials.postgresqlLogs.nameTitle": "PostgreSQL ログ", + "home.tutorials.postgresqlLogs.shortDescription": "PostgreSQL により作成されたエラーとスローログを収集しパースします。", + "home.tutorials.postgresqlMetrics.longDescription": "「postgresql」Metricbeat モジュールは、PostgreSQL サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.postgresqlMetrics.nameTitle": "PostgreSQL メトリック", + "home.tutorials.postgresqlMetrics.shortDescription": "PostgreSQL から内部メトリックを取得します。", + "home.tutorials.prometheusMetrics.artifacts.application.label": "ディスカバリ", + "home.tutorials.prometheusMetrics.longDescription": "「{moduleName}」Metricbeat モジュールは、Prometheus エンドポイントからメトリックを取得します。[詳細]({learnMoreLink})。", + "home.tutorials.prometheusMetrics.nameTitle": "Prometheus メトリック", + "home.tutorials.prometheusMetrics.shortDescription": "Prometheus エクスポーターからメトリックを取得します。.", + "home.tutorials.rabbitmqMetrics.artifacts.dashboards.linkLabel": "RabbitMQ メトリックダッシュボード", + "home.tutorials.rabbitmqMetrics.longDescription": "「rabbitmq」Metricbeat モジュールは、RabbitMQ サーバーから内部メトリックを取得します。[詳細]({learnMoreLink})。", + "home.tutorials.rabbitmqMetrics.nameTitle": "RabbitMQ メトリック", + "home.tutorials.rabbitmqMetrics.shortDescription": "RabbitMQ サーバーから内部メトリックを取得します。", + "home.tutorials.redisLogs.artifacts.dashboards.linkLabel": "Redis ログダッシュボード", + "home.tutorials.redisLogs.longDescription": "「redis」Filebeat モジュールは、Redis が作成したエラーとスローログをパースします。Redis がエラーログを作成するには、Redis 構成ファイルの「logfile」オプションが「redis-server.log」に設定されていることを確認してください。スローログは「SLOWLOG」コマンドで Redis から直接読み込まれます。Redis がスローログを記録するには、「slowlog-log-slower-than」オプションが設定されていることを確認してください。「slowlog」ファイルセットは実験的な機能のためご注意ください。[詳細]({learnMoreLink})。", + "home.tutorials.redisLogs.nameTitle": "Redis ログ", + "home.tutorials.redisLogs.shortDescription": "Redis が作成したエラーとスローログを収集しパースします。", + "home.tutorials.redisMetrics.artifacts.dashboards.linkLabel": "Redis メトリックダッシュボード", + "home.tutorials.redisMetrics.longDescription": "「redis」Metricbeat モジュールは、Redis サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.redisMetrics.nameTitle": "Redis メトリック", + "home.tutorials.redisMetrics.shortDescription": "Redis から内部メトリックを取得します。", + "home.tutorials.suricataLogs.artifacts.dashboards.linkLabel": "Suricata ログダッシュボード", + "home.tutorials.suricataLogs.longDescription": "「suricata」Filebeat モジュールは、[Suricata Eve JSON アウトプット](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html) からログを収集します。[詳細]({learnMoreLink})。", + "home.tutorials.suricataLogs.nameTitle": "Suricata ログ", + "home.tutorials.suricataLogs.shortDescription": "Suricata IDS/IPS/NSM が作成したログを収集します。", + "home.tutorials.systemLogs.artifacts.dashboards.linkLabel": "システムログダッシュボード", + "home.tutorials.systemLogs.longDescription": "「system」Filebeat モジュールは、一般的な Unix/Linux ベースのディストリビューションのシステムログサービスが作成したログを収集しパースします。このモジュールは Windows では利用できません。[詳細]({learnMoreLink})。", + "home.tutorials.systemLogs.nameTitle": "システムログ", + "home.tutorials.systemLogs.shortDescription": "ローカル Syslog サーバーが作成したログを収集しパースします。", + "home.tutorials.systemMetrics.artifacts.dashboards.linkLabel": "システムメトリックダッシュボード", + "home.tutorials.systemMetrics.longDescription": "「system」Metricbeat モジュールは、ホストから CPU、メモリー、ネットワーク、ディスクの統計を収集します。システム全体の統計とプロセスやファイルシステムごとの統計を収集します。[詳細]({learnMoreLink})。", + "home.tutorials.systemMetrics.nameTitle": "システムメトリック", + "home.tutorials.systemMetrics.shortDescription": "ホストから CPU、メモリー、ネットワーク、ディスクの統計を収集します。", + "home.tutorials.traefikLogs.artifacts.dashboards.linkLabel": "Traefik ログダッシュボード", + "home.tutorials.traefikLogs.longDescription": "「traefik」Filebeat モジュールが、Traefik により作成されたアクセスログをパースします。[詳細]({learnMoreLink})。", + "home.tutorials.traefikLogs.nameTitle": "Traefik ログ", + "home.tutorials.traefikLogs.shortDescription": "Traefik Proxy により作成されたアクセスログを収集しパースします。", + "home.tutorials.uptimeMonitors.artifacts.dashboards.linkLabel": "アップタイムアプリ", + "home.tutorials.uptimeMonitors.longDescription": "アクティブなプロービングでサービスの稼働状況を監視します。 Heartbeat が URL のリストに基づき、シンプ:にたずねます:生きてる?と [詳細]({learnMoreLink})。", + "home.tutorials.uptimeMonitors.nameTitle": "アップタイムモニター", + "home.tutorials.uptimeMonitors.shortDescription": "サービスの稼働状況を監視します。", + "home.tutorials.uwsgiMetrics.artifacts.dashboards.linkLabel": "uWSGI メトリックダッシュボード", + "home.tutorials.uwsgiMetrics.longDescription": "「uwsgi」Metricbeat モジュールは、uWSGI サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.uwsgiMetrics.nameTitle": "uWSGI メトリック", + "home.tutorials.uwsgiMetrics.shortDescription": "uWSGI サーバーから内部メトリックを取得します。", + "home.tutorials.vsphereMetrics.artifacts.application.label": "ディスカバリ", + "home.tutorials.vsphereMetrics.longDescription": "「vsphere」Metricbeat モジュールは、vSphere クラスターから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.vsphereMetrics.nameTitle": "vSphere メトリック", + "home.tutorials.vsphereMetrics.shortDescription": "vSphere から内部メトリックを取得します。", + "home.tutorials.windowsEventLogs.artifacts.application.label": "SIEM アプリ", + "home.tutorials.windowsEventLogs.longDescription": "Winlogbeat を使用して Windows Event Log からのログを収集します。[詳細]({learnMoreLink})。", + "home.tutorials.windowsEventLogs.nameTitle": "Windows Event Log", + "home.tutorials.windowsEventLogs.shortDescription": "Windows Event Log からイベントを取得します。", + "home.tutorials.windowsMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.windowsMetrics.longDescription": "「windows」Metricbeat モジュールは、Windows から内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.windowsMetrics.nameTitle": "Windows メトリック", + "home.tutorials.windowsMetrics.shortDescription": "Windows から内部メトリックを取得します。", + "home.tutorials.zeekLogs.artifacts.dashboards.linkLabel": "Zeek ログダッシュボード", + "home.tutorials.zeekLogs.longDescription": "「zeek」Filebeat モジュールが、[Zeek](https://www.zeek.org//documentation/index.html) からログを収集します。[詳細]({learnMoreLink})。", + "home.tutorials.zeekLogs.nameTitle": "Zeek ログ", + "home.tutorials.zeekLogs.shortDescription": "Zeek/Bro により作成されたログを収集します。", + "home.tutorials.zookeeperMetrics.artifacts.application.label": "ディスカバー", + "home.tutorials.zookeeperMetrics.longDescription": "「{moduleName}」Metricbeat モジュールは、Zookeeper サーバーから内部メトリックを取得します。 [詳細]({learnMoreLink})。", + "home.tutorials.zookeeperMetrics.nameTitle": "Zookeeper メトリック", + "home.tutorials.zookeeperMetrics.shortDescription": "Zookeeper サーバーから内部メトリックを取得します。", + "visTypeVislib.area.areaDescription": "折れ線グラフの下の数量を強調します。", + "visTypeVislib.area.areaTitle": "エリア", + "visTypeVislib.area.countText": "カウント", + "visTypeVislib.area.groupTitle": "系列を分割", + "visTypeVislib.area.metricsTitle": "Y 軸", + "visTypeVislib.area.radiusTitle": "点のサイズ", + "visTypeVislib.area.segmentTitle": "X 軸", + "visTypeVislib.area.splitTitle": "チャートを分割", + "visTypeVislib.area.tabs.metricsAxesTitle": "メトリックと軸", + "visTypeVislib.area.tabs.panelSettingsTitle": "パネル設定", + "visTypeVislib.axisModes.normalText": "標準", + "visTypeVislib.axisModes.percentageText": "パーセンテージ", + "visTypeVislib.axisModes.silhouetteText": "シルエット", + "visTypeVislib.axisModes.wiggleText": "振動", + "visTypeVislib.categoryAxis.rotate.angledText": "傾斜", + "visTypeVislib.categoryAxis.rotate.horizontalText": "横", + "visTypeVislib.categoryAxis.rotate.verticalText": "縦", + "visTypeVislib.chartModes.normalText": "標準", + "visTypeVislib.chartModes.stackedText": "スタック", + "visTypeVislib.chartTypes.areaText": "エリア", + "visTypeVislib.chartTypes.barText": "バー", + "visTypeVislib.chartTypes.lineText": "折れ線", + "visTypeVislib.controls.colorRanges.errorText": "各範囲は前の範囲よりも大きくなければなりません。", + "visTypeVislib.controls.colorSchema.colorSchemaLabel": "カラー図表", + "visTypeVislib.controls.colorSchema.howToChangeColorsDescription": "それぞれの色は凡例で変更できます。", + "visTypeVislib.controls.colorSchema.resetColorsButtonLabel": "色をリセット", + "visTypeVislib.controls.colorSchema.reverseColorSchemaLabel": "図表を反転", + "visTypeVislib.controls.gaugeOptions.alignmentLabel": "アラインメント", + "visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "範囲を自動拡張", + "visTypeVislib.controls.gaugeOptions.displayWarningsLabel": "警告を表示", + "visTypeVislib.controls.gaugeOptions.extendRangeTooltip": "範囲をデータの最高値に広げます。", + "visTypeVislib.controls.gaugeOptions.gaugeTypeLabel": "ゲージタイプ", + "visTypeVislib.controls.gaugeOptions.labelsTitle": "ラベル", + "visTypeVislib.controls.gaugeOptions.percentageModeLabel": "パーセンテージモード", + "visTypeVislib.controls.gaugeOptions.rangesTitle": "範囲", + "visTypeVislib.controls.gaugeOptions.showLabelsLabel": "ラベルを表示", + "visTypeVislib.controls.gaugeOptions.showLegendLabel": "凡例を表示", + "visTypeVislib.controls.gaugeOptions.showScaleLabel": "縮尺を表示", + "visTypeVislib.controls.gaugeOptions.styleTitle": "スタイル", + "visTypeVislib.controls.gaugeOptions.subTextLabel": "サブラベル", + "visTypeVislib.controls.gaugeOptions.switchWarningsTooltip": "警告のオン・オフを切り替えます。オンにすると、すべてのラベルを表示できない際に警告が表示されます。", + "visTypeVislib.controls.heatmapOptions.colorLabel": "色", + "visTypeVislib.controls.heatmapOptions.colorScaleLabel": "カラースケール", + "visTypeVislib.controls.heatmapOptions.colorsNumberLabel": "色の数", + "visTypeVislib.controls.heatmapOptions.labelsTitle": "ラベル", + "visTypeVislib.controls.heatmapOptions.overwriteAutomaticColorLabel": "自動からーを上書きする", + "visTypeVislib.controls.heatmapOptions.percentageModeLabel": "パーセンテージモード", + "visTypeVislib.controls.heatmapOptions.rotateLabel": "回転", + "visTypeVislib.controls.heatmapOptions.scaleToDataBoundsLabel": "データバウンドに合わせる", + "visTypeVislib.controls.heatmapOptions.showLabelsTitle": "ラベルを表示", + "visTypeVislib.controls.heatmapOptions.useCustomRangesLabel": "カスタム範囲を使用", + "visTypeVislib.controls.pointSeries.categoryAxis.alignLabel": "配置", + "visTypeVislib.controls.pointSeries.categoryAxis.filterLabelsLabel": "フィルターラベル", + "visTypeVislib.controls.pointSeries.categoryAxis.labelsTitle": "ラベル", + "visTypeVislib.controls.pointSeries.categoryAxis.positionLabel": "配置", + "visTypeVislib.controls.pointSeries.categoryAxis.showLabel": "表示", + "visTypeVislib.controls.pointSeries.categoryAxis.showLabelsLabel": "ラベルを表示", + "visTypeVislib.controls.pointSeries.categoryAxis.xAxisTitle": "X 軸", + "visTypeVislib.controls.pointSeries.gridAxis.dontShowLabel": "非表示", + "visTypeVislib.controls.pointSeries.gridAxis.gridText": "グリッド", + "visTypeVislib.controls.pointSeries.gridAxis.xAxisLinesLabel": "X 軸線を表示", + "visTypeVislib.controls.pointSeries.gridAxis.yAxisLinesDisabledTooltip": "ヒストグラムに X 軸線は表示できません。", + "visTypeVislib.controls.pointSeries.gridAxis.yAxisLinesLabel": "Y 軸線を表示", + "visTypeVislib.controls.pointSeries.series.chartTypeLabel": "チャートタイプ", + "visTypeVislib.controls.pointSeries.series.lineModeLabel": "線のモード", + "visTypeVislib.controls.pointSeries.series.lineWidthLabel": "線の幅", + "visTypeVislib.controls.pointSeries.series.metricsTitle": "メトリック", + "visTypeVislib.controls.pointSeries.series.modeLabel": "モード", + "visTypeVislib.controls.pointSeries.series.newAxisLabel": "新規軸…", + "visTypeVislib.controls.pointSeries.series.showDotsLabel": "点を表示", + "visTypeVislib.controls.pointSeries.series.showLineLabel": "線を表示", + "visTypeVislib.controls.pointSeries.series.valueAxisLabel": "値軸", + "visTypeVislib.controls.pointSeries.seriesAccordionAriaLabel": "{agg} オプションを切り替える", + "visTypeVislib.controls.pointSeries.valueAxes.addButtonTooltip": "Y 軸を追加します", + "visTypeVislib.controls.pointSeries.valueAxes.customExtentsLabel": "カスタム範囲", + "visTypeVislib.controls.pointSeries.valueAxes.maxLabel": "最高", + "visTypeVislib.controls.pointSeries.valueAxes.minErrorMessage": "最低値は最高値よりも低く設定する必要があります", + "visTypeVislib.controls.pointSeries.valueAxes.minLabel": "最低", + "visTypeVislib.controls.pointSeries.valueAxes.minNeededScaleText": "ログスケールが選択されている場合、最低値は 0 よりも大きいものである必要があります", + "visTypeVislib.controls.pointSeries.valueAxes.modeLabel": "モード", + "visTypeVislib.controls.pointSeries.valueAxes.positionLabel": "配置", + "visTypeVislib.controls.pointSeries.valueAxes.removeButtonTooltip": "Y 軸を削除します", + "visTypeVislib.controls.pointSeries.valueAxes.scaleToDataBounds.boundsMargin": "境界マージン", + "visTypeVislib.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin": "境界マージンは 0 以上でなければなりません", + "visTypeVislib.controls.pointSeries.valueAxes.scaleToDataBoundsLabel": "データバウンドに合わせる", + "visTypeVislib.controls.pointSeries.valueAxes.scaleTypeLabel": "スケールタイプ", + "visTypeVislib.controls.pointSeries.valueAxes.setAxisExtentsLabel": "軸の範囲の設定", + "visTypeVislib.controls.pointSeries.valueAxes.showLabel": "表示", + "visTypeVislib.controls.pointSeries.valueAxes.titleLabel": "タイトル", + "visTypeVislib.controls.pointSeries.valueAxes.toggleCustomExtendsAriaLabel": "カスタム範囲を切り替える", + "visTypeVislib.controls.pointSeries.valueAxes.toggleOptionsAriaLabel": "{axisName} オプションを切り替える", + "visTypeVislib.controls.pointSeries.valueAxes.yAxisTitle": "Y 軸", + "visTypeVislib.controls.rangeErrorMessage": "値は {min} と {max} の間でなければなりません", + "visTypeVislib.controls.truncateLabel": "切り捨て", + "visTypeVislib.controls.vislibBasicOptions.legendPositionLabel": "凡例の配置", + "visTypeVislib.controls.vislibBasicOptions.showTooltipLabel": "ツールヒントを表示", + "visTypeVislib.editors.heatmap.basicSettingsTitle": "基本設定", + "visTypeVislib.editors.heatmap.heatmapSettingsTitle": "ヒートマップ設定", + "visTypeVislib.editors.heatmap.highlightLabel": "ハイライト範囲", + "visTypeVislib.vislib.heatmap.maxBucketsText": "定義された数列が多すぎます ({nr}).構成されている最高値は {max} です。", + "visTypeVislib.editors.heatmap.highlightLabelTooltip": "チャートのカーソルを当てた部分と凡例の対応するラベルをハイライトします。", + "visTypeVislib.editors.pie.donutLabel": "ドーナッツ", + "visTypeVislib.editors.pie.labelsSettingsTitle": "ラベル設定", + "visTypeVislib.editors.pie.pieSettingsTitle": "パイ設定", + "visTypeVislib.editors.pie.showLabelsLabel": "ラベルを表示", + "visTypeVislib.editors.pie.showTopLevelOnlyLabel": "トップレベルのみ表示", + "visTypeVislib.editors.pie.showValuesLabel": "値を表示", + "visTypeVislib.editors.pointSeries.currentTimeMarkerLabel": "現在時刻マーカー", + "visTypeVislib.editors.pointSeries.orderBucketsBySumLabel": "バケットを合計で並べ替え", + "visTypeVislib.editors.pointSeries.settingsTitle": "設定", + "visTypeVislib.editors.pointSeries.showLabels": "チャートに値を表示", + "visTypeVislib.editors.pointSeries.thresholdLine.colorLabel": "ラインカラー", + "visTypeVislib.editors.pointSeries.thresholdLine.showLabel": "しきい線を表示", + "visTypeVislib.editors.pointSeries.thresholdLine.styleLabel": "ラインスタイル", + "visTypeVislib.editors.pointSeries.thresholdLine.valueLabel": "しきい値", + "visTypeVislib.editors.pointSeries.thresholdLine.widthLabel": "線の幅", + "visTypeVislib.editors.pointSeries.thresholdLineSettingsTitle": "しきい線", + "visTypeVislib.functions.pie.help": "パイビジュアライゼーション", + "visTypeVislib.functions.vislib.help": "Vislib ビジュアライゼーション", + "visTypeVislib.gauge.alignmentAutomaticTitle": "自動", + "visTypeVislib.gauge.alignmentHorizontalTitle": "横", + "visTypeVislib.gauge.alignmentVerticalTitle": "縦", + "visTypeVislib.gauge.gaugeDescription": "ゲージはメトリックのステータスを示します。メトリックの値としきい値との関連性を示すのに使用します。", + "visTypeVislib.gauge.gaugeTitle": "ゲージ", + "visTypeVislib.gauge.gaugeTypes.arcText": "弧形", + "visTypeVislib.gauge.gaugeTypes.circleText": "円", + "visTypeVislib.gauge.groupTitle": "グループを分割", + "visTypeVislib.gauge.metricTitle": "メトリック", + "visTypeVislib.goal.goalDescription": "ゴールチャートは、最終目標にどれだけ近いかを示します。", + "visTypeVislib.goal.goalTitle": "ゴール", + "visTypeVislib.goal.groupTitle": "グループを分割", + "visTypeVislib.goal.metricTitle": "メトリック", + "visTypeVislib.heatmap.groupTitle": "Y 軸", + "visTypeVislib.heatmap.heatmapDescription": "マトリックス内のセルに影をつける。", + "visTypeVislib.heatmap.heatmapTitle": "ヒートマップ", + "visTypeVislib.heatmap.metricTitle": "値", + "visTypeVislib.heatmap.segmentTitle": "X 軸", + "visTypeVislib.heatmap.splitTitle": "チャートを分割", + "visTypeVislib.histogram.groupTitle": "系列を分割", + "visTypeVislib.histogram.histogramDescription": "連続変数を各軸に割り当てる。", + "visTypeVislib.histogram.histogramTitle": "縦棒", + "visTypeVislib.histogram.metricTitle": "Y 軸", + "visTypeVislib.histogram.radiusTitle": "点のサイズ", + "visTypeVislib.histogram.segmentTitle": "X 軸", + "visTypeVislib.histogram.splitTitle": "チャートを分割", + "visTypeVislib.horizontalBar.groupTitle": "系列を分割", + "visTypeVislib.horizontalBar.horizontalBarDescription": "連続変数を各軸に割り当てる。", + "visTypeVislib.horizontalBar.horizontalBarTitle": "横棒", + "visTypeVislib.horizontalBar.metricTitle": "Y 軸", + "visTypeVislib.horizontalBar.radiusTitle": "点のサイズ", + "visTypeVislib.horizontalBar.segmentTitle": "X 軸", + "visTypeVislib.horizontalBar.splitTitle": "チャートを分割", + "visTypeVislib.interpolationModes.smoothedText": "スムーズ", + "visTypeVislib.interpolationModes.steppedText": "ステップ", + "visTypeVislib.interpolationModes.straightText": "直線", + "visTypeVislib.legendPositions.bottomText": "一番下", + "visTypeVislib.legendPositions.leftText": "左", + "visTypeVislib.legendPositions.rightText": "右", + "visTypeVislib.legendPositions.topText": "一番上", + "visTypeVislib.line.groupTitle": "系列を分割", + "visTypeVislib.line.lineDescription": "トレンドを強調します。", + "visTypeVislib.line.lineTitle": "折れ線", + "visTypeVislib.line.metricTitle": "Y 軸", + "visTypeVislib.line.radiusTitle": "点のサイズ", + "visTypeVislib.line.segmentTitle": "X 軸", + "visTypeVislib.line.splitTitle": "チャートを分割", + "visTypeVislib.pie.metricTitle": "サイズのスライス", + "visTypeVislib.pie.pieDescription": "全体に対する内訳を表現する。", + "visTypeVislib.pie.pieTitle": "パイ", + "visTypeVislib.pie.segmentTitle": "スライスの分割", + "visTypeVislib.pie.splitTitle": "チャートを分割", + "visTypeVislib.scaleTypes.linearText": "直線", + "visTypeVislib.scaleTypes.logText": "ログ", + "visTypeVislib.scaleTypes.squareRootText": "平方根", + "visTypeVislib.thresholdLine.style.dashedText": "鎖線", + "visTypeVislib.thresholdLine.style.dotdashedText": "点線", + "visTypeVislib.thresholdLine.style.fullText": "完全", + "visTypeVislib.vislib.tooltip.fieldLabel": "フィールド", + "visTypeVislib.vislib.tooltip.valueLabel": "値", + "visTypeVislib.vislib.legend.filterForValueButtonAriaLabel": "値 {legendDataLabel} でフィルタリング", + "visTypeVislib.vislib.legend.filterOutValueButtonAriaLabel": "値 {legendDataLabel} を除外", + "visTypeVislib.vislib.legend.loadingLabel": "読み込み中…", + "visTypeVislib.vislib.legend.setColorScreenReaderDescription": "値 {legendDataLabel} の色を設定", + "visTypeVislib.vislib.legend.toggleLegendButtonAriaLabel": "凡例を切り替える", + "visTypeVislib.vislib.legend.toggleLegendButtonTitle": "凡例を切り替える", + "visTypeVislib.vislib.legend.toggleOptionsButtonAriaLabel": "{legendDataLabel}、トグルオプション", "kibana-react.exitFullScreenButton.exitFullScreenModeButtonLabel": "全画面を終了", "kibana-react.exitFullScreenButton.fullScreenModeDescription": "ESC キーで全画面モードを終了します。", "kibana-react.savedObjects.finder.filterButtonLabel": "タイプ", @@ -4137,6 +4027,112 @@ "xpack.apm.transactionsTable.notFoundLabel": "トランザクションが見つかりませんでした。", "xpack.apm.transactionsTable.transactionsPerMinuteColumnLabel": "1 分あたりのトランザクション", "xpack.apm.transactionsTable.transactionsPerMinuteUnitLabel": "1分あたりトランザクション数", + "xpack.apm.tutorial.apmAgents.statusCheck.btnLabel": "エージェントステータスを確認", + "xpack.apm.tutorial.apmAgents.statusCheck.errorMessage": "エージェントからまだデータを受け取っていません", + "xpack.apm.tutorial.apmAgents.statusCheck.successMessage": "1 つまたは複数のエージェントからデータを受け取りました", + "xpack.apm.tutorial.apmAgents.statusCheck.text": "アプリケーションが実行されていてエージェントがデータを送信していることを確認してください。", + "xpack.apm.tutorial.apmAgents.statusCheck.title": "エージェントステータス", + "xpack.apm.tutorial.apmAgents.title": "APM エージェント", + "xpack.apm.tutorial.apmServer.statusCheck.btnLabel": "APM Server ステータスを確認", + "xpack.apm.tutorial.apmServer.statusCheck.errorMessage": "APM Server がまだ Elasticsearch に接続されていません", + "xpack.apm.tutorial.apmServer.statusCheck.successMessage": "APM Server が正常にセットアップされました", + "xpack.apm.tutorial.apmServer.statusCheck.text": "APM エージェントの導入を開始する前に、APM Server が実行されていることを確認してください。", + "xpack.apm.tutorial.apmServer.statusCheck.title": "APM Server ステータス", + "xpack.apm.tutorial.apmServer.title": "APM Server", + "xpack.apm.tutorial.djangoClient.configure.commands.addAgentComment": "インストールされたアプリにエージェントを追加します", + "xpack.apm.tutorial.djangoClient.configure.commands.addTracingMiddlewareComment": "パフォーマンスメトリックを送信するには、追跡ミドルウェアを追加します:", + "xpack.apm.tutorial.djangoClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_、スペース", + "xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", + "xpack.apm.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment": "必要なサーバー名を設定します。使用できる文字:", + "xpack.apm.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", + "xpack.apm.tutorial.djangoClient.configure.textPost": "高度な用途に関しては [ドキュメンテーション]({documentationLink}) を参照してください。", + "xpack.apm.tutorial.djangoClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「SERVICE_NAME」に基づきプログラムに従って作成されます。", + "xpack.apm.tutorial.djangoClient.configure.title": "エージェントの構成", + "xpack.apm.tutorial.djangoClient.install.textPre": "Python 用の APM エージェントを依存関係としてインストールします。", + "xpack.apm.tutorial.djangoClient.install.title": "APM エージェントのインストール", + "xpack.apm.tutorial.dotNetClient.configureAgent.textPost": "エージェントに「IConfiguration」インスタンスが渡されていない場合、(例: 非 ASP.NET Core アプリケーションの場合)、エージェントを環境変数で構成することもできます。\n 高度な用途に関しては [ドキュメンテーション]({documentationLink}) を参照してください。", + "xpack.apm.tutorial.dotNetClient.configureAgent.title": "appsettings.json ファイルの例:", + "xpack.apm.tutorial.dotNetClient.configureApplication.textPost": "「IConfiguration」インスタンスを渡すのはオプションで、これにより、エージェントはこの「IConfiguration」インスタンス (例: 「appsettings.json」ファイル) から構成を読み込みます。", + "xpack.apm.tutorial.dotNetClient.configureApplication.textPre": "「Elastic.Apm.NetCoreAll」パッケージの ASP.NET Core の場合、「Startup.cs」ファイル内の「Configure」メソドの「UseElasticApm」メソドを呼び出します。", + "xpack.apm.tutorial.dotNetClient.configureApplication.title": "エージェントをアプリケーションに追加", + "xpack.apm.tutorial.dotNetClient.download.textPre": "[NuGet]({allNuGetPackagesLink}) から .NET アプリケーションにエージェントパッケージを追加してください。用途の異なる複数の NuGet パッケージがあります。\n\nEntity Framework Core の ASP.NET Core アプリケーションの場合は、[Elastic.Apm.NetCoreAll]({netCoreAllApmPackageLink}) パッケージをダウンロードしてください。このパッケージは、自動的にすべてのエージェントコンポーネントをアプリケーションに追加します。\n\n 依存性を最低限に抑えたい場合、ASP.NET Core の監視のみに [Elastic.Apm.AspNetCore]({aspNetCorePackageLink}) パッケージ、または Entity Framework Core の監視のみに [Elastic.Apm.EfCore]({efCorePackageLink}) パッケージを使用することができます。\n\n 手動インストルメンテーションのみにパブリック Agent API を使用する場合は、[Elastic.Apm]({elasticApmPackageLink}) パッケージを使用してください。", + "xpack.apm.tutorial.dotNetClient.download.title": "APM エージェントのダウンロード", + "xpack.apm.tutorial.downloadServer.title": "APM Server をダウンロードして展開します", + "xpack.apm.tutorial.downloadServerRpm": "32 ビットパッケージをお探しですか?[ダウンロードページ]({downloadPageLink}) をご覧ください。", + "xpack.apm.tutorial.downloadServerTitle": "32 ビットパッケージをお探しですか?[ダウンロードページ]({downloadPageLink}) をご覧ください。", + "xpack.apm.tutorial.editConfig.textPre": "Elastic Stack の X-Pack セキュアバージョンをご使用の場合、「apm-server.yml」構成ファイルで認証情報を指定する必要があります。", + "xpack.apm.tutorial.editConfig.title": "構成の変更", + "xpack.apm.tutorial.elasticCloud.textPre": "APM サーバーを有効にするには、[the Elastic Cloud console](https://cloud.elastic.co/deployments?q={cloudId}) に移動し、展開設定で APM を有効にします。有効にした後、このページを更新してください。", + "xpack.apm.tutorial.elasticCloudInstructions.title": "APM エージェント", + "xpack.apm.tutorial.flaskClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_、スペース", + "xpack.apm.tutorial.flaskClient.configure.commands.configureElasticApmComment": "またはアプリケーションの設定で ELASTIC_APM を使用するよう構成します。", + "xpack.apm.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment": "環境変数を使用して初期化します", + "xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", + "xpack.apm.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment": "必要なサーバー名を設定します。使用できる文字:", + "xpack.apm.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", + "xpack.apm.tutorial.flaskClient.configure.textPost": "高度な用途に関しては [ドキュメンテーション]({documentationLink}) を参照してください。", + "xpack.apm.tutorial.flaskClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「SERVICE_NAME」に基づきプログラムに従って作成されます。", + "xpack.apm.tutorial.flaskClient.configure.title": "エージェントの構成", + "xpack.apm.tutorial.flaskClient.install.textPre": "Python 用の APM エージェントを依存関係としてインストールします。", + "xpack.apm.tutorial.flaskClient.install.title": "APM エージェントのインストール", + "xpack.apm.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment": "環境変数を使用して初期化します:", + "xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", + "xpack.apm.tutorial.goClient.configure.commands.setServiceNameComment": "サービス名を設定します。使用できる文字は # a-z、A-Z、0-9、-、_、スペースです。", + "xpack.apm.tutorial.goClient.configure.commands.usedExecutableNameComment": "ELASTIC_APM_SERVICE_NAME が指定されていない場合、実行可能な名前が使用されます。", + "xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", + "xpack.apm.tutorial.goClient.configure.textPost": "高度な構成に関しては [ドキュメンテーション]({documentationLink}) を参照してください。", + "xpack.apm.tutorial.goClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは実行ファイル名または「ELASTIC_APM_SERVICE_NAME」の環境変数に基づきプログラムに従って作成されます。", + "xpack.apm.tutorial.goClient.configure.title": "エージェントの構成", + "xpack.apm.tutorial.goClient.install.textPre": "Go の APM エージェントパッケージをインストールします。", + "xpack.apm.tutorial.goClient.install.title": "APM エージェントのインストール", + "xpack.apm.tutorial.goClient.instrument.textPost": "Go のソースコードのインストルメンテーションの詳細ガイドは、[ドキュメンテーション]({documentationLink}) をご参照ください。", + "xpack.apm.tutorial.goClient.instrument.textPre": "提供されたインストルメンテーションモジュールの 1 つ、またはトレーサー API を直接使用して、Go アプリケーションにインストルメンテーションを設定します。", + "xpack.apm.tutorial.goClient.instrument.title": "アプリケーションのインストルメンテーション", + "xpack.apm.tutorial.introduction": "アプリケーション内から詳細なパフォーマンスメトリックやエラーを集めます。", + "xpack.apm.tutorial.javaClient.download.textPre": "[Maven Central]({mavenCentralLink}) からエージェントジャーをダウンロード。アプリケーションにエージェントを依存関係として追加**しない**でください。", + "xpack.apm.tutorial.javaClient.download.title": "APM エージェントのダウンロード", + "xpack.apm.tutorial.javaClient.startApplication.textPost": "構成オプションと高度な用途に関しては、[ドキュメンテーション]({documentationLink}) をご覧ください。", + "xpack.apm.tutorial.javaClient.startApplication.textPre": "「-javaagent」フラグを追加してエージェントをシステムプロパティで構成します。\n\n * 必要なサービス名を設定します (使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)\n * カスタム APM Server URL を設定します (デフォルト: {customApmServerUrl})\n * アプリケーションのベースパッケージを設定します", + "xpack.apm.tutorial.javaClient.startApplication.title": "javaagent フラグのアプリケーションの起動", + "xpack.apm.tutorial.jsClient.enableRealUserMonitoring.textPre": "[ドキュメンテーション({documentationLink}) をご覧ください。", + "xpack.apm.tutorial.jsClient.enableRealUserMonitoring.title": "APM Server の Real User 監視エージェントを有効にする", + "xpack.apm.tutorial.nodeClient.configure.commands.addThisToTheFileTopComment": "アプリに読み込まれたファイルの一番上にこれを追加します", + "xpack.apm.tutorial.nodeClient.configure.commands.allowedCharactersComment": "使用できる文字は # a-z、A-Z、0-9、-、_、スペースです", + "xpack.apm.tutorial.nodeClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", + "xpack.apm.tutorial.nodeClient.configure.commands.setRequiredServiceNameComment": "package.json からサービス名を上書きします", + "xpack.apm.tutorial.nodeClient.configure.commands.useIfApmRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", + "xpack.apm.tutorial.nodeClient.configure.textPost": "[Babel/ES モジュール]({babelEsModulesLink}) との使用を含む高度な用途に関しては、 [ドキュメンテーション]({documentationLink}) をご覧ください。", + "xpack.apm.tutorial.nodeClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「serviceName」に基づきプログラムに従って作成されます。このエージェントは様々なフレームワークをサポートしていますが、カスタムスタックで使用することもできます。", + "xpack.apm.tutorial.nodeClient.configure.title": "エージェントの構成", + "xpack.apm.tutorial.nodeClient.install.textPre": "Node.js 用の APM エージェントをアプリケーションに依存関係としてインストール。", + "xpack.apm.tutorial.nodeClient.install.title": "APM エージェントのインストール", + "xpack.apm.tutorial.rackClient.configure.commands.optionalComment": "オプション、デフォルトで config/elastic_apm.yml になります", + "xpack.apm.tutorial.rackClient.configure.commands.requiredComment": "必要", + "xpack.apm.tutorial.rackClient.configure.textPre": "Rack または対応フレームワーク (Sinatra など) の場合は、アプリのミドルウェアを含めてエージェントを起動してください。", + "xpack.apm.tutorial.rackClient.configure.title": "エージェントの構成", + "xpack.apm.tutorial.rackClient.createConfig.commands.defaultsToTheNameOfRackAppClassComment": "デフォルトで Rack アプリのクラスになります。", + "xpack.apm.tutorial.rackClient.createConfig.commands.setCustomApmServerComment": "カスタム APM Server URL (デフォルト: {defaultServerUrl})", + "xpack.apm.tutorial.rackClient.createConfig.commands.setServiceNameComment": "サービス名を設定します - 使用できる文字は a-z、A-Z、0-9、-、_、スペースです。", + "xpack.apm.tutorial.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment": "APM Serverにトークンが必要な場合に使います", + "xpack.apm.tutorial.rackClient.createConfig.textPost": "構成オプションと高度な用途に関しては、[ドキュメンテーション]({documentationLink}) をご覧ください。\n\n", + "xpack.apm.tutorial.rackClient.createConfig.textPre": "構成ファイル {configFile} を作成します:", + "xpack.apm.tutorial.rackClient.createConfig.title": "構成ファイルの作成", + "xpack.apm.tutorial.rackClient.install.textPre": "Gemfile にエージェントを追加します", + "xpack.apm.tutorial.rackClient.install.title": "APM エージェントのインストール", + "xpack.apm.tutorial.railsClient.configure.textPost": "構成オプションと高度な用途に関しては、[ドキュメンテーション]({documentationLink}) をご覧ください。\n\n", + "xpack.apm.tutorial.railsClient.configure.textPre": "APM はアプリの起動時に自動的に起動します。構成ファイル {configFile} を作成してエージェントを構成します", + "xpack.apm.tutorial.railsClient.configure.title": "エージェントの構成", + "xpack.apm.tutorial.railsClient.install.textPre": "Gemfile にエージェントを追加します", + "xpack.apm.tutorial.railsClient.install.title": "APM エージェントのインストール", + "xpack.apm.tutorial.specProvider.artifacts.application.label": "APM を起動", + "xpack.apm.tutorial.specProvider.artifacts.dashboards.linkLabel": "APM ダッシュボード", + "xpack.apm.tutorial.specProvider.longDescription": "アプリケーションパフォーマンスモニタリング (APM) は、アプリケーション内から詳細なパフォーマンスメトリックやエラーを集めます。何千ものアプリケーションのパフォーマンスをリアルタイムで監視できます。[詳細]({learnMoreLink})。", + "xpack.apm.tutorial.specProvider.name": "APM", + "xpack.apm.tutorial.specProvider.savedObjectsInstallMsg": "APM UI の機能には APM インデックスパターンが必要なものがあります。", + "xpack.apm.tutorial.startServer.textPre": "サーバーは、Elasticsearch アプリケーションのパフォーマンスメトリックを処理し保存します。", + "xpack.apm.tutorial.startServer.title": "APM Server の起動", + "xpack.apm.tutorial.windowsServerInstructions.textPost": "注:システムでスクリプトの実行が無効な場合、スクリプトを実行するために現在のセッションの実行ポリシーの設定が必要となります。例: {command}。", + "xpack.apm.tutorial.windowsServerInstructions.textPre": "1.[ダウンロードページ]({downloadPageLink}) から APM Server Windows zip ファイルをダウンロードします。\n2.zip ファイルのコンテンツを {zipFileExtractFolder} に解凍します。\n3.「{apmServerDirectory}」ディレクトリの名前を「APM-Server」に変更します。\n4.管理者として PowerShell プロンプトを開きます (PowerShell アイコンを右クリックして「管理者として実行」を選択します)。Windows XP をご使用の場合、PowerShell のダウンロードとインストールが必要な場合があります。\n5.PowerShell プロンプトで次のコマンドを実行し、APM Server を Windows サービスとしてインストールします。", "xpack.apm.waterfall.exceedsMax": "このトレースの項目数は表示されている範囲を超えています", "xpack.beatsManagement.beat.actionSectionTypeLabel": "タイプ: {beatType}。", "xpack.beatsManagement.beat.actionSectionVersionLabel": "バージョン: {beatVersion}", @@ -5275,7 +5271,6 @@ "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyAriaLabel": "この {URL} を使用してスクリプトから、または Watcher で {PDF} を生成することもできます。{URL} をクリップボードにコピーするにはエンターキーを押してください。", "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyButtonLabel": "{POST} {URL} をコピー", "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyDescription": "{POST} {URL} をコピーして {KIBANA} 外または ウォッチャー から生成することもできます。", - "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelDisabledDescription": "PDF へのエクスポートは無効になっています。Chromium ブラウザを使用するにはレポートの構成が必要です。これを {fileName} ファイルに追加します。", "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelGenerateButtonLabel": "{PDF} を生成", "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelGenerateDescription": "ワークパッドのサイズによって、{PDF} の生成には数分かかる場合があります。", "xpack.canvas.workpadHeaderWorkpadExport.shareDownloadJSONTitle": "{JSON} をダウンロード", @@ -5671,7 +5666,6 @@ "xpack.fileUpload.jsonIndexFilePicker.filePickerLabel": "アップロードするファイルを選択", "xpack.fileUpload.jsonIndexFilePicker.fileProcessingError": "ファイル処理エラー: {errorMessage}", "xpack.fileUpload.jsonIndexFilePicker.fileSizeError": "ファイルサイズエラー: {errorMessage}", - "xpack.fileUpload.jsonIndexFilePicker.formatsAccepted": "許可されている形式:.json、.geojson", "xpack.fileUpload.jsonIndexFilePicker.maxSize": "最大サイズ:{maxFileSize}", "xpack.fileUpload.jsonIndexFilePicker.noFileNameError": "ファイル名が指定されていません", "xpack.fileUpload.jsonIndexFilePicker.parsingFile": "{featuresProcessed} 件の機能が解析されました…", @@ -6642,8 +6636,6 @@ "xpack.infra.metricsExplorer.openInTSVB": "ビジュアライザーで開く", "xpack.infra.metricsExplorer.viewNodeDetail": "{name} のメトリックを表示", "xpack.infra.node.ariaLabel": "{nodeName}、クリックしてメニューを開きます", - "xpack.infra.nodeContextMenu.viewLogsName": "ログを表示", - "xpack.infra.nodeContextMenu.viewMetricsName": "メトリックを表示", "xpack.infra.nodeDetails.labels.availabilityZone": "アベイラビリティゾーン", "xpack.infra.nodeDetails.labels.cloudProvider": "クラウドプロバイダー", "xpack.infra.nodeDetails.labels.containerized": "コンテナー化", @@ -8245,7 +8237,6 @@ "xpack.ml.jobsList.startDatafeedModal.cancelButtonLabel": "キャンセル", "xpack.ml.jobsList.startDatafeedModal.continueFromNowLabel": "今から続行", "xpack.ml.jobsList.startDatafeedModal.continueFromSpecifiedTimeLabel": "特定の時刻から続行", - "xpack.ml.jobsList.startDatafeedModal.continueFromStartTimeLabel": "{formattedStartTime} から続行", "xpack.ml.jobsList.startDatafeedModal.createWatchDescription": "データフィードの開始後ウォッチを作成します", "xpack.ml.jobsList.startDatafeedModal.noEndTimeLabel": "終了時刻が指定されていません (リアルタイム検索)", "xpack.ml.jobsList.startDatafeedModal.searchEndTimeTitle": "検索終了時刻", @@ -10499,7 +10490,6 @@ "xpack.searchProfiler.highlightDetails.totalTimeTooltip": "子を除き、このクエリコンポーネントだけに使用された合計時間です", "xpack.searchProfiler.highlightDetails.typeTitle": "タイプ", "xpack.searchProfiler.licenseErrorMessageDescription": "さらに可視化するには有効なライセンス ({licenseTypeList} または {platinumLicenseType}), が必要ですが、クラスターに見つかりませんでした。", - "xpack.searchProfiler.licenseHasExpiredMessage": "検索プロフィールを利用できません。ライセンスが期限切れです。", "xpack.searchProfiler.pageDisplayName": "検索プロファイラー", "xpack.searchProfiler.platinumLicenseTitle": "プラチナ", "xpack.searchProfiler.profileTree.cumulativeTimeTitle": "累積時間:", @@ -10514,8 +10504,6 @@ "xpack.searchProfiler.registryProviderDescription": "Elasticsearch クエリのパフォーマンスを素早く確認します.", "xpack.searchProfiler.registryProviderTitle": "検索プロファイラー", "xpack.searchProfiler.trialLicenseTitle": "トライアル", - "xpack.searchProfiler.unavailableLicenseInformationMessage": "検索プロファイラーを利用できません。現在ライセンス情報が利用できません。", - "xpack.searchProfiler.upgradeLicenseMessage": "現在の {licenseInfo} ライセンスでは検索プロファイラーを利用できません。ライセンスをアップグレードしてください。", "xpack.security.account.breadcrumb": "アカウント管理", "xpack.security.account.changePasswordDescription": "アカウントのパスワードを変更します。", "xpack.security.account.changePasswordForm.cancelButtonLabel": "リセット", @@ -10595,17 +10583,6 @@ "xpack.security.management.apiKeys.table.userFilterLabel": "ユーザー", "xpack.security.management.apiKeys.table.userNameColumnName": "ユーザー", "xpack.security.management.apiKeysTitle": "API キー", - "xpack.security.management.changePasswordForm.cancelButtonLabel": "キャンセル", - "xpack.security.management.changePasswordForm.changePasswordLinkLabel": "パスワードを変更", - "xpack.security.management.changePasswordForm.confirmPasswordLabel": "パスワードの確認", - "xpack.security.management.changePasswordForm.currentPasswordLabel": "現在のパスワード", - "xpack.security.management.changePasswordForm.incorrectPasswordDescription": "入力された現在のパスワードが正しくありません。", - "xpack.security.management.changePasswordForm.newPasswordLabel": "新しいパスワード", - "xpack.security.management.changePasswordForm.passwordDontMatchDescription": "パスワードが一致しません", - "xpack.security.management.changePasswordForm.passwordLabel": "パスワード", - "xpack.security.management.changePasswordForm.passwordLengthDescription": "パスワードは最低 6 文字必要です", - "xpack.security.management.changePasswordForm.saveChangesButtonLabel": "変更を保存", - "xpack.security.management.changePasswordForm.updateAndRestartKibanaDescription": "Kibana ユーザーのパスワードを変更後、kibana.yml ファイルを更新し Kibana を再起動する必要があります。", "xpack.security.management.editRole.cancelButtonLabel": "キャンセル", "xpack.security.management.editRole.changeAllPrivilegesLink": "(すべて変更)", "xpack.security.management.editRole.collapsiblePanel.hideLinkText": "非表示", @@ -10730,10 +10707,6 @@ "xpack.security.management.editRolespacePrivilegeForm.createPrivilegeButton": "スペース権限を作成", "xpack.security.management.editRolespacePrivilegeForm.updateGlobalPrivilegeButton": "グローバル特権を更新", "xpack.security.management.editRolespacePrivilegeForm.updatePrivilegeButton": "スペース権限を更新", - "xpack.security.management.passwordForm.confirmPasswordLabel": "パスワードの確認", - "xpack.security.management.passwordForm.passwordDontMatchDescription": "パスワードが一致しません", - "xpack.security.management.passwordForm.passwordLabel": "パスワード", - "xpack.security.management.passwordForm.passwordLengthDescription": "パスワードは最低 6 文字必要です", "xpack.security.management.roles.actionsColumnName": "アクション", "xpack.security.management.roles.cloneRoleActionName": "{roleName} を複製", "xpack.security.management.roles.confirmDelete.cancelButtonLabel": "キャンセル", @@ -11059,6 +11032,8 @@ "xpack.siem.dataProviders.toggle": "切り替え", "xpack.siem.dataProviders.valueAriaLabel": "値", "xpack.siem.dataProviders.valuePlaceholder": "値", + "xpack.siem.detectionEngine.headerPage.pageBadgeLabel": "ベータ", + "xpack.siem.detectionEngine.headerPage.pageBadgeTooltip": "SIEM は現在ベータ段階です。Kibana repo で問題やバグを報告して、製品の改善にご協力ください。", "xpack.siem.draggables.field.categoryLabel": "カテゴリー", "xpack.siem.draggables.field.fieldLabel": "フィールド", "xpack.siem.draggables.field.typeLabel": "タイプ", @@ -11356,8 +11331,6 @@ "xpack.siem.overview.packetBeatDnsTitle": "Packetbeat DNS", "xpack.siem.overview.packetBeatFlowTitle": "Packetbeatフロー", "xpack.siem.overview.packetbeatTLSTitle": "Packetbeat TLS", - "xpack.siem.overview.pageBadgeLabel": "ベータ", - "xpack.siem.overview.pageBadgeTooltip": "SIEM は現在ベータ段階です。Kibana repo で問題やバグを報告して、製品の改善にご協力ください。", "xpack.siem.overview.pageSubtitle": "Elastic Stackによるセキュリティ情報とイベント管理", "xpack.siem.overview.pageTitle": "SIEM", "xpack.siem.overview.startedText": "セキュリティ情報およびイベント管理(SIEM)へようこそ。はじめに{docs}や{data}をご参照ください。今後の機能に関する情報やチュートリアルは、{siemSolution} ページをお見逃しなく。", @@ -11365,7 +11338,6 @@ "xpack.siem.overview.startedText.docsLinkText": "ドキュメンテーション", "xpack.siem.overview.startedText.siemSolutionLinkText": "SIEM ソリューション", "xpack.siem.overview.startedTitle": "はじめて使う", - "xpack.siem.overview.winlogbeatTitle": "Winlogbeat", "xpack.siem.pages.fourohfour.noContentFoundDescription": "コンテンツがありません", "xpack.siem.paginatedTable.rowsButtonLabel": "ページごとの行数", "xpack.siem.paginatedTable.showingSubtitle": "表示中", @@ -12912,7 +12884,6 @@ "xpack.watcher.deleteSelectedWatchesConfirmModal.deleteButtonLabel": "{numWatchesToDelete, plural, one {ウォッチ} other {# ウォッチ}}を削除 ", "xpack.watcher.deleteSelectedWatchesConfirmModal.descriptionText": "{numWatchesToDelete, plural, one {削除されたウォッチ} other {削除されたウォッチ}}は回復できません", "xpack.watcher.models.actionStatus.actionStatusJsonPropertyMissingBadRequestMessage": "JSON引数には\"{missingProperty}\"プロパティが含まれている必要があります", - "xpack.watcher.models.actionStatus.notDetermineActionStatusBadImplementationMessage": "アクションステータスを把握できませんでした; action = {actionStatusJson}", "xpack.watcher.models.baseAction.selectMessageText": "アクションを実行します。", "xpack.watcher.models.baseAction.simulateButtonLabel": "今すぐこのアクションをシミュレート", "xpack.watcher.models.baseAction.simulateMessage": "アクション {id} のシミュレーションが完了しました", @@ -13174,11 +13145,7 @@ "xpack.watcher.sections.watchList.errorTitle": "ウォッチの読み込み中にエラーが発生しました", "xpack.watcher.sections.watchList.header": "しきい値アラートを作成", "xpack.watcher.sections.watchList.loadingWatchesDescription": "ウォッチの読み込み中...", - "xpack.watcher.sections.watchList.managementSection.editDisplayName": "編集", - "xpack.watcher.sections.watchList.managementSection.newWatchDisplayName": "新規ウォッチ", - "xpack.watcher.sections.watchList.managementSection.statusDisplayName": "ステータス", "xpack.watcher.sections.watchList.managementSection.watcherDisplayName": "Watcher", - "xpack.watcher.sections.watchList.managementSection.watchesDisplayName": "ウォッチ", "xpack.watcher.sections.watchList.subhead": "特定のパラメーターに到達した際にメール、Slack メッセージ、ログイベントを送信します。", "xpack.watcher.sections.watchList.toggleActivatationErrorNotification.activateDescriptionText": "ウォッチを有効化できませんでした", "xpack.watcher.sections.watchList.toggleActivatationErrorNotification.deactivateDescriptionText": "ウォッチを無効化できませんでした", @@ -13234,4 +13201,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。", "xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。" } -} +} \ No newline at end of file diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index dc72e83ebe3c30..a5b2bafaded884 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -77,8 +77,6 @@ }, "messages": { "common.ui.aggResponse.allDocsTitle": "所有文档", - "common.ui.aggResponse.fieldLabel": "字段", - "common.ui.aggResponse.valueLabel": "值", "common.ui.aggTypes.aggNotValidLabel": "- 聚合无效 -", "common.ui.aggTypes.aggregateWith.noAggsErrorTooltip": "选择的字段没有兼容的聚合。", "common.ui.aggTypes.aggregateWithLabel": "聚合对象", @@ -452,7 +450,6 @@ "common.ui.flotCharts.thuLabel": "周四", "common.ui.flotCharts.tueLabel": "周二", "common.ui.flotCharts.wedLabel": "周三", - "common.ui.management.breadcrumb": "管理", "common.ui.modals.cancelButtonLabel": "取消", "common.ui.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}:{errMessage}", "common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。", @@ -509,13 +506,6 @@ "common.ui.vis.editors.sidebar.tabs.optionsLabel": "选项", "common.ui.vis.kibanaMap.leaflet.fitDataBoundsAriaLabel": "适应数据边界", "common.ui.vis.kibanaMap.zoomWarning": "已达到缩放级别最大数目。要一直放大,请升级到 Elasticsearch 和 Kibana 的 {defaultDistribution}。您可以通过 {ems} 免费使用其他缩放级别。或者,您可以配置自己的地图服务器。请前往 { wms } 或 { configSettings} 以获取详细信息。", - "common.ui.vis.visTypes.legend.filterForValueButtonAriaLabel": "筛留值 {legendDataLabel}", - "common.ui.vis.visTypes.legend.filterOutValueButtonAriaLabel": "筛除值 {legendDataLabel}", - "common.ui.vis.visTypes.legend.loadingLabel": "正在加载……", - "common.ui.vis.visTypes.legend.setColorScreenReaderDescription": "为值 {legendDataLabel} 设置颜色", - "common.ui.vis.visTypes.legend.toggleLegendButtonAriaLabel": "切换图例", - "common.ui.vis.visTypes.legend.toggleLegendButtonTitle": "切换图例", - "common.ui.vis.visTypes.legend.toggleOptionsButtonAriaLabel": "{legendDataLabel}切换选项", "common.ui.vislib.colormaps.bluesText": "蓝色", "common.ui.vislib.colormaps.greensText": "绿色", "common.ui.vislib.colormaps.greenToRedText": "绿到红", @@ -733,7 +723,6 @@ "data.filter.options.pinAllFiltersButtonLabel": "全部固定", "data.filter.options.unpinAllFiltersButtonLabel": "全部取消固定", "data.filter.searchBar.changeAllFiltersTitle": "更改所有筛选", - "data.indexPatterns.fetchFieldErrorTitle": "提取字段时出错", "data.indexPatterns.unableWriteLabel": "无法写入索引模式!请刷新页面以获取此索引模式的最新更改。", "data.indexPatterns.unknownFieldErrorMessage": "indexPattern “{title}” 中的字段 “{name}” 使用未知字段类型。", "data.indexPatterns.unknownFieldHeader": "未知字段类型 {type}", @@ -1113,307 +1102,6 @@ "kbn.advancedSettings.visualization.tileMap.wmsDefaultsTitle": "默认 WMS 属性", "kbn.advancedSettings.visualizeEnableLabsText": "允许用户创建、查看和编辑实验性可视化。如果禁用,\n 仅被视为生产就绪的可视化可供用户使用。", "kbn.advancedSettings.visualizeEnableLabsTitle": "启用实验性可视化", - "kbn.common.tutorials.auditbeat.cloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.auditbeat.premCloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.auditbeat.premInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.auditbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.auditbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.auditbeatCloudInstructions.config.debTitle": "编辑配置", - "kbn.common.tutorials.auditbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.auditbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.auditbeatCloudInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.auditbeatCloudInstructions.config.rpmTitle": "编辑配置", - "kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.auditbeatCloudInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.auditbeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.auditbeatInstructions.config.debTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.auditbeatInstructions.config.debTitle": "编辑配置", - "kbn.common.tutorials.auditbeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.auditbeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.auditbeatInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.auditbeatInstructions.config.rpmTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.auditbeatInstructions.config.rpmTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.auditbeatInstructions.config.rpmTitle": "编辑配置", - "kbn.common.tutorials.auditbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.auditbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.auditbeatInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.auditbeatInstructions.install.debTextPost": "寻找 32 位软件包?请参阅[下载页面]({linkUrl})。", - "kbn.common.tutorials.auditbeatInstructions.install.debTextPre": "首次使用 Auditbeat?请参阅[入门指南]({linkUrl})。", - "kbn.common.tutorials.auditbeatInstructions.install.debTitle": "下载并安装 Auditbeat", - "kbn.common.tutorials.auditbeatInstructions.install.osxTextPre": "首次使用 Auditbeat?请参阅[入门指南]({linkUrl})。", - "kbn.common.tutorials.auditbeatInstructions.install.osxTitle": "下载并安装 Auditbeat", - "kbn.common.tutorials.auditbeatInstructions.install.rpmTextPost": "寻找 32 位软件包?请参阅[下载页面]({linkUrl})。", - "kbn.common.tutorials.auditbeatInstructions.install.rpmTextPre": "首次使用 Auditbeat?请参阅[入门指南]({linkUrl})。", - "kbn.common.tutorials.auditbeatInstructions.install.rpmTitle": "下载并安装 Auditbeat", - "kbn.common.tutorials.auditbeatInstructions.install.windowsTextPost": "在 {auditbeatPath} 文件中修改 {propertyName} 下的设置以指向您的 Elasticsearch 安装。", - "kbn.common.tutorials.auditbeatInstructions.install.windowsTextPre": "首次使用 Auditbeat?请参阅[入门指南]({guideLinkUrl})。\n 1.从[下载]({auditbeatLinkUrl})页面下载 Auditbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 `{directoryName}` 目录重命名为 `Auditbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Auditbeat 安装为 Windows 服务。", - "kbn.common.tutorials.auditbeatInstructions.install.windowsTitle": "下载并安装 Auditbeat", - "kbn.common.tutorials.auditbeatInstructions.start.debTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.auditbeatInstructions.start.debTitle": "启动 Auditbeat", - "kbn.common.tutorials.auditbeatInstructions.start.osxTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.auditbeatInstructions.start.osxTitle": "启动 Auditbeat", - "kbn.common.tutorials.auditbeatInstructions.start.rpmTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.auditbeatInstructions.start.rpmTitle": "启动 Auditbeat", - "kbn.common.tutorials.auditbeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.auditbeatInstructions.start.windowsTitle": "启动 Auditbeat", - "kbn.common.tutorials.auditbeatStatusCheck.buttonLabel": "检查数据", - "kbn.common.tutorials.auditbeatStatusCheck.errorText": "尚未接收到数据", - "kbn.common.tutorials.auditbeatStatusCheck.successText": "已成功接收数据", - "kbn.common.tutorials.auditbeatStatusCheck.text": "确认从 Auditbeat 收到数据", - "kbn.common.tutorials.auditbeatStatusCheck.title": "状态", - "kbn.common.tutorials.filebeat.cloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.filebeat.premCloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.filebeat.premInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.filebeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.filebeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.filebeatCloudInstructions.config.debTitle": "编辑配置", - "kbn.common.tutorials.filebeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.filebeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.filebeatCloudInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.filebeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.filebeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.filebeatCloudInstructions.config.rpmTitle": "编辑配置", - "kbn.common.tutorials.filebeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.filebeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.filebeatCloudInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.filebeatEnableInstructions.debTextPost": "在 `/etc/filebeat/modules.d/{moduleName}.yml` 文件中修改设置。", - "kbn.common.tutorials.filebeatEnableInstructions.debTitle": "启用和配置 {moduleName} 模块", - "kbn.common.tutorials.filebeatEnableInstructions.osxTextPost": "在 `modules.d/{moduleName}.yml` 文件中修改设置。", - "kbn.common.tutorials.filebeatEnableInstructions.osxTextPre": "从安装目录中,运行:", - "kbn.common.tutorials.filebeatEnableInstructions.osxTitle": "启用和配置 {moduleName} 模块", - "kbn.common.tutorials.filebeatEnableInstructions.rpmTextPost": "在 `/etc/filebeat/modules.d/{moduleName}.yml` 文件中修改设置。", - "kbn.common.tutorials.filebeatEnableInstructions.rpmTitle": "启用和配置 {moduleName} 模块", - "kbn.common.tutorials.filebeatEnableInstructions.windowsTextPost": "在 `modules.d/{moduleName}.yml` 文件中修改设置。", - "kbn.common.tutorials.filebeatEnableInstructions.windowsTextPre": "从 {path} 文件夹中,运行:", - "kbn.common.tutorials.filebeatEnableInstructions.windowsTitle": "启用和配置 {moduleName} 模块", - "kbn.common.tutorials.filebeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.filebeatInstructions.config.debTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.filebeatInstructions.config.debTitle": "编辑配置", - "kbn.common.tutorials.filebeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.filebeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.filebeatInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.filebeatInstructions.config.rpmTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.filebeatInstructions.config.rpmTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.filebeatInstructions.config.rpmTitle": "编辑配置", - "kbn.common.tutorials.filebeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.filebeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.filebeatInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.filebeatInstructions.install.debTextPost": "寻找 32 位软件包?请参阅[下载页面]({linkUrl})。", - "kbn.common.tutorials.filebeatInstructions.install.debTextPre": "首次使用 Filebeat?请参阅[入门指南]({linkUrl})。", - "kbn.common.tutorials.filebeatInstructions.install.debTitle": "下载并安装 Filebeat", - "kbn.common.tutorials.filebeatInstructions.install.osxTextPre": "首次使用 Filebeat?请参阅[入门指南]({linkUrl})。", - "kbn.common.tutorials.filebeatInstructions.install.osxTitle": "下载并安装 Filebeat", - "kbn.common.tutorials.filebeatInstructions.install.rpmTextPost": "寻找 32 位软件包?请参阅[下载页面]({linkUrl})。", - "kbn.common.tutorials.filebeatInstructions.install.rpmTextPre": "首次使用 Filebeat?请参阅[入门指南]({linkUrl})。", - "kbn.common.tutorials.filebeatInstructions.install.rpmTitle": "下载并安装 Filebeat", - "kbn.common.tutorials.filebeatInstructions.install.windowsTextPost": "在 {filebeatPath} 文件中修改 {propertyName} 下的设置以指向您的 Elasticsearch 安装。", - "kbn.common.tutorials.filebeatInstructions.install.windowsTextPre": "首次使用 Filebeat?请参阅[入门指南]({guideLinkUrl})。\n 1.从[下载]({filebeatLinkUrl})页面下载 Filebeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 `{directoryName}` 目录重命名为 `Filebeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Filebeat 安装为 Windows 服务。", - "kbn.common.tutorials.filebeatInstructions.install.windowsTitle": "下载并安装 Filebeat", - "kbn.common.tutorials.filebeatInstructions.start.debTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.filebeatInstructions.start.debTitle": "启动 Filebeat", - "kbn.common.tutorials.filebeatInstructions.start.osxTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.filebeatInstructions.start.osxTitle": "启动 Filebeat", - "kbn.common.tutorials.filebeatInstructions.start.rpmTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.filebeatInstructions.start.rpmTitle": "启动 Filebeat", - "kbn.common.tutorials.filebeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.filebeatInstructions.start.windowsTitle": "启动 Filebeat", - "kbn.common.tutorials.filebeatStatusCheck.buttonLabel": "检查数据", - "kbn.common.tutorials.filebeatStatusCheck.errorText": "尚未从此模块收到任何数据", - "kbn.common.tutorials.filebeatStatusCheck.successText": "从此模块成功收到数据", - "kbn.common.tutorials.filebeatStatusCheck.text": "确认已从 Filebeat `{moduleName}` 模块成功收到数据", - "kbn.common.tutorials.filebeatStatusCheck.title": "模块状态", - "kbn.common.tutorials.functionbeat.cloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.functionbeat.premCloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.functionbeat.premInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.functionbeatAWSInstructions.textPost": "其中 `` 和 `` 是您的帐户凭据,`us-east-1` 是所需的地区。", - "kbn.common.tutorials.functionbeatAWSInstructions.textPre": "在环境中设置您的 AWS 帐户凭据:", - "kbn.common.tutorials.functionbeatAWSInstructions.title": "设置 AWS 凭据", - "kbn.common.tutorials.functionbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.functionbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.functionbeatCloudInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.functionbeatCloudInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.functionbeatEnableOnPremInstructions.defaultTextPost": "其中 `` 是要采集的日志组名称,`` 是将用于暂存 Functionbeat 部署的有效 S3 存储桶名称。", - "kbn.common.tutorials.functionbeatEnableOnPremInstructions.defaultTitle": "配置 Cloudwatch 日志组", - "kbn.common.tutorials.functionbeatEnableOnPremInstructionsOSXLinux.textPre": "在 `functionbeat.yml` 文件中修改设置。", - "kbn.common.tutorials.functionbeatEnableOnPremInstructionsWindows.textPre": "在 {path} 文件中修改设置。", - "kbn.common.tutorials.functionbeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.functionbeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.functionbeatInstructions.config.osxTitle": "配置 Elastic 集群", - "kbn.common.tutorials.functionbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.functionbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.functionbeatInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.functionbeatInstructions.deploy.osxTextPre": "这会将 Functionbeat 安装为 Lambda 函数。`setup` 命令检查 Elasticsearch 配置并加载 Kibana 索引模式。通常可省略此命令。", - "kbn.common.tutorials.functionbeatInstructions.deploy.osxTitle": "将 Functionbeat 部署到 AWS Lambda", - "kbn.common.tutorials.functionbeatInstructions.deploy.windowsTextPre": "这会将 Functionbeat 安装为 Lambda 函数。`setup` 命令检查 Elasticsearch 配置并加载 Kibana 索引模式。通常可省略此命令。", - "kbn.common.tutorials.functionbeatInstructions.deploy.windowsTitle": "将 Functionbeat 部署到 AWS Lambda", - "kbn.common.tutorials.functionbeatInstructions.install.linuxTextPre": "首次使用 Functionbeat?请参阅[入门指南]({link})。", - "kbn.common.tutorials.functionbeatInstructions.install.linuxTitle": "下载并安装 Functionbeat", - "kbn.common.tutorials.functionbeatInstructions.install.osxTextPre": "首次使用 Functionbeat?请参阅[入门指南]({link})。", - "kbn.common.tutorials.functionbeatInstructions.install.osxTitle": "下载并安装 Functionbeat", - "kbn.common.tutorials.functionbeatInstructions.install.windowsTextPre": "首次使用 Functionbeat?请参阅[入门指南]({functionbeatLink})。\n 1.从[下载]({elasticLink})页面下载 Functionbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 {directoryName} 目录重命名为 `Functionbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符下,前往 Functionbeat 目录:", - "kbn.common.tutorials.functionbeatInstructions.install.windowsTitle": "下载并安装 Functionbeat", - "kbn.common.tutorials.functionbeatStatusCheck.buttonLabel": "检查数据", - "kbn.common.tutorials.functionbeatStatusCheck.errorText": "尚未从 Functionbeat 收到任何数据", - "kbn.common.tutorials.functionbeatStatusCheck.successText": "从 Functionbeat 成功收到数据", - "kbn.common.tutorials.functionbeatStatusCheck.text": "确认从 Functionbeat 收到数据", - "kbn.common.tutorials.functionbeatStatusCheck.title": "Functionbeat 状态", - "kbn.common.tutorials.heartbeat.cloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.heartbeat.premCloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.heartbeat.premInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.heartbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.heartbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.heartbeatCloudInstructions.config.debTitle": "编辑配置", - "kbn.common.tutorials.heartbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.heartbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.heartbeatCloudInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.heartbeatCloudInstructions.config.rpmTitle": "编辑配置", - "kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.heartbeatCloudInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.debTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.defaultTextPost": "有关如何在 Heartbeat 中配置监测的详细信息,请参阅 [Heartbeat 配置文档]({configureLink})", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.defaultTitle": "编辑配置 - 添加监测", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.osxTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.rpmTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", - "kbn.common.tutorials.heartbeatEnableCloudInstructions.windowsTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.debTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.defaultTextPost": "其中 {hostTemplate} 是受监测 URL。有关如何在 Heartbeat 中配置监测的详细信息,请参阅 [Heartbeat 配置文档]({configureLink})", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.defaultTitle": "编辑配置 - 添加监测", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.osxTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.rpmTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", - "kbn.common.tutorials.heartbeatEnableOnPremInstructions.windowsTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", - "kbn.common.tutorials.heartbeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.heartbeatInstructions.config.debTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.heartbeatInstructions.config.debTitle": "编辑配置", - "kbn.common.tutorials.heartbeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.heartbeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.heartbeatInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.heartbeatInstructions.config.rpmTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.heartbeatInstructions.config.rpmTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.heartbeatInstructions.config.rpmTitle": "编辑配置", - "kbn.common.tutorials.heartbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.heartbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.heartbeatInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.heartbeatInstructions.install.debTextPost": "寻找 32 位软件包?请参阅[下载页面]({link})。", - "kbn.common.tutorials.heartbeatInstructions.install.debTextPre": "首次使用 Heartbeat?请参阅[入门指南]({link})。", - "kbn.common.tutorials.heartbeatInstructions.install.debTitle": "下载并安装 Heartbeat", - "kbn.common.tutorials.heartbeatInstructions.install.osxTextPre": "首次使用 Heartbeat?请参阅[入门指南]({link})。", - "kbn.common.tutorials.heartbeatInstructions.install.osxTitle": "下载并安装 Heartbeat", - "kbn.common.tutorials.heartbeatInstructions.install.rpmTextPre": "首次使用 Heartbeat?请参阅[入门指南]({link})。", - "kbn.common.tutorials.heartbeatInstructions.install.rpmTitle": "下载并安装 Heartbeat", - "kbn.common.tutorials.heartbeatInstructions.install.windowsTextPre": "首次使用 Heartbeat?请参阅[入门指南]({heartbeatLink})。\n 1.从[下载]({elasticLink})页面下载 Heartbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 {directoryName} 目录重命名为 `Heartbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Heartbeat 安装为 Windows 服务。", - "kbn.common.tutorials.heartbeatInstructions.install.windowsTitle": "下载并安装 Heartbeat", - "kbn.common.tutorials.heartbeatInstructions.start.debTextPre": "`setup` 命令加载 Kibana 索引模式。", - "kbn.common.tutorials.heartbeatInstructions.start.debTitle": "启动 Heartbeat", - "kbn.common.tutorials.heartbeatInstructions.start.osxTextPre": "`setup` 命令加载 Kibana 索引模式。", - "kbn.common.tutorials.heartbeatInstructions.start.osxTitle": "启动 Heartbeat", - "kbn.common.tutorials.heartbeatInstructions.start.rpmTextPre": "`setup` 命令加载 Kibana 索引模式。", - "kbn.common.tutorials.heartbeatInstructions.start.rpmTitle": "启动 Heartbeat", - "kbn.common.tutorials.heartbeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 索引模式。", - "kbn.common.tutorials.heartbeatInstructions.start.windowsTitle": "启动 Heartbeat", - "kbn.common.tutorials.heartbeatStatusCheck.buttonLabel": "检查数据", - "kbn.common.tutorials.heartbeatStatusCheck.errorText": "尚未从 Heartbeat 收到任何数据", - "kbn.common.tutorials.heartbeatStatusCheck.successText": "从 Heartbeat 成功收到数据", - "kbn.common.tutorials.heartbeatStatusCheck.text": "确认从 Heartbeat 收到数据", - "kbn.common.tutorials.heartbeatStatusCheck.title": "Heartbeat 状态", - "kbn.common.tutorials.logstashInstructions.install.java.osxTextPre": "按照[此处]({link})的安装说明执行操作。", - "kbn.common.tutorials.logstashInstructions.install.java.osxTitle": "下载并安装 Java Runtime Environment", - "kbn.common.tutorials.logstashInstructions.install.java.windowsTextPre": "按照[此处]({link})的安装说明执行操作。", - "kbn.common.tutorials.logstashInstructions.install.java.windowsTitle": "下载并安装 Java Runtime Environment", - "kbn.common.tutorials.logstashInstructions.install.logstash.osxTextPre": "首次使用 Logstash? 请参阅[入门指南]({link})。", - "kbn.common.tutorials.logstashInstructions.install.logstash.osxTitle": "下载并安装 Logstash", - "kbn.common.tutorials.logstashInstructions.install.logstash.windowsTextPre": "首次使用 Logstash? 请参阅[入门指南]({logstashLink})。\n 1. [下载]({elasticLink}) Logstash Windows zip 文件。\n 2.解压缩 zip 文件的内容。", - "kbn.common.tutorials.logstashInstructions.install.logstash.windowsTitle": "下载并安装 Logstash", - "kbn.common.tutorials.metricbeat.cloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.metricbeat.premCloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.metricbeat.premInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.metricbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.metricbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.metricbeatCloudInstructions.config.debTitle": "编辑配置", - "kbn.common.tutorials.metricbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.metricbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.metricbeatCloudInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.metricbeatCloudInstructions.config.rpmTitle": "编辑配置", - "kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.metricbeatCloudInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.metricbeatEnableInstructions.debTextPost": "在 `/etc/metricbeat/modules.d/{moduleName}.yml` 文件中修改设置。", - "kbn.common.tutorials.metricbeatEnableInstructions.debTitle": "启用和配置 {moduleName} 模块", - "kbn.common.tutorials.metricbeatEnableInstructions.osxTextPost": "在 `modules.d/{moduleName}.yml` 文件中修改设置。", - "kbn.common.tutorials.metricbeatEnableInstructions.osxTextPre": "从安装目录中,运行:", - "kbn.common.tutorials.metricbeatEnableInstructions.osxTitle": "启用和配置 {moduleName} 模块", - "kbn.common.tutorials.metricbeatEnableInstructions.rpmTextPost": "在 `/etc/metricbeat/modules.d/{moduleName}.yml` 文件中修改设置。", - "kbn.common.tutorials.metricbeatEnableInstructions.rpmTitle": "启用和配置 {moduleName} 模块", - "kbn.common.tutorials.metricbeatEnableInstructions.windowsTextPost": "在 `modules.d/{moduleName}.yml` 文件中修改设置。", - "kbn.common.tutorials.metricbeatEnableInstructions.windowsTextPre": "从 {path} 文件夹中,运行:", - "kbn.common.tutorials.metricbeatEnableInstructions.windowsTitle": "启用和配置 {moduleName} 模块", - "kbn.common.tutorials.metricbeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.metricbeatInstructions.config.debTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.metricbeatInstructions.config.debTitle": "编辑配置", - "kbn.common.tutorials.metricbeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.metricbeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.metricbeatInstructions.config.osxTitle": "编辑配置", - "kbn.common.tutorials.metricbeatInstructions.config.rpmTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.metricbeatInstructions.config.rpmTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.metricbeatInstructions.config.rpmTitle": "编辑配置", - "kbn.common.tutorials.metricbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.metricbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.metricbeatInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.metricbeatInstructions.install.debTextPost": "寻找 32 位软件包?请参阅[下载页面]({link})。", - "kbn.common.tutorials.metricbeatInstructions.install.debTextPre": "首次使用 Metricbeat?请参阅[入门指南]({link})。", - "kbn.common.tutorials.metricbeatInstructions.install.debTitle": "下载并安装 Metricbeat", - "kbn.common.tutorials.metricbeatInstructions.install.osxTextPre": "首次使用 Metricbeat?请参阅[入门指南]({link})。", - "kbn.common.tutorials.metricbeatInstructions.install.osxTitle": "下载并安装 Metricbeat", - "kbn.common.tutorials.metricbeatInstructions.install.rpmTextPre": "首次使用 Metricbeat?请参阅[入门指南]({link})。", - "kbn.common.tutorials.metricbeatInstructions.install.rpmTitle": "下载并安装 Metricbeat", - "kbn.common.tutorials.metricbeatInstructions.install.windowsTextPost": "在 {path} 文件中修改 `output.elasticsearch` 下的设置以指向您的 Elasticsearch 安装。", - "kbn.common.tutorials.metricbeatInstructions.install.windowsTextPre": "首次使用 Metricbeat?请参阅[入门指南]({metricbeatLink})。\n 1.从[下载]({elasticLink})页面下载 Metricbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 {directoryName} 目录重命名为 `Metricbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Metricbeat 安装为 Windows 服务。", - "kbn.common.tutorials.metricbeatInstructions.install.windowsTitle": "下载并安装 Metricbeat", - "kbn.common.tutorials.metricbeatInstructions.start.debTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.metricbeatInstructions.start.debTitle": "启动 Metricbeat", - "kbn.common.tutorials.metricbeatInstructions.start.osxTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.metricbeatInstructions.start.osxTitle": "启动 Metricbeat", - "kbn.common.tutorials.metricbeatInstructions.start.rpmTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.metricbeatInstructions.start.rpmTitle": "启动 Metricbeat", - "kbn.common.tutorials.metricbeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.metricbeatInstructions.start.windowsTitle": "启动 Metricbeat", - "kbn.common.tutorials.metricbeatStatusCheck.buttonLabel": "检查数据", - "kbn.common.tutorials.metricbeatStatusCheck.errorText": "尚未从此模块收到任何数据", - "kbn.common.tutorials.metricbeatStatusCheck.successText": "从此模块成功收到数据", - "kbn.common.tutorials.metricbeatStatusCheck.text": "确认从 Metricbeat `{moduleName}` 模块收到数据", - "kbn.common.tutorials.metricbeatStatusCheck.title": "模块状态", - "kbn.common.tutorials.premCloudInstructions.option1.textPre": "前往 [Elastic Cloud]({link})。如果您还没有帐户,请注册。免费试用 14 天。\n\n登录至 Elastic Cloud 控制台\n\n如要创建集群,请在 Elastic Cloud 控制台中:\n 1.选择**创建部署**,然后指定**部署名称**\n 2.根据需要修改其他部署选项(或者不修改,默认值可帮助您快速入门)\n 3.单击**创建部署**\n 4.等候部署创建完成\n 5.前往新的 Cloud Kibana 实例,然后按照 Kibana 主页上的说明执行操作", - "kbn.common.tutorials.premCloudInstructions.option1.title": "选项 1:在 Elastic Cloud 中尝试", - "kbn.common.tutorials.premCloudInstructions.option2.textPre": "如果基于托管式 Elasticsearch 实例运行此 Kibana 实例,请继续手动设置。\n\n针对您的记录,分别将 **Elasticsearch** 终端节点另存为 {urlTemplate}将集群**密码**另存为 {passwordTemplate}", - "kbn.common.tutorials.premCloudInstructions.option2.title": "选项 2:将本地 Kibana 连接到 Cloud 实例", - "kbn.common.tutorials.winlogbeat.cloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.winlogbeat.premCloudInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.winlogbeat.premInstructions.gettingStarted.title": "入门", - "kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", - "kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", - "kbn.common.tutorials.winlogbeatCloudInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.winlogbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", - "kbn.common.tutorials.winlogbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", - "kbn.common.tutorials.winlogbeatInstructions.config.windowsTitle": "编辑配置", - "kbn.common.tutorials.winlogbeatInstructions.install.windowsTextPost": "在 {path} 文件中修改 `output.elasticsearch` 下的设置以指向您的 Elasticsearch 安装。", - "kbn.common.tutorials.winlogbeatInstructions.install.windowsTextPre": "首次使用 Winlogbeat?请参阅[入门指南]({winlogbeatLink})。\n 1.从[下载]({elasticLink})页面下载 Winlogbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 {directoryName} 目录重命名为 `Winlogbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Winlogbeat 安装为 Windows 服务。", - "kbn.common.tutorials.winlogbeatInstructions.install.windowsTitle": "下载并安装 Winlogbeat", - "kbn.common.tutorials.winlogbeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", - "kbn.common.tutorials.winlogbeatInstructions.start.windowsTitle": "启动 Winlogbeat", - "kbn.common.tutorials.winlogbeatStatusCheck.buttonLabel": "检查数据", - "kbn.common.tutorials.winlogbeatStatusCheck.errorText": "尚未接收到数据", - "kbn.common.tutorials.winlogbeatStatusCheck.successText": "已成功接收数据", - "kbn.common.tutorials.winlogbeatStatusCheck.text": "确认从 Winlogbeat 收到数据", - "kbn.common.tutorials.winlogbeatStatusCheck.title": "模块状态", "kbn.context.breadcrumb": "{indexPatternTitle}#{docId} 的上下文", "kbn.context.failedToLoadAnchorDocumentDescription": "无法加载该定位点文档", "kbn.context.failedToLoadAnchorDocumentErrorDescription": "无法加载定位点文档。", @@ -1896,8 +1584,6 @@ "kbn.management.landing.header": "Kibana {version} 管理", "kbn.management.landing.subhead": "管理您的索引、索引模式、已保存对象、Kibana 设置等等。", "kbn.management.landing.text": "在左侧菜单中可找到完整工具列表", - "kbn.management.managementDescription": "您用于管理 Elastic Stack 的中心控制台。", - "kbn.management.managementLabel": "管理", "kbn.management.objects.confirmModalOptions.deleteButtonLabel": "删除", "kbn.management.objects.confirmModalOptions.modalDescription": "您无法恢复删除的对象", "kbn.management.objects.confirmModalOptions.modalTitle": "删除已保存 Kibana 对象?", @@ -2062,366 +1748,6 @@ "kbn.management.settings.searchBarAriaLabel": "搜索高级设置", "kbn.management.settings.sectionLabel": "高级设置", "kbn.managementTitle": "管理", - "kbn.server.tutorials.aerospikeMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.aerospikeMetrics.longDescription": "Metricbeat 模块 `aerospike` 从 Aerospike 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.aerospikeMetrics.nameTitle": "Aerospike 指标", - "kbn.server.tutorials.aerospikeMetrics.shortDescription": "从 Aerospike 服务器提取内部指标。", - "kbn.server.tutorials.apacheLogs.artifacts.dashboards.linkLabel": "Apache 日志仪表板", - "kbn.server.tutorials.apacheLogs.longDescription": "Filebeat 模块 apache 解析 Apache HTTP 服务器创建的访问和错误日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.apacheLogs.nameTitle": "Apache 日志", - "kbn.server.tutorials.apacheLogs.shortDescription": "收集并解析 Apache HTTP 服务器创建的访问和错误日志。", - "kbn.server.tutorials.apacheMetrics.artifacts.dashboards.linkLabel": "Apache 指标仪表板", - "kbn.server.tutorials.apacheMetrics.longDescription": "Metricbeat 模块 `apache` 从 Apache 2 HTTP 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.apacheMetrics.nameTitle": "Apache 指标", - "kbn.server.tutorials.apacheMetrics.shortDescription": "从 Apache 2 HTTP 服务器提取内部指标。", - "kbn.server.tutorials.apm.apmAgents.statusCheck.btnLabel": "检查代理状态", - "kbn.server.tutorials.apm.apmAgents.statusCheck.errorMessage": "尚未从代理收到任何数据", - "kbn.server.tutorials.apm.apmAgents.statusCheck.successMessage": "从一个或多个代理成功接收数据", - "kbn.server.tutorials.apm.apmAgents.statusCheck.text": "确保您的应用程序正在运行且代理正在发送数据。", - "kbn.server.tutorials.apm.apmAgents.statusCheck.title": "代理状态", - "kbn.server.tutorials.apm.apmAgents.title": "APM 代理", - "kbn.server.tutorials.apm.apmServer.statusCheck.btnLabel": "检查 APM Server 状态", - "kbn.server.tutorials.apm.apmServer.statusCheck.errorMessage": "APM Server 仍未连接到 Elasticsearch", - "kbn.server.tutorials.apm.apmServer.statusCheck.successMessage": "您已正确设置 APM Server", - "kbn.server.tutorials.apm.apmServer.statusCheck.text": "在开始实施 APM 代理之前,确保 APM Server 正在运行。", - "kbn.server.tutorials.apm.apmServer.statusCheck.title": "APM Server 状态", - "kbn.server.tutorials.apm.apmServer.title": "APM Server", - "kbn.server.tutorials.apm.djangoClient.configure.commands.addAgentComment": "向已安装应用添加代理", - "kbn.server.tutorials.apm.djangoClient.configure.commands.addTracingMiddlewareComment": "要发送性能指标,请添加我们的跟踪中间件:", - "kbn.server.tutorials.apm.djangoClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_ 以及空格", - "kbn.server.tutorials.apm.djangoClient.configure.commands.setCustomApmServerUrlComment": "设置定制 APM Server URL(默认值:{defaultApmServerUrl})", - "kbn.server.tutorials.apm.djangoClient.configure.commands.setRequiredServiceNameComment": "设置所需的服务名称。允许使用的字符:", - "kbn.server.tutorials.apm.djangoClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server 需要令牌时使用", - "kbn.server.tutorials.apm.djangoClient.configure.textPost": "有关高级用法,请参阅[文档]({documentationLink})。", - "kbn.server.tutorials.apm.djangoClient.configure.textPre": "代理是在您的应用程序进程内运行的库。APM 服务是基于 `SERVICE_NAME` 以编程方式创建的。", - "kbn.server.tutorials.apm.djangoClient.configure.title": "配置代理", - "kbn.server.tutorials.apm.djangoClient.install.textPre": "将 Python 的 APM 代理安装为依赖项。", - "kbn.server.tutorials.apm.djangoClient.install.title": "安装 APM 代理", - "kbn.server.tutorials.apm.dotNetClient.configureAgent.textPost": "如果您未将 `IConfiguration` 实例传递给代理(例如非 ASP.NET Core 应用程序), 您还可以通过环境变量配置代理。\n 有关高级用法,请参阅[文档]({documentationLink})。", - "kbn.server.tutorials.apm.dotNetClient.configureAgent.title": "样例 appsettings.json 文件:", - "kbn.server.tutorials.apm.dotNetClient.configureApplication.textPost": "传递 `IConfiguration` 实例为可选操作,通过此操作,代理将通过此`IConfiguration` 实例 读取配置设置(例如,从 `appsettings.json` 文件)。", - "kbn.server.tutorials.apm.dotNetClient.configureApplication.textPre": "对于具有 `Elastic.Apm.NetCoreAll` 软件包的 ASP.NET Core,请在 `Startup.cs` 文件内的 `Configure` 方法中调用 `UseAllElasticApm`。", - "kbn.server.tutorials.apm.dotNetClient.configureApplication.title": "将代理添加到应用程序", - "kbn.server.tutorials.apm.dotNetClient.download.textPre": "将代理软件包从 [NuGet]({allNuGetPackagesLink}) 添加到 .NET 应用程序。有多个 NuGet 软件包可用于不同的用例。\n\n对于具有 Entity Framework Core 的 ASP.NET Core 应用程序,请下载 [Elastic.Apm.NetCoreAll]({netCoreAllApmPackageLink}) 软件包。此软件包将自动将每个 代理组件添加到您的应用程序。\n\n 如果您希望最大程度减少依存关系,您可以将 [Elastic.Apm.AspNetCore]({aspNetCorePackageLink}) 软件包仅用于 ASP.NET Core 监测,或将 [Elastic.Apm.EfCore]({efCorePackageLink}) 软件包仅用于 Entity Framework Core 监测。\n\n 如果仅希望将公共代理 API 用于手动检测,请使用 [Elastic.Apm]({elasticApmPackageLink}) 软件包。", - "kbn.server.tutorials.apm.dotNetClient.download.title": "下载 APM 代理", - "kbn.server.tutorials.apm.downloadServer.title": "下载并解压缩 APM Server", - "kbn.server.tutorials.apm.downloadServerRpm": "寻找 32 位软件包?请参阅[下载页面]({downloadPageLink})。", - "kbn.server.tutorials.apm.downloadServerTitle": "寻找 32 位软件包?请参阅[下载页面]({downloadPageLink})。", - "kbn.server.tutorials.apm.editConfig.textPre": "如果您正在使用 Elastic Stack 的 X-Pack 安全版本,则必须在 `apm-server.yml` 配置文件中指定凭据。", - "kbn.server.tutorials.apm.editConfig.title": "编辑配置", - "kbn.server.tutorials.apm.elasticCloud.textPre": "要启用 APM Server,请前往 [Elastic Cloud 控制台](https://cloud.elastic.co/deployments?q={cloudId}) 并在部署设置中启用 APM。启用后,请刷新此页面。", - "kbn.server.tutorials.apm.elasticCloudInstructions.title": "APM 代理", - "kbn.server.tutorials.apm.flaskClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_ 以及空格", - "kbn.server.tutorials.apm.flaskClient.configure.commands.configureElasticApmComment": "或进行配置以在您的应用程序设置中使用 ELASTIC_APM", - "kbn.server.tutorials.apm.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment": "使用环境变量初始化", - "kbn.server.tutorials.apm.flaskClient.configure.commands.setCustomApmServerUrlComment": "设置定制 APM Server URL(默认值:{defaultApmServerUrl})", - "kbn.server.tutorials.apm.flaskClient.configure.commands.setRequiredServiceNameComment": "设置所需的服务名称。允许使用的字符:", - "kbn.server.tutorials.apm.flaskClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server 需要令牌时使用", - "kbn.server.tutorials.apm.flaskClient.configure.textPost": "有关高级用法,请参阅[文档]({documentationLink})。", - "kbn.server.tutorials.apm.flaskClient.configure.textPre": "代理是在您的应用程序进程内运行的库。APM 服务是基于 `SERVICE_NAME` 以编程方式创建的。", - "kbn.server.tutorials.apm.flaskClient.configure.title": "配置代理", - "kbn.server.tutorials.apm.flaskClient.install.textPre": "将 Python 的 APM 代理安装为依赖项。", - "kbn.server.tutorials.apm.flaskClient.install.title": "安装 APM 代理", - "kbn.server.tutorials.apm.goClient.configure.commands.initializeUsingEnvironmentVariablesComment": "使用环境变量初始化:", - "kbn.server.tutorials.apm.goClient.configure.commands.setCustomApmServerUrlComment": "设置定制 APM Server URL(默认值:{defaultApmServerUrl})", - "kbn.server.tutorials.apm.goClient.configure.commands.setServiceNameComment": "设置服务名称。允许使用的字符:# a-z、A-Z、0-9、-、_ 和空格。", - "kbn.server.tutorials.apm.goClient.configure.commands.usedExecutableNameComment": "如果未指定 ELASTIC_APM_SERVICE_NAME,将会使用可执行文件名称。", - "kbn.server.tutorials.apm.goClient.configure.commands.useIfApmRequiresTokenComment": "APM Server 需要令牌时使用", - "kbn.server.tutorials.apm.goClient.configure.textPost": "有关高级配置,请参阅[文档]({documentationLink})。", - "kbn.server.tutorials.apm.goClient.configure.textPre": "代理是在您的应用程序进程内运行的库。APM 服务将基于可执行文件名称或 `ELASTIC_APM_SERVICE_NAME` 环境变量以编程方式进行创建。", - "kbn.server.tutorials.apm.goClient.configure.title": "配置代理", - "kbn.server.tutorials.apm.goClient.install.textPre": "安装 Go 的 APM 代理软件包。", - "kbn.server.tutorials.apm.goClient.install.title": "安装 APM 代理", - "kbn.server.tutorials.apm.goClient.instrument.textPost": "有关检测 Go 源代码的详细指南,请参阅[文档]({documentationLink})。", - "kbn.server.tutorials.apm.goClient.instrument.textPre": "使用以下已提供检测模块之一或直接使用跟踪器 API 来检测 Go 应用程序。", - "kbn.server.tutorials.apm.goClient.instrument.title": "检测您的应用程序", - "kbn.server.tutorials.apm.introduction": "从您的应用程序内收集深入全面的性能指标和错误。", - "kbn.server.tutorials.apm.javaClient.download.textPre": "从 [Maven Central]({mavenCentralLink}) 下载代理 jar。**切勿**将该代理添加为您的应用程序的依赖项。", - "kbn.server.tutorials.apm.javaClient.download.title": "下载 APM 代理", - "kbn.server.tutorials.apm.javaClient.startApplication.textPost": "有关配置选项和高级用法,请参阅[文档]({documentationLink})。", - "kbn.server.tutorials.apm.javaClient.startApplication.textPre": "添加 `-javaagent` 标志并使用系统属性配置代理。\n\n * 设置所需的服务名称(允许使用的字符:a-z、A-Z、0-9、-、_ 和空格)\n * 设置定制 APM Server URL(默认值:{customApmServerUrl})\n * 设置您的应用程序的基础软件包", - "kbn.server.tutorials.apm.javaClient.startApplication.title": "使用 javaagent 标志设置您的应用程序", - "kbn.server.tutorials.apm.jsClient.enableRealUserMonitoring.textPre": "请参阅[文档]({documentationLink})。", - "kbn.server.tutorials.apm.jsClient.enableRealUserMonitoring.title": "在 APM 服务器中启用真实用户 Monitoring 支持", - "kbn.server.tutorials.apm.nodeClient.configure.commands.addThisToTheFileTopComment": "将其添加到您的应用中加载的第一个文件的上面", - "kbn.server.tutorials.apm.nodeClient.configure.commands.allowedCharactersComment": "允许使用的字符:a-z、A-Z、0-9、-、_ 和空格", - "kbn.server.tutorials.apm.nodeClient.configure.commands.setCustomApmServerUrlComment": "设置定制 APM Server URL(默认值:{defaultApmServerUrl})", - "kbn.server.tutorials.apm.nodeClient.configure.commands.setRequiredServiceNameComment": "覆盖来自 package.json 的服务名", - "kbn.server.tutorials.apm.nodeClient.configure.commands.useIfApmRequiresTokenComment": "APM Server 需要令牌时使用", - "kbn.server.tutorials.apm.nodeClient.configure.textPost": "请参阅[文档]({documentationLink})以了解高级用法,包括如何使用 [Babel/ES 模块]({babelEsModulesLink})。", - "kbn.server.tutorials.apm.nodeClient.configure.textPre": "代理是在您的应用程序进程内运行的库。APM 服务是基于 `serviceName` 以编程方式创建的。此代理支持各种框架,而且还可以与您的定制堆栈配合使用。", - "kbn.server.tutorials.apm.nodeClient.configure.title": "配置代理", - "kbn.server.tutorials.apm.nodeClient.install.textPre": "将 Node.js 的 APM 代理安装为您的应用程序的依赖项。", - "kbn.server.tutorials.apm.nodeClient.install.title": "安装 APM 代理", - "kbn.server.tutorials.apm.rackClient.configure.commands.optionalComment": "可选,默认为 config/elastic_apm.yml", - "kbn.server.tutorials.apm.rackClient.configure.commands.requiredComment": "必填", - "kbn.server.tutorials.apm.rackClient.configure.textPre": "对于 Rack 或兼容的框架(例如 Sinatra),在您的应用中加入中间件,然后启动代理。", - "kbn.server.tutorials.apm.rackClient.configure.title": "配置代理", - "kbn.server.tutorials.apm.rackClient.createConfig.commands.defaultsToTheNameOfRackAppClassComment": "默认为 Rack 应用的类名称。", - "kbn.server.tutorials.apm.rackClient.createConfig.commands.setCustomApmServerComment": "设置定制 APM Server URL(默认值:{defaultServerUrl})", - "kbn.server.tutorials.apm.rackClient.createConfig.commands.setServiceNameComment": "设置服务名称 - 允许使用的字符:a-z、A-Z、0-9、-、_ 和空格", - "kbn.server.tutorials.apm.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment": "APM Server 需要令牌时使用", - "kbn.server.tutorials.apm.rackClient.createConfig.textPost": "有关配置选项和高级用法,请参阅[文档]({documentationLink})。\n\n", - "kbn.server.tutorials.apm.rackClient.createConfig.textPre": "创建配置文件 {configFile}:", - "kbn.server.tutorials.apm.rackClient.createConfig.title": "创建配置文件", - "kbn.server.tutorials.apm.rackClient.install.textPre": "将代理添加您的 Gemfile。", - "kbn.server.tutorials.apm.rackClient.install.title": "安装 APM 代理", - "kbn.server.tutorials.apm.railsClient.configure.textPost": "有关配置选项和高级用法,请参阅[文档]({documentationLink})。\n\n", - "kbn.server.tutorials.apm.railsClient.configure.textPre": "您的应用启动时,APM 自动启动。通过创建配置文件 {configFile} 来配置代理", - "kbn.server.tutorials.apm.railsClient.configure.title": "配置代理", - "kbn.server.tutorials.apm.railsClient.install.textPre": "将代理添加您的 Gemfile。", - "kbn.server.tutorials.apm.railsClient.install.title": "安装 APM 代理", - "kbn.server.tutorials.apm.specProvider.artifacts.application.label": "启动 APM", - "kbn.server.tutorials.apm.specProvider.artifacts.dashboards.linkLabel": "APM 仪表板", - "kbn.server.tutorials.apm.specProvider.longDescription": "应用程序性能 Monitoring (APM) 从您的应用程序内收集深入全面的性能指标和错误。其允许您实时监测数以千计的应用程序的性能。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.apm.specProvider.name": "APM", - "kbn.server.tutorials.apm.specProvider.savedObjectsInstallMsg": "APM UI 中的某些功能需要 APM 索引模式。", - "kbn.server.tutorials.apm.startServer.textPre": "服务器在 Elasticsearch 中处理并存储应用程序性能指标。", - "kbn.server.tutorials.apm.startServer.title": "启动 APM Server", - "kbn.server.tutorials.apm.windowsServerInstructions.textPost": "注意:如果您的系统禁用了脚本执行,则需要为当前会话设置执行策略,以允许脚本运行。例如:{command}。", - "kbn.server.tutorials.apm.windowsServerInstructions.textPre": "1.从[下载页面]({downloadPageLink})下载 APM Server Windows zip 文件。\n2.将 zip 文件的内容解压缩到 {zipFileExtractFolder}。\n3.将 {apmServerDirectory} 目录重命名为 `APM-Server`。\n4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n5.从 PowerShell 提示符处,运行以下命令以将 APM Server 安装为 Windows 服务:", - "kbn.server.tutorials.auditbeat.artifacts.dashboards.linkLabel": "SIEM App", - "kbn.server.tutorials.auditbeat.longDescription": "使用 Auditbeat 从主机收集审计数据。其中包括进程、用户、登录、套接字信息、文件访问等等。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.auditbeat.nameTitle": "Auditbeat", - "kbn.server.tutorials.auditbeat.shortDescription": "从主机收集审计数据。", - "kbn.server.tutorials.awsMetrics.artifacts.dashboards.linkLabel": "AWS 指标仪表板", - "kbn.server.tutorials.awsMetrics.longDescription": "Metricbeat 模块 `aws` 从 AWS API 和 Cloudwatch 提取监测指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.awsMetrics.nameTitle": "AWS 指标", - "kbn.server.tutorials.awsMetrics.shortDescription": "从 AWS API 和 Cloudwatch 提取 EC2 实例的监测指标。", - "kbn.server.tutorials.cephMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.cephMetrics.longDescription": "Metricbeat 模块 `ceph` 从 Ceph 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.cephMetrics.nameTitle": "Ceph 指标", - "kbn.server.tutorials.cephMetrics.shortDescription": "从 Ceph 服务器提取内部指标。", - "kbn.server.tutorials.ciscoLogs.artifacts.dashboards.linkLabel": "SIEM App", - "kbn.server.tutorials.ciscoLogs.longDescription": "这是用于 Cisco 网络设备日志的模块。当前支持“asa”文件集,该文件集用于通过 Syslog 接收或从文件读取的 Cisco ASA 防火墙日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.ciscoLogs.nameTitle": "Cisco", - "kbn.server.tutorials.ciscoLogs.shortDescription": "收集并解析从 Cisco ASA 防火墙接收的日志。", - "kbn.server.tutorials.cloudwatchLogs.longDescription": "通过部署将运行为 AWS Lambda 函数 的 Functionbeat,来收集 Cloudwatch 日志。 [了解详情]({learnMoreLink})。", - "kbn.server.tutorials.cloudwatchLogs.nameTitle": "Cloudwatch 日志", - "kbn.server.tutorials.cloudwatchLogs.shortDescription": "使用 Functionbeat 收集 Cloudwatch 日志", - "kbn.server.tutorials.corednsLogs.artifacts.dashboards.linkLabel": "CoreDNS 日志仪表板", - "kbn.server.tutorials.corednsLogs.longDescription": "`coredns` Filebeat 模块从 [CoreDNS](https://coredns.io/manual/toc/) 收集日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.corednsLogs.nameTitle": "CoreDNS 日志", - "kbn.server.tutorials.corednsLogs.shortDescription": "收集 Coredns 创建的日志。", - "kbn.server.tutorials.corednsMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.corednsMetrics.longDescription": "Metricbeat 模块 `coredns` 从 CoreDNS 提取监测指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.corednsMetrics.nameTitle": "CoreDNS 指标", - "kbn.server.tutorials.corednsMetrics.shortDescription": "从 CoreDNS 服务器提取监测指标。", - "kbn.server.tutorials.couchbaseMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.couchbaseMetrics.longDescription": "Metricbeat 模块 `couchbase` 从 Couchbase 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.couchbaseMetrics.nameTitle": "Couchbase 指标", - "kbn.server.tutorials.couchbaseMetrics.shortDescription": "从 Couchbase 提取内部指标。", - "kbn.server.tutorials.couchdbMetrics.artifacts.dashboards.linkLabel": "CouchDB 指标仪表板", - "kbn.server.tutorials.couchdbMetrics.longDescription": "`couchdb` Metricbeat 模块从 CouchDB 提取监测指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.couchdbMetrics.nameTitle": "CouchDB 指标", - "kbn.server.tutorials.couchdbMetrics.shortDescription": "从 CouchdB 服务器提取监测指标。", - "kbn.server.tutorials.dockerMetrics.artifacts.dashboards.linkLabel": "Docker 指标仪表板", - "kbn.server.tutorials.dockerMetrics.longDescription": "Metricbeat 模块 `docker` 从 Docker 服务器提取指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.dockerMetrics.nameTitle": "Docker 指标", - "kbn.server.tutorials.dockerMetrics.shortDescription": "提取有关 Docker 容器的指标。", - "kbn.server.tutorials.dropwizardMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.dropwizardMetrics.longDescription": "Metricbeat 模块 `dropwizard` 从 Dropwizard Java 应用程序提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.dropwizardMetrics.nameTitle": "Dropwizard 指标", - "kbn.server.tutorials.dropwizardMetrics.shortDescription": "从 Dropwizard Java 应用程序提取内部指标。", - "kbn.server.tutorials.elasticsearchLogs.artifacts.application.label": "Discover", - "kbn.server.tutorials.elasticsearchLogs.longDescription": "Filebeat 模块 `elasticsearch` 解析 Elasticsearch 创建的日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.elasticsearchLogs.nameTitle": "Elasticsearch 日志", - "kbn.server.tutorials.elasticsearchLogs.shortDescription": "收集并解析 Elasticsearch 创建的日志。", - "kbn.server.tutorials.elasticsearchMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.elasticsearchMetrics.longDescription": "Metricbeat 模块 `elasticsearch` 从 Elasticsearch 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.elasticsearchMetrics.nameTitle": "Elasticsearch 指标", - "kbn.server.tutorials.elasticsearchMetrics.shortDescription": "从 Elasticsearch 提取内部指标。", - "kbn.server.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel": "SIEM App", - "kbn.server.tutorials.envoyproxyLogs.longDescription": "这是用于 [Envoy 代理访问日志](https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log)的 Filebeat 模块。其在 Kubernetes 中既支持独立部署,又支持 Envoy 代理部署。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.envoyproxyLogs.nameTitle": "Envoyproxy", - "kbn.server.tutorials.envoyproxyLogs.shortDescription": "收集并解析从 Envoy 代理接收的日志。", - "kbn.server.tutorials.etcdMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.etcdMetrics.longDescription": "Metricbeat 模块 `etcd` 从 Etcd 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.etcdMetrics.nameTitle": "Etcd 指标", - "kbn.server.tutorials.etcdMetrics.shortDescription": "从 Etcd 服务器提取内部指标。", - "kbn.server.tutorials.golangMetrics.artifacts.dashboards.linkLabel": "Golang 指标仪表板", - "kbn.server.tutorials.golangMetrics.longDescription": "Metricbeat 模块 `{moduleName}` 从 Golang 应用提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.golangMetrics.nameTitle": "Golang 指标", - "kbn.server.tutorials.golangMetrics.shortDescription": "从 Golang 应用提取内部指标。", - "kbn.server.tutorials.haproxyMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.haproxyMetrics.longDescription": "Metricbeat 模块 `haproxy` 从 HAProxy 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.haproxyMetrics.nameTitle": "HAProxy 指标", - "kbn.server.tutorials.haproxyMetrics.shortDescription": "从 HAProxy 服务器提取内部指标。", - "kbn.server.tutorials.iisLogs.artifacts.dashboards.linkLabel": "IIS 日志仪表板", - "kbn.server.tutorials.iisLogs.longDescription": "Filebeat 模块 `iis` 解析 IIS HTTP 服务器创建的访问和错误日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.iisLogs.nameTitle": "IIS 日志", - "kbn.server.tutorials.iisLogs.shortDescription": "收集并解析 IIS HTTP 服务器创建的访问和错误日志。", - "kbn.server.tutorials.iptablesLogs.artifacts.dashboards.linkLabel": "SIEM App", - "kbn.server.tutorials.iptablesLogs.longDescription": "这是用于 iptables 和 ip6tables 日志的模块。其解析在网络上通过 Syslog 或从文件中接收的日志。另外,其识别某些 Ubiquiti 防火墙添加的前缀,该前缀包含规则集名称、规则编号和对流量执行的操作(允许/拒绝)。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.iptablesLogs.nameTitle": "Iptables / Ubiquiti", - "kbn.server.tutorials.iptablesLogs.shortDescription": "从 Ubiqiti 防火墙收集并解析 iptables 和 ip6tables 日志。", - "kbn.server.tutorials.kafkaLogs.artifacts.dashboards.linkLabel": "Kafka 日志仪表板", - "kbn.server.tutorials.kafkaLogs.longDescription": "Filebeat 模块 `kafka` 解析 Kafka 创建的日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.kafkaLogs.nameTitle": "Kafka 日志", - "kbn.server.tutorials.kafkaLogs.shortDescription": "收集并解析 Kafka 创建的日志。", - "kbn.server.tutorials.kafkaMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.kafkaMetrics.longDescription": "Metricbeat 模块 `kafka` 从 Kafka 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.kafkaMetrics.nameTitle": "Kafka 指标", - "kbn.server.tutorials.kafkaMetrics.shortDescription": "从 Kafka 服务器提取内部指标。", - "kbn.server.tutorials.kibanaMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.kibanaMetrics.longDescription": "Metricbeat 模块 `kibana` 从 Kibana 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.kibanaMetrics.nameTitle": "Kibana 指标", - "kbn.server.tutorials.kibanaMetrics.shortDescription": "从 Kibana 提取内部指标。", - "kbn.server.tutorials.kubernetesMetrics.artifacts.dashboards.linkLabel": "Kubernetes 指标仪表板", - "kbn.server.tutorials.kubernetesMetrics.longDescription": "Metricbeat 模块 `kubernetes` 从 Kubernetes API 提取指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.kubernetesMetrics.nameTitle": "Kubernetes 指标", - "kbn.server.tutorials.kubernetesMetrics.shortDescription": "从您的 Kubernetes 安装提取指标。", - "kbn.server.tutorials.logstashLogs.artifacts.dashboards.linkLabel": "Logstash 日志仪表板", - "kbn.server.tutorials.logstashLogs.longDescription": "Filebeat 模块 `logstash` 解析 Logstash 创建的调试和慢查询日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.logstashLogs.nameTitle": "Logstash 日志", - "kbn.server.tutorials.logstashLogs.shortDescription": "收集并解析 Logstash 创建的调试和慢查询日志。", - "kbn.server.tutorials.logstashMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.logstashMetrics.longDescription": "Metricbeat 模块 `{moduleName}` 从 Logstash 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.logstashMetrics.nameTitle": "Logstash 指标", - "kbn.server.tutorials.logstashMetrics.shortDescription": "从 Logstash 服务器提取内部指标。", - "kbn.server.tutorials.memcachedMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.memcachedMetrics.longDescription": "Metricbeat 模块 `memcached` 从 Memcached 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.memcachedMetrics.nameTitle": "Memcached 指标", - "kbn.server.tutorials.memcachedMetrics.shortDescription": "从 Memcached 提取内部指标。", - "kbn.server.tutorials.mongodbMetrics.artifacts.dashboards.linkLabel": "MongoDB 指标仪表板", - "kbn.server.tutorials.mongodbMetrics.longDescription": "Metricbeat 模块 `mongodb` 从 MongoDB 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.mongodbMetrics.nameTitle": "MongoDB 指标", - "kbn.server.tutorials.mongodbMetrics.shortDescription": "从 MongoDB 提取内部指标。", - "kbn.server.tutorials.mssqlMetrics.artifacts.dashboards.linkLabel": "Microsoft SQL Server 指标仪表板", - "kbn.server.tutorials.mssqlMetrics.longDescription": "Metricbeat 模块 `mssql` 从 Microsoft SQL Server 提取监测、日志和性能指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.mssqlMetrics.nameTitle": "Microsoft SQL Server 指标", - "kbn.server.tutorials.mssqlMetrics.shortDescription": "从 Microsoft SQL Server 实例提取监测指标", - "kbn.server.tutorials.muninMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.muninMetrics.longDescription": "Metricbeat 模块 `munin` 从 Munin 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.muninMetrics.nameTitle": "Munin 指标", - "kbn.server.tutorials.muninMetrics.shortDescription": "从 Munin 服务器提取内部指标。", - "kbn.server.tutorials.mysqlLogs.artifacts.dashboards.linkLabel": "MySQL 日志仪表板", - "kbn.server.tutorials.mysqlLogs.longDescription": "Filebeat 模块 `mysql` 解析 MySQL 创建的错误和慢查询日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.mysqlLogs.nameTitle": "MySQL 日志", - "kbn.server.tutorials.mysqlLogs.shortDescription": "收集并解析 MySQL 创建的错误和慢查询日志。", - "kbn.server.tutorials.mysqlMetrics.artifacts.dashboards.linkLabel": "MySQL 指标仪表板", - "kbn.server.tutorials.mysqlMetrics.longDescription": "Metricbeat 模块 `mysql` 从 MySQL 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.mysqlMetrics.nameTitle": "MySQL 指标", - "kbn.server.tutorials.mysqlMetrics.shortDescription": "从 MySQL 提取内部指标。", - "kbn.server.tutorials.natsLogs.artifacts.dashboards.linkLabel": "Nats 日志仪表板", - "kbn.server.tutorials.natsLogs.longDescription": "Filebeat 模块 `nats` 解析 Nats 创建的日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.natsLogs.nameTitle": "Nats 日志", - "kbn.server.tutorials.natsLogs.shortDescription": "收集并解析 Nats 创建的日志。", - "kbn.server.tutorials.natsMetrics.artifacts.dashboards.linkLabel": "Nats 指标仪表板", - "kbn.server.tutorials.natsMetrics.longDescription": "Metricbeat 模块 `nats` 从 Nats 提取监测指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.natsMetrics.nameTitle": "Nats 指标", - "kbn.server.tutorials.natsMetrics.shortDescription": "从 Nats 服务器提取监测指标。", - "kbn.server.tutorials.netflow.common.config.elasticCloud.osxTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口,{password} 是 {elastic} 用户的密码。", - "kbn.server.tutorials.netflow.common.config.elasticCloud.osxTextPre": "修改 {logstashConfigPath} 以设置配置参数:", - "kbn.server.tutorials.netflow.common.config.elasticCloud.osxTitle": "编辑配置", - "kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口,{password} 是 {elastic} 用户的密码。", - "kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTextPre": "修改 {logstashConfigPath} 以设置配置参数:", - "kbn.server.tutorials.netflow.common.config.elasticCloud.windowsTitle": "编辑配置", - "kbn.server.tutorials.netflow.common.config.onPrem.osxTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口。", - "kbn.server.tutorials.netflow.common.config.onPrem.osxTextPre": "修改 {logstashConfigPath} 以设置配置参数:", - "kbn.server.tutorials.netflow.common.config.onPrem.osxTitle": "编辑配置", - "kbn.server.tutorials.netflow.common.config.onPrem.windowsTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口。", - "kbn.server.tutorials.netflow.common.config.onPrem.windowsTextPre": "修改 {logstashConfigPath} 以设置配置参数:", - "kbn.server.tutorials.netflow.common.config.onPrem.windowsTitle": "编辑配置", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口,{esUrl} 是在 Elastic Cloud 上运行的 Elasticsearch 的 URL,{password} 是 {elastic} 用户的密码。", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTextPre": "修改 {logstashConfigPath} 以设置配置参数:", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.osxTitle": "编辑配置", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口,{esUrl} 是在 Elastic Cloud 上运行的 Elasticsearch 的 URL,{password} 是 {elastic} 用户的密码。", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPre": "修改 {logstashConfigPath} 以设置配置参数:", - "kbn.server.tutorials.netflow.common.config.onPremElasticCloud.windowsTitle": "编辑配置", - "kbn.server.tutorials.netflow.common.setup.osxTextPost": "“{setupOption}” 选项可在 Elasticsearch 中创建 {netflowPrefix} 索引模式,并导入 Kibana 仪表板和可视化。对随后的运行省略此选项可避免覆盖现有仪表板。", - "kbn.server.tutorials.netflow.common.setup.osxTextPre": "运行:", - "kbn.server.tutorials.netflow.common.setup.osxTitle": "运行 Netflow 模块", - "kbn.server.tutorials.netflow.common.setup.windowsTextPost": "“{setupOption}” 选项可在 Elasticsearch 中创建 {netflowPrefix} 索引模式,并导入 Kibana 仪表板和可视化。对随后的运行省略此选项可避免覆盖现有仪表板。", - "kbn.server.tutorials.netflow.common.setup.windowsTextPre": "运行:", - "kbn.server.tutorials.netflow.common.setup.windowsTitle": "运行 Netflow 模块", - "kbn.server.tutorials.netflow.elasticCloudInstructions.title": "入门", - "kbn.server.tutorials.netflow.onPremElasticCloudInstructions.title": "入门", - "kbn.server.tutorials.netflow.onPremInstructions.title": "入门", - "kbn.server.tutorials.netflow.tutorialLongDescription": "Logstash Netflow 模块收集并解析网络流量数据,在 Elasticsearch 中索引事件,并安装一套 Kibana 仪表板。此模块支持 Netflow 版本 5 和 9。[了解详情]({linkUrl})。", - "kbn.server.tutorials.netflow.tutorialShortDescription": "收集 Netflow 导出器发送的 Netflow 记录。", - "kbn.server.tutorials.nginxLogs.artifacts.dashboards.linkLabel": "Nginx 日志仪表板", - "kbn.server.tutorials.nginxLogs.longDescription": "Filebeat 模块 `nginx` 解析 Nginx HTTP 服务器创建的访问和错误日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.nginxLogs.nameTitle": "Nginx 日志", - "kbn.server.tutorials.nginxLogs.shortDescription": "收集并解析 Nginx HTTP 服务器创建的访问和错误日志。", - "kbn.server.tutorials.nginxMetrics.artifacts.dashboards.linkLabel": "Nginx 指标仪表板", - "kbn.server.tutorials.nginxMetrics.longDescription": "Metricbeat 模块 `nginx` 从 Nginx HTTP 服务器提取内部指标。该模块从 {statusModuleLink} 生成的网页收集服务器状态数据。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.nginxMetrics.nameTitle": "Nginx 指标", - "kbn.server.tutorials.nginxMetrics.shortDescription": "从 Nginx HTTP 服务器提取内部指标。", - "kbn.server.tutorials.osqueryLogs.artifacts.dashboards.linkLabel": "Osquery 日志仪表板", - "kbn.server.tutorials.osqueryLogs.longDescription": "Filebeat 模块 `osquery` 收集 `osqueryd` 收集的 JSON 结果日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.osqueryLogs.nameTitle": "Osquery 日志", - "kbn.server.tutorials.osqueryLogs.shortDescription": "收集 osqueryd 创建的结果日志。", - "kbn.server.tutorials.phpFpmMetrics.longDescription": "Metricbeat 模块 `php_fpm` 从 PHP-FPM 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.phpFpmMetrics.nameTitle": "PHP-FPM 指标", - "kbn.server.tutorials.phpFpmMetrics.shortDescription": "从 PHP-FPM 提取内部指标。", - "kbn.server.tutorials.postgresqlLogs.artifacts.dashboards.linkLabel": "PostgreSQL 日志仪表板", - "kbn.server.tutorials.postgresqlLogs.longDescription": "Filebeat 模块 `postgresql` 解析 PostgreSQL 创建的错误和慢查询日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.postgresqlLogs.nameTitle": "PostgreSQL 日志", - "kbn.server.tutorials.postgresqlLogs.shortDescription": "收集并解析 PostgreSQL 创建的错误和慢查询日志。", - "kbn.server.tutorials.postgresqlMetrics.longDescription": "Metricbeat 模块 `postgresql` 从 PostgreSQL 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.postgresqlMetrics.nameTitle": "PostgreSQL 指标", - "kbn.server.tutorials.postgresqlMetrics.shortDescription": "从 PostgreSQL 提取内部指标。", - "kbn.server.tutorials.prometheusMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.prometheusMetrics.longDescription": "Metricbeat 模块 `{moduleName}` 从 Prometheus 终端节点提取指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.prometheusMetrics.nameTitle": "Prometheus 指标", - "kbn.server.tutorials.prometheusMetrics.shortDescription": "从 Prometheus 导出器提取指标。", - "kbn.server.tutorials.rabbitmqMetrics.artifacts.dashboards.linkLabel": "RabbitMQ 指标仪表板", - "kbn.server.tutorials.rabbitmqMetrics.longDescription": "Metricbeat 模块 `rabbitmq` 从 RabbitMQ 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.rabbitmqMetrics.nameTitle": "RabbitMQ 指标", - "kbn.server.tutorials.rabbitmqMetrics.shortDescription": "从 RabbitMQ 服务器提取内部指标。", - "kbn.server.tutorials.redisLogs.artifacts.dashboards.linkLabel": "Redis 日志仪表板", - "kbn.server.tutorials.redisLogs.longDescription": "Filebeat 模块 `redis` 解析 Redis 创建的错误和慢查询日志。为了使 Redis 写入错误日志,确保 Redis 配置文件中的 `logfile` 选项设置为 `redis-server.log`。通过 `SLOWLOG` 命令可直接从 Redis 读取慢查询日志。为了使 Redis 记录慢查询日志,确保设置了 `slowlog-log-slower-than` 选项。请注意,`slowlog` 是实验性文件集。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.redisLogs.nameTitle": "Redis 日志", - "kbn.server.tutorials.redisLogs.shortDescription": "收集并解析 Redis 创建的错误和慢查询日志。", - "kbn.server.tutorials.redisMetrics.artifacts.dashboards.linkLabel": "Redis 指标仪表板", - "kbn.server.tutorials.redisMetrics.longDescription": "Metricbeat 模块 `redis` 从 Redis 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.redisMetrics.nameTitle": "Redis 指标", - "kbn.server.tutorials.redisMetrics.shortDescription": "从 Redis 提取内部指标。", - "kbn.server.tutorials.suricataLogs.artifacts.dashboards.linkLabel": "Suricata 日志仪表板", - "kbn.server.tutorials.suricataLogs.longDescription": "Filebeat 模块 `suricata` 从 [Suricata Eve JSON 输出](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html)收集日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.suricataLogs.nameTitle": "Suricata 日志", - "kbn.server.tutorials.suricataLogs.shortDescription": "收集 Suricata IDS/IPS/NSM 创建的结果日志。", - "kbn.server.tutorials.systemLogs.artifacts.dashboards.linkLabel": "系统日志仪表板", - "kbn.server.tutorials.systemLogs.longDescription": "Filebeat 模块 `system` 收集并解析常见 Unix/Linux 型分发的系统日志服务创建的日志。此模块在 Windows 上不可用。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.systemLogs.nameTitle": "系统日志", - "kbn.server.tutorials.systemLogs.shortDescription": "收集并解析本地 Syslog 服务器写入的日志。", - "kbn.server.tutorials.systemMetrics.artifacts.dashboards.linkLabel": "系统指标仪表板", - "kbn.server.tutorials.systemMetrics.longDescription": "Metricbeat 模块 `system` 从主机收集 CPU、内存、网络和磁盘统计信息。其收集系统范围的统计信息以及每个进程和文件系统的统计信息。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.systemMetrics.nameTitle": "系统指标", - "kbn.server.tutorials.systemMetrics.shortDescription": "从主机上收集 CPU、内存、网络和磁盘统计信息。", - "kbn.server.tutorials.traefikLogs.artifacts.dashboards.linkLabel": "Traefik 日志仪表板", - "kbn.server.tutorials.traefikLogs.longDescription": "Filebeat 模块 `traefik` 解析 Traefik 创建的访问日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.traefikLogs.nameTitle": "Traefik 日志", - "kbn.server.tutorials.traefikLogs.shortDescription": "收集和解析 Traefik 代理创建的访问日志。", - "kbn.server.tutorials.uptimeMonitors.artifacts.dashboards.linkLabel": "Uptime 应用", - "kbn.server.tutorials.uptimeMonitors.longDescription": "通过主动探测来监测服务的可用性。 通过给定 URL 列表,Heartbeat 仅仅询问:是否保持连接? [了解详情]({learnMoreLink})。", - "kbn.server.tutorials.uptimeMonitors.nameTitle": "运行时间监测", - "kbn.server.tutorials.uptimeMonitors.shortDescription": "监测服务的可用性", - "kbn.server.tutorials.uwsgiMetrics.artifacts.dashboards.linkLabel": "uWSGI 指标仪表板", - "kbn.server.tutorials.uwsgiMetrics.longDescription": "Metricbeat 模块 `uwsgi` 从 uWSGI 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.uwsgiMetrics.nameTitle": "uWSGI 指标", - "kbn.server.tutorials.uwsgiMetrics.shortDescription": "从 uWSGI 服务器提取内部指标。", - "kbn.server.tutorials.vsphereMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.vsphereMetrics.longDescription": "Metricbeat 模块 `vsphere` 从 vSphere 集群提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.vsphereMetrics.nameTitle": "vSphere 指标", - "kbn.server.tutorials.vsphereMetrics.shortDescription": "从 vSphere 提取内部指标。", - "kbn.server.tutorials.windowsEventLogs.artifacts.application.label": "SIEM App", - "kbn.server.tutorials.windowsEventLogs.longDescription": "使用 Winlogbeat 从 Windows 事件日志收集日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.windowsEventLogs.nameTitle": "Windows 事件日志", - "kbn.server.tutorials.windowsEventLogs.shortDescription": "从 Windows 事件日志提取日志。", - "kbn.server.tutorials.windowsMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.windowsMetrics.longDescription": "Metricbeat 模块 `windows` 从 Windows 提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.windowsMetrics.nameTitle": "Windows 指标", - "kbn.server.tutorials.windowsMetrics.shortDescription": "从 Windows 提取内部指标。", - "kbn.server.tutorials.zeekLogs.artifacts.dashboards.linkLabel": "Zeek 日志仪表板", - "kbn.server.tutorials.zeekLogs.longDescription": "Filebeat 模块 `zeek` 从 [Zeek](https://www.zeek.org//documentation/index.html) 收集日志。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.zeekLogs.nameTitle": "Zeek 日志", - "kbn.server.tutorials.zeekLogs.shortDescription": "收集 Zeek/Bro 创建的日志。", - "kbn.server.tutorials.zookeeperMetrics.artifacts.application.label": "Discover", - "kbn.server.tutorials.zookeeperMetrics.longDescription": "Metricbeat 模块 `{moduleName}` 从 Zookeeper 服务器提取内部指标。[了解详情]({learnMoreLink})。", - "kbn.server.tutorials.zookeeperMetrics.nameTitle": "Zookeeper 指标", - "kbn.server.tutorials.zookeeperMetrics.shortDescription": "从 Zookeeper 服务器提取内部指标。", "kbn.settings.advancedSettings.voiceAnnouncement.searchResultScreenReaderMessage": "您已搜索 {query}。{sectionLenght, plural, one {# 个部分} other {# 个部分}}中有 {optionLenght, plural, one {# 个选项} other {# 个选项}}", "kbn.topNavMenu.openInspectorButtonLabel": "检查", "kbn.topNavMenu.refreshButtonLabel": "刷新", @@ -2483,183 +1809,747 @@ "kbn.visualize.wizard.step1Breadcrumb": "创建", "kbn.visualize.wizard.step2Breadcrumb": "创建", "kbn.visualizeTitle": "可视化", - "kbnVislibVisTypes.area.areaDescription": "突出折线图下方的数量", - "kbnVislibVisTypes.area.areaTitle": "面积图", - "kbnVislibVisTypes.area.countText": "计数", - "kbnVislibVisTypes.area.groupTitle": "拆分序列", - "kbnVislibVisTypes.area.metricsTitle": "Y 轴", - "kbnVislibVisTypes.area.radiusTitle": "点大小", - "kbnVislibVisTypes.area.segmentTitle": "X 轴", - "kbnVislibVisTypes.area.splitTitle": "拆分图表", - "kbnVislibVisTypes.area.tabs.metricsAxesTitle": "指标和轴", - "kbnVislibVisTypes.area.tabs.panelSettingsTitle": "面板设置", - "kbnVislibVisTypes.axisModes.normalText": "正常", - "kbnVislibVisTypes.axisModes.percentageText": "百分比", - "kbnVislibVisTypes.axisModes.silhouetteText": "剪影", - "kbnVislibVisTypes.axisModes.wiggleText": "扭动", - "kbnVislibVisTypes.categoryAxis.rotate.angledText": "带角度", - "kbnVislibVisTypes.categoryAxis.rotate.horizontalText": "水平", - "kbnVislibVisTypes.categoryAxis.rotate.verticalText": "垂直", - "kbnVislibVisTypes.chartModes.normalText": "正常", - "kbnVislibVisTypes.chartModes.stackedText": "堆叠", - "kbnVislibVisTypes.chartTypes.areaText": "面积图", - "kbnVislibVisTypes.chartTypes.barText": "条形图", - "kbnVislibVisTypes.chartTypes.lineText": "折线图", - "kbnVislibVisTypes.controls.colorRanges.errorText": "每个范围应大于前一范围。", - "kbnVislibVisTypes.controls.colorSchema.colorSchemaLabel": "颜色模式", - "kbnVislibVisTypes.controls.colorSchema.howToChangeColorsDescription": "可以更改图例中的各个颜色。", - "kbnVislibVisTypes.controls.colorSchema.resetColorsButtonLabel": "重置颜色", - "kbnVislibVisTypes.controls.colorSchema.reverseColorSchemaLabel": "反转模式", - "kbnVislibVisTypes.controls.gaugeOptions.alignmentLabel": "对齐方式", - "kbnVislibVisTypes.controls.gaugeOptions.autoExtendRangeLabel": "自动扩展范围", - "kbnVislibVisTypes.controls.gaugeOptions.displayWarningsLabel": "显示警告", - "kbnVislibVisTypes.controls.gaugeOptions.extendRangeTooltip": "将数据范围扩展到最大值。", - "kbnVislibVisTypes.controls.gaugeOptions.gaugeTypeLabel": "仪表类型", - "kbnVislibVisTypes.controls.gaugeOptions.labelsTitle": "标签", - "kbnVislibVisTypes.controls.gaugeOptions.percentageModeLabel": "百分比模式", - "kbnVislibVisTypes.controls.gaugeOptions.rangesTitle": "范围", - "kbnVislibVisTypes.controls.gaugeOptions.showLabelsLabel": "显示标签", - "kbnVislibVisTypes.controls.gaugeOptions.showLegendLabel": "显示图例", - "kbnVislibVisTypes.controls.gaugeOptions.showScaleLabel": "显示比例", - "kbnVislibVisTypes.controls.gaugeOptions.styleTitle": "样式", - "kbnVislibVisTypes.controls.gaugeOptions.subTextLabel": "子标签", - "kbnVislibVisTypes.controls.gaugeOptions.switchWarningsTooltip": "打开/关闭警告。打开时,如果标签没有全部显示,则显示警告。", - "kbnVislibVisTypes.controls.heatmapOptions.colorLabel": "颜色", - "kbnVislibVisTypes.controls.heatmapOptions.colorScaleLabel": "色阶", - "kbnVislibVisTypes.controls.heatmapOptions.colorsNumberLabel": "颜色个数", - "kbnVislibVisTypes.controls.heatmapOptions.labelsTitle": "标签", - "kbnVislibVisTypes.controls.heatmapOptions.overwriteAutomaticColorLabel": "覆盖自动配色", - "kbnVislibVisTypes.controls.heatmapOptions.percentageModeLabel": "百分比模式", - "kbnVislibVisTypes.controls.heatmapOptions.rotateLabel": "旋转", - "kbnVislibVisTypes.controls.heatmapOptions.scaleToDataBoundsLabel": "缩放到数据边界", - "kbnVislibVisTypes.controls.heatmapOptions.showLabelsTitle": "显示标签", - "kbnVislibVisTypes.controls.heatmapOptions.useCustomRangesLabel": "使用定制范围", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.alignLabel": "对齐", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.filterLabelsLabel": "筛选标签", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.labelsTitle": "标签", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.positionLabel": "位置", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.showLabel": "显示", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.showLabelsLabel": "显示标签", - "kbnVislibVisTypes.controls.pointSeries.categoryAxis.xAxisTitle": "X 轴", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.dontShowLabel": "不显示", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.gridText": "网格", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.xAxisLinesLabel": "显示 X 轴线", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.yAxisLinesDisabledTooltip": "直方图的 X 轴线无法显示。", - "kbnVislibVisTypes.controls.pointSeries.gridAxis.yAxisLinesLabel": "Y 轴线", - "kbnVislibVisTypes.controls.pointSeries.series.chartTypeLabel": "图表类型", - "kbnVislibVisTypes.controls.pointSeries.series.lineModeLabel": "线条模式", - "kbnVislibVisTypes.controls.pointSeries.series.lineWidthLabel": "线条宽度", - "kbnVislibVisTypes.controls.pointSeries.series.metricsTitle": "指标", - "kbnVislibVisTypes.controls.pointSeries.series.modeLabel": "模式", - "kbnVislibVisTypes.controls.pointSeries.series.newAxisLabel": "新建轴…...", - "kbnVislibVisTypes.controls.pointSeries.series.showDotsLabel": "显示点线", - "kbnVislibVisTypes.controls.pointSeries.series.showLineLabel": "显示为线条", - "kbnVislibVisTypes.controls.pointSeries.series.valueAxisLabel": "值轴", - "kbnVislibVisTypes.controls.pointSeries.seriesAccordionAriaLabel": "切换 {agg} 选项", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.addButtonTooltip": "添加 Y 轴", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.customExtentsLabel": "定制范围", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.maxLabel": "最大值", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.minErrorMessage": "最小值应小于最大值。", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.minLabel": "最小值", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.minNeededScaleText": "如果选择了对数刻度,最小值必须大于 0。", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.modeLabel": "模式", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.positionLabel": "位置", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.removeButtonTooltip": "移除 Y 轴", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleToDataBounds.boundsMargin": "边界边距", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin": "边界边距必须大于或等于 0。", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleToDataBoundsLabel": "缩放到数据边界", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleTypeLabel": "缩放类型", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.setAxisExtentsLabel": "设置轴范围", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.showLabel": "显示", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.titleLabel": "标题", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.toggleCustomExtendsAriaLabel": "切换定制范围", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.toggleOptionsAriaLabel": "切换 {axisName} 选项", - "kbnVislibVisTypes.controls.pointSeries.valueAxes.yAxisTitle": "Y 轴", - "kbnVislibVisTypes.controls.rangeErrorMessage": "值必须是在 {min} 到 {max} 的范围内", - "kbnVislibVisTypes.controls.truncateLabel": "截断", - "kbnVislibVisTypes.controls.vislibBasicOptions.legendPositionLabel": "图例位置", - "kbnVislibVisTypes.controls.vislibBasicOptions.showTooltipLabel": "显示工具提示", - "kbnVislibVisTypes.editors.heatmap.basicSettingsTitle": "基本设置", - "kbnVislibVisTypes.editors.heatmap.heatmapSettingsTitle": "热图设置", - "kbnVislibVisTypes.editors.heatmap.highlightLabel": "高亮范围", - "kbnVislibVisTypes.vislib.heatmap.maxBucketsText": "定义了过多的序列 ({nr})。配置的最大值为 {max}。", - "kbnVislibVisTypes.editors.heatmap.highlightLabelTooltip": "高亮显示图表中鼠标悬停的范围以及图例中对应的标签。", - "kbnVislibVisTypes.editors.pie.donutLabel": "圆环图", - "kbnVislibVisTypes.editors.pie.labelsSettingsTitle": "标签设置", - "kbnVislibVisTypes.editors.pie.pieSettingsTitle": "饼图设置", - "kbnVislibVisTypes.editors.pie.showLabelsLabel": "显示标签", - "kbnVislibVisTypes.editors.pie.showTopLevelOnlyLabel": "仅显示顶级", - "kbnVislibVisTypes.editors.pie.showValuesLabel": "显示值", - "kbnVislibVisTypes.editors.pointSeries.currentTimeMarkerLabel": "当前时间标记", - "kbnVislibVisTypes.editors.pointSeries.orderBucketsBySumLabel": "按总计值排序存储桶", - "kbnVislibVisTypes.editors.pointSeries.settingsTitle": "设置", - "kbnVislibVisTypes.editors.pointSeries.showLabels": "在图表上显示值", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.colorLabel": "线条颜色", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.showLabel": "显示阈值线条", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.styleLabel": "线条样式", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.valueLabel": "阈值", - "kbnVislibVisTypes.editors.pointSeries.thresholdLine.widthLabel": "线条宽度", - "kbnVislibVisTypes.editors.pointSeries.thresholdLineSettingsTitle": "阈值线条", - "kbnVislibVisTypes.functions.pie.help": "饼图可视化", - "kbnVislibVisTypes.functions.vislib.help": "Vislib 可视化", - "kbnVislibVisTypes.gauge.alignmentAutomaticTitle": "自动", - "kbnVislibVisTypes.gauge.alignmentHorizontalTitle": "水平", - "kbnVislibVisTypes.gauge.alignmentVerticalTitle": "垂直", - "kbnVislibVisTypes.gauge.gaugeDescription": "仪表盘图指示指标的状态。用于显示指标值与参考阈值的相关程度。", - "kbnVislibVisTypes.gauge.gaugeTitle": "仪表盘图", - "kbnVislibVisTypes.gauge.gaugeTypes.arcText": "弧形", - "kbnVislibVisTypes.gauge.gaugeTypes.circleText": "圆形", - "kbnVislibVisTypes.gauge.groupTitle": "拆分组", - "kbnVislibVisTypes.gauge.metricTitle": "指标", - "kbnVislibVisTypes.goal.goalDescription": "目标图指示与最终目标的接近程度。", - "kbnVislibVisTypes.goal.goalTitle": "目标图", - "kbnVislibVisTypes.goal.groupTitle": "拆分组", - "kbnVislibVisTypes.goal.metricTitle": "指标", - "kbnVislibVisTypes.heatmap.groupTitle": "Y 轴", - "kbnVislibVisTypes.heatmap.heatmapDescription": "为矩阵中的单元格添加阴影", - "kbnVislibVisTypes.heatmap.heatmapTitle": "热力图", - "kbnVislibVisTypes.heatmap.metricTitle": "值", - "kbnVislibVisTypes.heatmap.segmentTitle": "X 轴", - "kbnVislibVisTypes.heatmap.splitTitle": "拆分图表", - "kbnVislibVisTypes.histogram.groupTitle": "拆分序列", - "kbnVislibVisTypes.histogram.histogramDescription": "向每个轴赋予连续变量", - "kbnVislibVisTypes.histogram.histogramTitle": "垂直条形图", - "kbnVislibVisTypes.histogram.metricTitle": "Y 轴", - "kbnVislibVisTypes.histogram.radiusTitle": "点大小", - "kbnVislibVisTypes.histogram.segmentTitle": "X 轴", - "kbnVislibVisTypes.histogram.splitTitle": "拆分图表", - "kbnVislibVisTypes.horizontalBar.groupTitle": "拆分序列", - "kbnVislibVisTypes.horizontalBar.horizontalBarDescription": "向每个轴赋予连续变量", - "kbnVislibVisTypes.horizontalBar.horizontalBarTitle": "水平条形图", - "kbnVislibVisTypes.horizontalBar.metricTitle": "Y 轴", - "kbnVislibVisTypes.horizontalBar.radiusTitle": "点大小", - "kbnVislibVisTypes.horizontalBar.segmentTitle": "X 轴", - "kbnVislibVisTypes.horizontalBar.splitTitle": "拆分图表", - "kbnVislibVisTypes.interpolationModes.smoothedText": "平滑", - "kbnVislibVisTypes.interpolationModes.steppedText": "渐变", - "kbnVislibVisTypes.interpolationModes.straightText": "直线", - "kbnVislibVisTypes.legendPositions.bottomText": "下", - "kbnVislibVisTypes.legendPositions.leftText": "左", - "kbnVislibVisTypes.legendPositions.rightText": "右", - "kbnVislibVisTypes.legendPositions.topText": "上", - "kbnVislibVisTypes.line.groupTitle": "拆分序列", - "kbnVislibVisTypes.line.lineDescription": "突出趋势", - "kbnVislibVisTypes.line.lineTitle": "折线图", - "kbnVislibVisTypes.line.metricTitle": "Y 轴", - "kbnVislibVisTypes.line.radiusTitle": "点大小", - "kbnVislibVisTypes.line.segmentTitle": "X 轴", - "kbnVislibVisTypes.line.splitTitle": "拆分图表", - "kbnVislibVisTypes.pie.metricTitle": "切片大小", - "kbnVislibVisTypes.pie.pieDescription": "比较整体的各个部分", - "kbnVislibVisTypes.pie.pieTitle": "饼图", - "kbnVislibVisTypes.pie.segmentTitle": "拆分切片", - "kbnVislibVisTypes.pie.splitTitle": "拆分图表", - "kbnVislibVisTypes.scaleTypes.linearText": "线性", - "kbnVislibVisTypes.scaleTypes.logText": "对数", - "kbnVislibVisTypes.scaleTypes.squareRootText": "平方根", - "kbnVislibVisTypes.thresholdLine.style.dashedText": "虚线", - "kbnVislibVisTypes.thresholdLine.style.dotdashedText": "点虚线", - "kbnVislibVisTypes.thresholdLine.style.fullText": "实线", + "home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.auditbeat.premInstructions.gettingStarted.title": "入门", + "home.tutorials.common.auditbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.auditbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.auditbeatCloudInstructions.config.debTitle": "编辑配置", + "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.auditbeatCloudInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.auditbeatCloudInstructions.config.rpmTitle": "编辑配置", + "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.auditbeatCloudInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.auditbeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.auditbeatInstructions.config.debTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.auditbeatInstructions.config.debTitle": "编辑配置", + "home.tutorials.common.auditbeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.auditbeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.auditbeatInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.auditbeatInstructions.config.rpmTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.auditbeatInstructions.config.rpmTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.auditbeatInstructions.config.rpmTitle": "编辑配置", + "home.tutorials.common.auditbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.auditbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.auditbeatInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.auditbeatInstructions.install.debTextPost": "寻找 32 位软件包?请参阅[下载页面]({linkUrl})。", + "home.tutorials.common.auditbeatInstructions.install.debTextPre": "首次使用 Auditbeat?请参阅[入门指南]({linkUrl})。", + "home.tutorials.common.auditbeatInstructions.install.debTitle": "下载并安装 Auditbeat", + "home.tutorials.common.auditbeatInstructions.install.osxTextPre": "首次使用 Auditbeat?请参阅[入门指南]({linkUrl})。", + "home.tutorials.common.auditbeatInstructions.install.osxTitle": "下载并安装 Auditbeat", + "home.tutorials.common.auditbeatInstructions.install.rpmTextPost": "寻找 32 位软件包?请参阅[下载页面]({linkUrl})。", + "home.tutorials.common.auditbeatInstructions.install.rpmTextPre": "首次使用 Auditbeat?请参阅[入门指南]({linkUrl})。", + "home.tutorials.common.auditbeatInstructions.install.rpmTitle": "下载并安装 Auditbeat", + "home.tutorials.common.auditbeatInstructions.install.windowsTextPost": "在 {auditbeatPath} 文件中修改 {propertyName} 下的设置以指向您的 Elasticsearch 安装。", + "home.tutorials.common.auditbeatInstructions.install.windowsTextPre": "首次使用 Auditbeat?请参阅[入门指南]({guideLinkUrl})。\n 1.从[下载]({auditbeatLinkUrl})页面下载 Auditbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 `{directoryName}` 目录重命名为 `Auditbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Auditbeat 安装为 Windows 服务。", + "home.tutorials.common.auditbeatInstructions.install.windowsTitle": "下载并安装 Auditbeat", + "home.tutorials.common.auditbeatInstructions.start.debTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.auditbeatInstructions.start.debTitle": "启动 Auditbeat", + "home.tutorials.common.auditbeatInstructions.start.osxTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.auditbeatInstructions.start.osxTitle": "启动 Auditbeat", + "home.tutorials.common.auditbeatInstructions.start.rpmTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.auditbeatInstructions.start.rpmTitle": "启动 Auditbeat", + "home.tutorials.common.auditbeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.auditbeatInstructions.start.windowsTitle": "启动 Auditbeat", + "home.tutorials.common.auditbeatStatusCheck.buttonLabel": "检查数据", + "home.tutorials.common.auditbeatStatusCheck.errorText": "尚未接收到数据", + "home.tutorials.common.auditbeatStatusCheck.successText": "已成功接收数据", + "home.tutorials.common.auditbeatStatusCheck.text": "确认从 Auditbeat 收到数据", + "home.tutorials.common.auditbeatStatusCheck.title": "状态", + "home.tutorials.common.filebeat.cloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.filebeat.premCloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.filebeat.premInstructions.gettingStarted.title": "入门", + "home.tutorials.common.filebeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.filebeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.filebeatCloudInstructions.config.debTitle": "编辑配置", + "home.tutorials.common.filebeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.filebeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.filebeatCloudInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.filebeatCloudInstructions.config.rpmTitle": "编辑配置", + "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.filebeatCloudInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.filebeatEnableInstructions.debTextPost": "在 `/etc/filebeat/modules.d/{moduleName}.yml` 文件中修改设置。", + "home.tutorials.common.filebeatEnableInstructions.debTitle": "启用和配置 {moduleName} 模块", + "home.tutorials.common.filebeatEnableInstructions.osxTextPost": "在 `modules.d/{moduleName}.yml` 文件中修改设置。", + "home.tutorials.common.filebeatEnableInstructions.osxTextPre": "从安装目录中,运行:", + "home.tutorials.common.filebeatEnableInstructions.osxTitle": "启用和配置 {moduleName} 模块", + "home.tutorials.common.filebeatEnableInstructions.rpmTextPost": "在 `/etc/filebeat/modules.d/{moduleName}.yml` 文件中修改设置。", + "home.tutorials.common.filebeatEnableInstructions.rpmTitle": "启用和配置 {moduleName} 模块", + "home.tutorials.common.filebeatEnableInstructions.windowsTextPost": "在 `modules.d/{moduleName}.yml` 文件中修改设置。", + "home.tutorials.common.filebeatEnableInstructions.windowsTextPre": "从 {path} 文件夹中,运行:", + "home.tutorials.common.filebeatEnableInstructions.windowsTitle": "启用和配置 {moduleName} 模块", + "home.tutorials.common.filebeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.filebeatInstructions.config.debTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.filebeatInstructions.config.debTitle": "编辑配置", + "home.tutorials.common.filebeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.filebeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.filebeatInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.filebeatInstructions.config.rpmTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.filebeatInstructions.config.rpmTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.filebeatInstructions.config.rpmTitle": "编辑配置", + "home.tutorials.common.filebeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.filebeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.filebeatInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.filebeatInstructions.install.debTextPost": "寻找 32 位软件包?请参阅[下载页面]({linkUrl})。", + "home.tutorials.common.filebeatInstructions.install.debTextPre": "首次使用 Filebeat?请参阅[入门指南]({linkUrl})。", + "home.tutorials.common.filebeatInstructions.install.debTitle": "下载并安装 Filebeat", + "home.tutorials.common.filebeatInstructions.install.osxTextPre": "首次使用 Filebeat?请参阅[入门指南]({linkUrl})。", + "home.tutorials.common.filebeatInstructions.install.osxTitle": "下载并安装 Filebeat", + "home.tutorials.common.filebeatInstructions.install.rpmTextPost": "寻找 32 位软件包?请参阅[下载页面]({linkUrl})。", + "home.tutorials.common.filebeatInstructions.install.rpmTextPre": "首次使用 Filebeat?请参阅[入门指南]({linkUrl})。", + "home.tutorials.common.filebeatInstructions.install.rpmTitle": "下载并安装 Filebeat", + "home.tutorials.common.filebeatInstructions.install.windowsTextPost": "在 {filebeatPath} 文件中修改 {propertyName} 下的设置以指向您的 Elasticsearch 安装。", + "home.tutorials.common.filebeatInstructions.install.windowsTextPre": "首次使用 Filebeat?请参阅[入门指南]({guideLinkUrl})。\n 1.从[下载]({filebeatLinkUrl})页面下载 Filebeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 `{directoryName}` 目录重命名为 `Filebeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Filebeat 安装为 Windows 服务。", + "home.tutorials.common.filebeatInstructions.install.windowsTitle": "下载并安装 Filebeat", + "home.tutorials.common.filebeatInstructions.start.debTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.filebeatInstructions.start.debTitle": "启动 Filebeat", + "home.tutorials.common.filebeatInstructions.start.osxTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.filebeatInstructions.start.osxTitle": "启动 Filebeat", + "home.tutorials.common.filebeatInstructions.start.rpmTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.filebeatInstructions.start.rpmTitle": "启动 Filebeat", + "home.tutorials.common.filebeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.filebeatInstructions.start.windowsTitle": "启动 Filebeat", + "home.tutorials.common.filebeatStatusCheck.buttonLabel": "检查数据", + "home.tutorials.common.filebeatStatusCheck.errorText": "尚未从此模块收到任何数据", + "home.tutorials.common.filebeatStatusCheck.successText": "从此模块成功收到数据", + "home.tutorials.common.filebeatStatusCheck.text": "确认已从 Filebeat `{moduleName}` 模块成功收到数据", + "home.tutorials.common.filebeatStatusCheck.title": "模块状态", + "home.tutorials.common.functionbeat.cloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.functionbeat.premCloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.functionbeat.premInstructions.gettingStarted.title": "入门", + "home.tutorials.common.functionbeatAWSInstructions.textPost": "其中 `` 和 `` 是您的帐户凭据,`us-east-1` 是所需的地区。", + "home.tutorials.common.functionbeatAWSInstructions.textPre": "在环境中设置您的 AWS 帐户凭据:", + "home.tutorials.common.functionbeatAWSInstructions.title": "设置 AWS 凭据", + "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.functionbeatCloudInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.functionbeatCloudInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTextPost": "其中 `` 是要采集的日志组名称,`` 是将用于暂存 Functionbeat 部署的有效 S3 存储桶名称。", + "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTitle": "配置 Cloudwatch 日志组", + "home.tutorials.common.functionbeatEnableOnPremInstructionsOSXLinux.textPre": "在 `functionbeat.yml` 文件中修改设置。", + "home.tutorials.common.functionbeatEnableOnPremInstructionsWindows.textPre": "在 {path} 文件中修改设置。", + "home.tutorials.common.functionbeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.functionbeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.functionbeatInstructions.config.osxTitle": "配置 Elastic 集群", + "home.tutorials.common.functionbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.functionbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.functionbeatInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.functionbeatInstructions.deploy.osxTextPre": "这会将 Functionbeat 安装为 Lambda 函数。`setup` 命令检查 Elasticsearch 配置并加载 Kibana 索引模式。通常可省略此命令。", + "home.tutorials.common.functionbeatInstructions.deploy.osxTitle": "将 Functionbeat 部署到 AWS Lambda", + "home.tutorials.common.functionbeatInstructions.deploy.windowsTextPre": "这会将 Functionbeat 安装为 Lambda 函数。`setup` 命令检查 Elasticsearch 配置并加载 Kibana 索引模式。通常可省略此命令。", + "home.tutorials.common.functionbeatInstructions.deploy.windowsTitle": "将 Functionbeat 部署到 AWS Lambda", + "home.tutorials.common.functionbeatInstructions.install.linuxTextPre": "首次使用 Functionbeat?请参阅[入门指南]({link})。", + "home.tutorials.common.functionbeatInstructions.install.linuxTitle": "下载并安装 Functionbeat", + "home.tutorials.common.functionbeatInstructions.install.osxTextPre": "首次使用 Functionbeat?请参阅[入门指南]({link})。", + "home.tutorials.common.functionbeatInstructions.install.osxTitle": "下载并安装 Functionbeat", + "home.tutorials.common.functionbeatInstructions.install.windowsTextPre": "首次使用 Functionbeat?请参阅[入门指南]({functionbeatLink})。\n 1.从[下载]({elasticLink})页面下载 Functionbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 {directoryName} 目录重命名为 `Functionbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符下,前往 Functionbeat 目录:", + "home.tutorials.common.functionbeatInstructions.install.windowsTitle": "下载并安装 Functionbeat", + "home.tutorials.common.functionbeatStatusCheck.buttonLabel": "检查数据", + "home.tutorials.common.functionbeatStatusCheck.errorText": "尚未从 Functionbeat 收到任何数据", + "home.tutorials.common.functionbeatStatusCheck.successText": "从 Functionbeat 成功收到数据", + "home.tutorials.common.functionbeatStatusCheck.text": "确认从 Functionbeat 收到数据", + "home.tutorials.common.functionbeatStatusCheck.title": "Functionbeat 状态", + "home.tutorials.common.heartbeat.cloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.heartbeat.premCloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.heartbeat.premInstructions.gettingStarted.title": "入门", + "home.tutorials.common.heartbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.heartbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.heartbeatCloudInstructions.config.debTitle": "编辑配置", + "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.heartbeatCloudInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.heartbeatCloudInstructions.config.rpmTitle": "编辑配置", + "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.heartbeatCloudInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.heartbeatEnableCloudInstructions.debTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", + "home.tutorials.common.heartbeatEnableCloudInstructions.defaultTextPost": "有关如何在 Heartbeat 中配置监测的详细信息,请参阅 [Heartbeat 配置文档]({configureLink})", + "home.tutorials.common.heartbeatEnableCloudInstructions.defaultTitle": "编辑配置 - 添加监测", + "home.tutorials.common.heartbeatEnableCloudInstructions.osxTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", + "home.tutorials.common.heartbeatEnableCloudInstructions.rpmTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", + "home.tutorials.common.heartbeatEnableCloudInstructions.windowsTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.debTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTextPost": "其中 {hostTemplate} 是受监测 URL。有关如何在 Heartbeat 中配置监测的详细信息,请参阅 [Heartbeat 配置文档]({configureLink})", + "home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTitle": "编辑配置 - 添加监测", + "home.tutorials.common.heartbeatEnableOnPremInstructions.osxTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.rpmTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", + "home.tutorials.common.heartbeatEnableOnPremInstructions.windowsTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", + "home.tutorials.common.heartbeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.heartbeatInstructions.config.debTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.heartbeatInstructions.config.debTitle": "编辑配置", + "home.tutorials.common.heartbeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.heartbeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.heartbeatInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.heartbeatInstructions.config.rpmTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.heartbeatInstructions.config.rpmTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.heartbeatInstructions.config.rpmTitle": "编辑配置", + "home.tutorials.common.heartbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.heartbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.heartbeatInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.heartbeatInstructions.install.debTextPost": "寻找 32 位软件包?请参阅[下载页面]({link})。", + "home.tutorials.common.heartbeatInstructions.install.debTextPre": "首次使用 Heartbeat?请参阅[入门指南]({link})。", + "home.tutorials.common.heartbeatInstructions.install.debTitle": "下载并安装 Heartbeat", + "home.tutorials.common.heartbeatInstructions.install.osxTextPre": "首次使用 Heartbeat?请参阅[入门指南]({link})。", + "home.tutorials.common.heartbeatInstructions.install.osxTitle": "下载并安装 Heartbeat", + "home.tutorials.common.heartbeatInstructions.install.rpmTextPre": "首次使用 Heartbeat?请参阅[入门指南]({link})。", + "home.tutorials.common.heartbeatInstructions.install.rpmTitle": "下载并安装 Heartbeat", + "home.tutorials.common.heartbeatInstructions.install.windowsTextPre": "首次使用 Heartbeat?请参阅[入门指南]({heartbeatLink})。\n 1.从[下载]({elasticLink})页面下载 Heartbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 {directoryName} 目录重命名为 `Heartbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Heartbeat 安装为 Windows 服务。", + "home.tutorials.common.heartbeatInstructions.install.windowsTitle": "下载并安装 Heartbeat", + "home.tutorials.common.heartbeatInstructions.start.debTextPre": "`setup` 命令加载 Kibana 索引模式。", + "home.tutorials.common.heartbeatInstructions.start.debTitle": "启动 Heartbeat", + "home.tutorials.common.heartbeatInstructions.start.osxTextPre": "`setup` 命令加载 Kibana 索引模式。", + "home.tutorials.common.heartbeatInstructions.start.osxTitle": "启动 Heartbeat", + "home.tutorials.common.heartbeatInstructions.start.rpmTextPre": "`setup` 命令加载 Kibana 索引模式。", + "home.tutorials.common.heartbeatInstructions.start.rpmTitle": "启动 Heartbeat", + "home.tutorials.common.heartbeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 索引模式。", + "home.tutorials.common.heartbeatInstructions.start.windowsTitle": "启动 Heartbeat", + "home.tutorials.common.heartbeatStatusCheck.buttonLabel": "检查数据", + "home.tutorials.common.heartbeatStatusCheck.errorText": "尚未从 Heartbeat 收到任何数据", + "home.tutorials.common.heartbeatStatusCheck.successText": "从 Heartbeat 成功收到数据", + "home.tutorials.common.heartbeatStatusCheck.text": "确认从 Heartbeat 收到数据", + "home.tutorials.common.heartbeatStatusCheck.title": "Heartbeat 状态", + "home.tutorials.common.logstashInstructions.install.java.osxTextPre": "按照[此处]({link})的安装说明执行操作。", + "home.tutorials.common.logstashInstructions.install.java.osxTitle": "下载并安装 Java Runtime Environment", + "home.tutorials.common.logstashInstructions.install.java.windowsTextPre": "按照[此处]({link})的安装说明执行操作。", + "home.tutorials.common.logstashInstructions.install.java.windowsTitle": "下载并安装 Java Runtime Environment", + "home.tutorials.common.logstashInstructions.install.logstash.osxTextPre": "首次使用 Logstash? 请参阅[入门指南]({link})。", + "home.tutorials.common.logstashInstructions.install.logstash.osxTitle": "下载并安装 Logstash", + "home.tutorials.common.logstashInstructions.install.logstash.windowsTextPre": "首次使用 Logstash? 请参阅[入门指南]({logstashLink})。\n 1. [下载]({elasticLink}) Logstash Windows zip 文件。\n 2.解压缩 zip 文件的内容。", + "home.tutorials.common.logstashInstructions.install.logstash.windowsTitle": "下载并安装 Logstash", + "home.tutorials.common.metricbeat.cloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.metricbeat.premCloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.metricbeat.premInstructions.gettingStarted.title": "入门", + "home.tutorials.common.metricbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.metricbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.metricbeatCloudInstructions.config.debTitle": "编辑配置", + "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.metricbeatCloudInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.metricbeatCloudInstructions.config.rpmTitle": "编辑配置", + "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.metricbeatCloudInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.metricbeatEnableInstructions.debTextPost": "在 `/etc/metricbeat/modules.d/{moduleName}.yml` 文件中修改设置。", + "home.tutorials.common.metricbeatEnableInstructions.debTitle": "启用和配置 {moduleName} 模块", + "home.tutorials.common.metricbeatEnableInstructions.osxTextPost": "在 `modules.d/{moduleName}.yml` 文件中修改设置。", + "home.tutorials.common.metricbeatEnableInstructions.osxTextPre": "从安装目录中,运行:", + "home.tutorials.common.metricbeatEnableInstructions.osxTitle": "启用和配置 {moduleName} 模块", + "home.tutorials.common.metricbeatEnableInstructions.rpmTextPost": "在 `/etc/metricbeat/modules.d/{moduleName}.yml` 文件中修改设置。", + "home.tutorials.common.metricbeatEnableInstructions.rpmTitle": "启用和配置 {moduleName} 模块", + "home.tutorials.common.metricbeatEnableInstructions.windowsTextPost": "在 `modules.d/{moduleName}.yml` 文件中修改设置。", + "home.tutorials.common.metricbeatEnableInstructions.windowsTextPre": "从 {path} 文件夹中,运行:", + "home.tutorials.common.metricbeatEnableInstructions.windowsTitle": "启用和配置 {moduleName} 模块", + "home.tutorials.common.metricbeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.metricbeatInstructions.config.debTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.metricbeatInstructions.config.debTitle": "编辑配置", + "home.tutorials.common.metricbeatInstructions.config.osxTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.metricbeatInstructions.config.osxTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.metricbeatInstructions.config.osxTitle": "编辑配置", + "home.tutorials.common.metricbeatInstructions.config.rpmTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.metricbeatInstructions.config.rpmTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.metricbeatInstructions.config.rpmTitle": "编辑配置", + "home.tutorials.common.metricbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.metricbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.metricbeatInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.metricbeatInstructions.install.debTextPost": "寻找 32 位软件包?请参阅[下载页面]({link})。", + "home.tutorials.common.metricbeatInstructions.install.debTextPre": "首次使用 Metricbeat?请参阅[入门指南]({link})。", + "home.tutorials.common.metricbeatInstructions.install.debTitle": "下载并安装 Metricbeat", + "home.tutorials.common.metricbeatInstructions.install.osxTextPre": "首次使用 Metricbeat?请参阅[入门指南]({link})。", + "home.tutorials.common.metricbeatInstructions.install.osxTitle": "下载并安装 Metricbeat", + "home.tutorials.common.metricbeatInstructions.install.rpmTextPre": "首次使用 Metricbeat?请参阅[入门指南]({link})。", + "home.tutorials.common.metricbeatInstructions.install.rpmTitle": "下载并安装 Metricbeat", + "home.tutorials.common.metricbeatInstructions.install.windowsTextPost": "在 {path} 文件中修改 `output.elasticsearch` 下的设置以指向您的 Elasticsearch 安装。", + "home.tutorials.common.metricbeatInstructions.install.windowsTextPre": "首次使用 Metricbeat?请参阅[入门指南]({metricbeatLink})。\n 1.从[下载]({elasticLink})页面下载 Metricbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 {directoryName} 目录重命名为 `Metricbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Metricbeat 安装为 Windows 服务。", + "home.tutorials.common.metricbeatInstructions.install.windowsTitle": "下载并安装 Metricbeat", + "home.tutorials.common.metricbeatInstructions.start.debTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.metricbeatInstructions.start.debTitle": "启动 Metricbeat", + "home.tutorials.common.metricbeatInstructions.start.osxTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.metricbeatInstructions.start.osxTitle": "启动 Metricbeat", + "home.tutorials.common.metricbeatInstructions.start.rpmTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.metricbeatInstructions.start.rpmTitle": "启动 Metricbeat", + "home.tutorials.common.metricbeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.metricbeatInstructions.start.windowsTitle": "启动 Metricbeat", + "home.tutorials.common.metricbeatStatusCheck.buttonLabel": "检查数据", + "home.tutorials.common.metricbeatStatusCheck.errorText": "尚未从此模块收到任何数据", + "home.tutorials.common.metricbeatStatusCheck.successText": "从此模块成功收到数据", + "home.tutorials.common.metricbeatStatusCheck.text": "确认从 Metricbeat `{moduleName}` 模块收到数据", + "home.tutorials.common.metricbeatStatusCheck.title": "模块状态", + "home.tutorials.common.premCloudInstructions.option1.textPre": "前往 [Elastic Cloud]({link})。如果您还没有帐户,请注册。免费试用 14 天。\n\n登录至 Elastic Cloud 控制台\n\n如要创建集群,请在 Elastic Cloud 控制台中:\n 1.选择**创建部署**,然后指定**部署名称**\n 2.根据需要修改其他部署选项(或者不修改,默认值可帮助您快速入门)\n 3.单击**创建部署**\n 4.等候部署创建完成\n 5.前往新的 Cloud Kibana 实例,然后按照 Kibana 主页上的说明执行操作", + "home.tutorials.common.premCloudInstructions.option1.title": "选项 1:在 Elastic Cloud 中尝试", + "home.tutorials.common.premCloudInstructions.option2.textPre": "如果基于托管式 Elasticsearch 实例运行此 Kibana 实例,请继续手动设置。\n\n针对您的记录,分别将 **Elasticsearch** 终端节点另存为 {urlTemplate}将集群**密码**另存为 {passwordTemplate}", + "home.tutorials.common.premCloudInstructions.option2.title": "选项 2:将本地 Kibana 连接到 Cloud 实例", + "home.tutorials.common.winlogbeat.cloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.winlogbeat.premCloudInstructions.gettingStarted.title": "入门", + "home.tutorials.common.winlogbeat.premInstructions.gettingStarted.title": "入门", + "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", + "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", + "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.winlogbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", + "home.tutorials.common.winlogbeatInstructions.config.windowsTextPre": "修改 {path} 以设置连接信息:", + "home.tutorials.common.winlogbeatInstructions.config.windowsTitle": "编辑配置", + "home.tutorials.common.winlogbeatInstructions.install.windowsTextPost": "在 {path} 文件中修改 `output.elasticsearch` 下的设置以指向您的 Elasticsearch 安装。", + "home.tutorials.common.winlogbeatInstructions.install.windowsTextPre": "首次使用 Winlogbeat?请参阅[入门指南]({winlogbeatLink})。\n 1.从[下载]({elasticLink})页面下载 Winlogbeat Windows zip 文件。\n 2.将 zip 文件的内容解压缩到 {folderPath}。\n 3.将 {directoryName} 目录重命名为 `Winlogbeat`。\n 4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n 5.从 PowerShell 提示符处,运行以下命令以将 Winlogbeat 安装为 Windows 服务。", + "home.tutorials.common.winlogbeatInstructions.install.windowsTitle": "下载并安装 Winlogbeat", + "home.tutorials.common.winlogbeatInstructions.start.windowsTextPre": "`setup` 命令加载 Kibana 仪表板。如果仪表板已设置,请省略此命令。", + "home.tutorials.common.winlogbeatInstructions.start.windowsTitle": "启动 Winlogbeat", + "home.tutorials.common.winlogbeatStatusCheck.buttonLabel": "检查数据", + "home.tutorials.common.winlogbeatStatusCheck.errorText": "尚未接收到数据", + "home.tutorials.common.winlogbeatStatusCheck.successText": "已成功接收数据", + "home.tutorials.common.winlogbeatStatusCheck.text": "确认从 Winlogbeat 收到数据", + "home.tutorials.common.winlogbeatStatusCheck.title": "模块状态", + "home.tutorials.aerospikeMetrics.artifacts.application.label": "Discover", + "home.tutorials.aerospikeMetrics.longDescription": "Metricbeat 模块 `aerospike` 从 Aerospike 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.aerospikeMetrics.nameTitle": "Aerospike 指标", + "home.tutorials.aerospikeMetrics.shortDescription": "从 Aerospike 服务器提取内部指标。", + "home.tutorials.apacheLogs.artifacts.dashboards.linkLabel": "Apache 日志仪表板", + "home.tutorials.apacheLogs.longDescription": "Filebeat 模块 apache 解析 Apache HTTP 服务器创建的访问和错误日志。[了解详情]({learnMoreLink})。", + "home.tutorials.apacheLogs.nameTitle": "Apache 日志", + "home.tutorials.apacheLogs.shortDescription": "收集并解析 Apache HTTP 服务器创建的访问和错误日志。", + "home.tutorials.apacheMetrics.artifacts.dashboards.linkLabel": "Apache 指标仪表板", + "home.tutorials.apacheMetrics.longDescription": "Metricbeat 模块 `apache` 从 Apache 2 HTTP 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.apacheMetrics.nameTitle": "Apache 指标", + "home.tutorials.apacheMetrics.shortDescription": "从 Apache 2 HTTP 服务器提取内部指标。", + "home.tutorials.auditbeat.artifacts.dashboards.linkLabel": "SIEM App", + "home.tutorials.auditbeat.longDescription": "使用 Auditbeat 从主机收集审计数据。其中包括进程、用户、登录、套接字信息、文件访问等等。[了解详情]({learnMoreLink})。", + "home.tutorials.auditbeat.nameTitle": "Auditbeat", + "home.tutorials.auditbeat.shortDescription": "从主机收集审计数据。", + "home.tutorials.awsMetrics.artifacts.dashboards.linkLabel": "AWS 指标仪表板", + "home.tutorials.awsMetrics.longDescription": "Metricbeat 模块 `aws` 从 AWS API 和 Cloudwatch 提取监测指标。[了解详情]({learnMoreLink})。", + "home.tutorials.awsMetrics.nameTitle": "AWS 指标", + "home.tutorials.awsMetrics.shortDescription": "从 AWS API 和 Cloudwatch 提取 EC2 实例的监测指标。", + "home.tutorials.cephMetrics.artifacts.application.label": "Discover", + "home.tutorials.cephMetrics.longDescription": "Metricbeat 模块 `ceph` 从 Ceph 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.cephMetrics.nameTitle": "Ceph 指标", + "home.tutorials.cephMetrics.shortDescription": "从 Ceph 服务器提取内部指标。", + "home.tutorials.ciscoLogs.artifacts.dashboards.linkLabel": "SIEM App", + "home.tutorials.ciscoLogs.longDescription": "这是用于 Cisco 网络设备日志的模块。当前支持“asa”文件集,该文件集用于通过 Syslog 接收或从文件读取的 Cisco ASA 防火墙日志。[了解详情]({learnMoreLink})。", + "home.tutorials.ciscoLogs.nameTitle": "Cisco", + "home.tutorials.ciscoLogs.shortDescription": "收集并解析从 Cisco ASA 防火墙接收的日志。", + "home.tutorials.cloudwatchLogs.longDescription": "通过部署将运行为 AWS Lambda 函数 的 Functionbeat,来收集 Cloudwatch 日志。 [了解详情]({learnMoreLink})。", + "home.tutorials.cloudwatchLogs.nameTitle": "Cloudwatch 日志", + "home.tutorials.cloudwatchLogs.shortDescription": "使用 Functionbeat 收集 Cloudwatch 日志", + "home.tutorials.corednsLogs.artifacts.dashboards.linkLabel": "CoreDNS 日志仪表板", + "home.tutorials.corednsLogs.longDescription": "`coredns` Filebeat 模块从 [CoreDNS](https://coredns.io/manual/toc/) 收集日志。[了解详情]({learnMoreLink})。", + "home.tutorials.corednsLogs.nameTitle": "CoreDNS 日志", + "home.tutorials.corednsLogs.shortDescription": "收集 Coredns 创建的日志。", + "home.tutorials.corednsMetrics.artifacts.application.label": "Discover", + "home.tutorials.corednsMetrics.longDescription": "Metricbeat 模块 `coredns` 从 CoreDNS 提取监测指标。[了解详情]({learnMoreLink})。", + "home.tutorials.corednsMetrics.nameTitle": "CoreDNS 指标", + "home.tutorials.corednsMetrics.shortDescription": "从 CoreDNS 服务器提取监测指标。", + "home.tutorials.couchbaseMetrics.artifacts.application.label": "Discover", + "home.tutorials.couchbaseMetrics.longDescription": "Metricbeat 模块 `couchbase` 从 Couchbase 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.couchbaseMetrics.nameTitle": "Couchbase 指标", + "home.tutorials.couchbaseMetrics.shortDescription": "从 Couchbase 提取内部指标。", + "home.tutorials.couchdbMetrics.artifacts.dashboards.linkLabel": "CouchDB 指标仪表板", + "home.tutorials.couchdbMetrics.longDescription": "`couchdb` Metricbeat 模块从 CouchDB 提取监测指标。[了解详情]({learnMoreLink})。", + "home.tutorials.couchdbMetrics.nameTitle": "CouchDB 指标", + "home.tutorials.couchdbMetrics.shortDescription": "从 CouchdB 服务器提取监测指标。", + "home.tutorials.dockerMetrics.artifacts.dashboards.linkLabel": "Docker 指标仪表板", + "home.tutorials.dockerMetrics.longDescription": "Metricbeat 模块 `docker` 从 Docker 服务器提取指标。[了解详情]({learnMoreLink})。", + "home.tutorials.dockerMetrics.nameTitle": "Docker 指标", + "home.tutorials.dockerMetrics.shortDescription": "提取有关 Docker 容器的指标。", + "home.tutorials.dropwizardMetrics.artifacts.application.label": "Discover", + "home.tutorials.dropwizardMetrics.longDescription": "Metricbeat 模块 `dropwizard` 从 Dropwizard Java 应用程序提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.dropwizardMetrics.nameTitle": "Dropwizard 指标", + "home.tutorials.dropwizardMetrics.shortDescription": "从 Dropwizard Java 应用程序提取内部指标。", + "home.tutorials.elasticsearchLogs.artifacts.application.label": "Discover", + "home.tutorials.elasticsearchLogs.longDescription": "Filebeat 模块 `elasticsearch` 解析 Elasticsearch 创建的日志。[了解详情]({learnMoreLink})。", + "home.tutorials.elasticsearchLogs.nameTitle": "Elasticsearch 日志", + "home.tutorials.elasticsearchLogs.shortDescription": "收集并解析 Elasticsearch 创建的日志。", + "home.tutorials.elasticsearchMetrics.artifacts.application.label": "Discover", + "home.tutorials.elasticsearchMetrics.longDescription": "Metricbeat 模块 `elasticsearch` 从 Elasticsearch 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.elasticsearchMetrics.nameTitle": "Elasticsearch 指标", + "home.tutorials.elasticsearchMetrics.shortDescription": "从 Elasticsearch 提取内部指标。", + "home.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel": "SIEM App", + "home.tutorials.envoyproxyLogs.longDescription": "这是用于 [Envoy 代理访问日志](https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log)的 Filebeat 模块。其在 Kubernetes 中既支持独立部署,又支持 Envoy 代理部署。[了解详情]({learnMoreLink})。", + "home.tutorials.envoyproxyLogs.nameTitle": "Envoyproxy", + "home.tutorials.envoyproxyLogs.shortDescription": "收集并解析从 Envoy 代理接收的日志。", + "home.tutorials.etcdMetrics.artifacts.application.label": "Discover", + "home.tutorials.etcdMetrics.longDescription": "Metricbeat 模块 `etcd` 从 Etcd 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.etcdMetrics.nameTitle": "Etcd 指标", + "home.tutorials.etcdMetrics.shortDescription": "从 Etcd 服务器提取内部指标。", + "home.tutorials.golangMetrics.artifacts.dashboards.linkLabel": "Golang 指标仪表板", + "home.tutorials.golangMetrics.longDescription": "Metricbeat 模块 `{moduleName}` 从 Golang 应用提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.golangMetrics.nameTitle": "Golang 指标", + "home.tutorials.golangMetrics.shortDescription": "从 Golang 应用提取内部指标。", + "home.tutorials.haproxyMetrics.artifacts.application.label": "Discover", + "home.tutorials.haproxyMetrics.longDescription": "Metricbeat 模块 `haproxy` 从 HAProxy 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.haproxyMetrics.nameTitle": "HAProxy 指标", + "home.tutorials.haproxyMetrics.shortDescription": "从 HAProxy 服务器提取内部指标。", + "home.tutorials.iisLogs.artifacts.dashboards.linkLabel": "IIS 日志仪表板", + "home.tutorials.iisLogs.longDescription": "Filebeat 模块 `iis` 解析 IIS HTTP 服务器创建的访问和错误日志。[了解详情]({learnMoreLink})。", + "home.tutorials.iisLogs.nameTitle": "IIS 日志", + "home.tutorials.iisLogs.shortDescription": "收集并解析 IIS HTTP 服务器创建的访问和错误日志。", + "home.tutorials.iptablesLogs.artifacts.dashboards.linkLabel": "SIEM App", + "home.tutorials.iptablesLogs.longDescription": "这是用于 iptables 和 ip6tables 日志的模块。其解析在网络上通过 Syslog 或从文件中接收的日志。另外,其识别某些 Ubiquiti 防火墙添加的前缀,该前缀包含规则集名称、规则编号和对流量执行的操作(允许/拒绝)。[了解详情]({learnMoreLink})。", + "home.tutorials.iptablesLogs.nameTitle": "Iptables / Ubiquiti", + "home.tutorials.iptablesLogs.shortDescription": "从 Ubiqiti 防火墙收集并解析 iptables 和 ip6tables 日志。", + "home.tutorials.kafkaLogs.artifacts.dashboards.linkLabel": "Kafka 日志仪表板", + "home.tutorials.kafkaLogs.longDescription": "Filebeat 模块 `kafka` 解析 Kafka 创建的日志。[了解详情]({learnMoreLink})。", + "home.tutorials.kafkaLogs.nameTitle": "Kafka 日志", + "home.tutorials.kafkaLogs.shortDescription": "收集并解析 Kafka 创建的日志。", + "home.tutorials.kafkaMetrics.artifacts.application.label": "Discover", + "home.tutorials.kafkaMetrics.longDescription": "Metricbeat 模块 `kafka` 从 Kafka 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.kafkaMetrics.nameTitle": "Kafka 指标", + "home.tutorials.kafkaMetrics.shortDescription": "从 Kafka 服务器提取内部指标。", + "home.tutorials.kibanaMetrics.artifacts.application.label": "Discover", + "home.tutorials.kibanaMetrics.longDescription": "Metricbeat 模块 `kibana` 从 Kibana 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.kibanaMetrics.nameTitle": "Kibana 指标", + "home.tutorials.kibanaMetrics.shortDescription": "从 Kibana 提取内部指标。", + "home.tutorials.kubernetesMetrics.artifacts.dashboards.linkLabel": "Kubernetes 指标仪表板", + "home.tutorials.kubernetesMetrics.longDescription": "Metricbeat 模块 `kubernetes` 从 Kubernetes API 提取指标。[了解详情]({learnMoreLink})。", + "home.tutorials.kubernetesMetrics.nameTitle": "Kubernetes 指标", + "home.tutorials.kubernetesMetrics.shortDescription": "从您的 Kubernetes 安装提取指标。", + "home.tutorials.logstashLogs.artifacts.dashboards.linkLabel": "Logstash 日志仪表板", + "home.tutorials.logstashLogs.longDescription": "Filebeat 模块 `logstash` 解析 Logstash 创建的调试和慢查询日志。[了解详情]({learnMoreLink})。", + "home.tutorials.logstashLogs.nameTitle": "Logstash 日志", + "home.tutorials.logstashLogs.shortDescription": "收集并解析 Logstash 创建的调试和慢查询日志。", + "home.tutorials.logstashMetrics.artifacts.application.label": "Discover", + "home.tutorials.logstashMetrics.longDescription": "Metricbeat 模块 `{moduleName}` 从 Logstash 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.logstashMetrics.nameTitle": "Logstash 指标", + "home.tutorials.logstashMetrics.shortDescription": "从 Logstash 服务器提取内部指标。", + "home.tutorials.memcachedMetrics.artifacts.application.label": "Discover", + "home.tutorials.memcachedMetrics.longDescription": "Metricbeat 模块 `memcached` 从 Memcached 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.memcachedMetrics.nameTitle": "Memcached 指标", + "home.tutorials.memcachedMetrics.shortDescription": "从 Memcached 提取内部指标。", + "home.tutorials.mongodbMetrics.artifacts.dashboards.linkLabel": "MongoDB 指标仪表板", + "home.tutorials.mongodbMetrics.longDescription": "Metricbeat 模块 `mongodb` 从 MongoDB 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.mongodbMetrics.nameTitle": "MongoDB 指标", + "home.tutorials.mongodbMetrics.shortDescription": "从 MongoDB 提取内部指标。", + "home.tutorials.mssqlMetrics.artifacts.dashboards.linkLabel": "Microsoft SQL Server 指标仪表板", + "home.tutorials.mssqlMetrics.longDescription": "Metricbeat 模块 `mssql` 从 Microsoft SQL Server 提取监测、日志和性能指标。[了解详情]({learnMoreLink})。", + "home.tutorials.mssqlMetrics.nameTitle": "Microsoft SQL Server 指标", + "home.tutorials.mssqlMetrics.shortDescription": "从 Microsoft SQL Server 实例提取监测指标", + "home.tutorials.muninMetrics.artifacts.application.label": "Discover", + "home.tutorials.muninMetrics.longDescription": "Metricbeat 模块 `munin` 从 Munin 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.muninMetrics.nameTitle": "Munin 指标", + "home.tutorials.muninMetrics.shortDescription": "从 Munin 服务器提取内部指标。", + "home.tutorials.mysqlLogs.artifacts.dashboards.linkLabel": "MySQL 日志仪表板", + "home.tutorials.mysqlLogs.longDescription": "Filebeat 模块 `mysql` 解析 MySQL 创建的错误和慢查询日志。[了解详情]({learnMoreLink})。", + "home.tutorials.mysqlLogs.nameTitle": "MySQL 日志", + "home.tutorials.mysqlLogs.shortDescription": "收集并解析 MySQL 创建的错误和慢查询日志。", + "home.tutorials.mysqlMetrics.artifacts.dashboards.linkLabel": "MySQL 指标仪表板", + "home.tutorials.mysqlMetrics.longDescription": "Metricbeat 模块 `mysql` 从 MySQL 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.mysqlMetrics.nameTitle": "MySQL 指标", + "home.tutorials.mysqlMetrics.shortDescription": "从 MySQL 提取内部指标。", + "home.tutorials.natsLogs.artifacts.dashboards.linkLabel": "Nats 日志仪表板", + "home.tutorials.natsLogs.longDescription": "Filebeat 模块 `nats` 解析 Nats 创建的日志。[了解详情]({learnMoreLink})。", + "home.tutorials.natsLogs.nameTitle": "Nats 日志", + "home.tutorials.natsLogs.shortDescription": "收集并解析 Nats 创建的日志。", + "home.tutorials.natsMetrics.artifacts.dashboards.linkLabel": "Nats 指标仪表板", + "home.tutorials.natsMetrics.longDescription": "Metricbeat 模块 `nats` 从 Nats 提取监测指标。[了解详情]({learnMoreLink})。", + "home.tutorials.natsMetrics.nameTitle": "Nats 指标", + "home.tutorials.natsMetrics.shortDescription": "从 Nats 服务器提取监测指标。", + "home.tutorials.netflow.common.config.elasticCloud.osxTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口,{password} 是 {elastic} 用户的密码。", + "home.tutorials.netflow.common.config.elasticCloud.osxTextPre": "修改 {logstashConfigPath} 以设置配置参数:", + "home.tutorials.netflow.common.config.elasticCloud.osxTitle": "编辑配置", + "home.tutorials.netflow.common.config.elasticCloud.windowsTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口,{password} 是 {elastic} 用户的密码。", + "home.tutorials.netflow.common.config.elasticCloud.windowsTextPre": "修改 {logstashConfigPath} 以设置配置参数:", + "home.tutorials.netflow.common.config.elasticCloud.windowsTitle": "编辑配置", + "home.tutorials.netflow.common.config.onPrem.osxTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口。", + "home.tutorials.netflow.common.config.onPrem.osxTextPre": "修改 {logstashConfigPath} 以设置配置参数:", + "home.tutorials.netflow.common.config.onPrem.osxTitle": "编辑配置", + "home.tutorials.netflow.common.config.onPrem.windowsTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口。", + "home.tutorials.netflow.common.config.onPrem.windowsTextPre": "修改 {logstashConfigPath} 以设置配置参数:", + "home.tutorials.netflow.common.config.onPrem.windowsTitle": "编辑配置", + "home.tutorials.netflow.common.config.onPremElasticCloud.osxTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口,{esUrl} 是在 Elastic Cloud 上运行的 Elasticsearch 的 URL,{password} 是 {elastic} 用户的密码。", + "home.tutorials.netflow.common.config.onPremElasticCloud.osxTextPre": "修改 {logstashConfigPath} 以设置配置参数:", + "home.tutorials.netflow.common.config.onPremElasticCloud.osxTitle": "编辑配置", + "home.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPost": "其中 {udpPort} 是 Logstash 用于接收 Netflow 数据的 UDP 端口,{esUrl} 是在 Elastic Cloud 上运行的 Elasticsearch 的 URL,{password} 是 {elastic} 用户的密码。", + "home.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPre": "修改 {logstashConfigPath} 以设置配置参数:", + "home.tutorials.netflow.common.config.onPremElasticCloud.windowsTitle": "编辑配置", + "home.tutorials.netflow.common.setup.osxTextPost": "“{setupOption}” 选项可在 Elasticsearch 中创建 {netflowPrefix} 索引模式,并导入 Kibana 仪表板和可视化。对随后的运行省略此选项可避免覆盖现有仪表板。", + "home.tutorials.netflow.common.setup.osxTextPre": "运行:", + "home.tutorials.netflow.common.setup.osxTitle": "运行 Netflow 模块", + "home.tutorials.netflow.common.setup.windowsTextPost": "“{setupOption}” 选项可在 Elasticsearch 中创建 {netflowPrefix} 索引模式,并导入 Kibana 仪表板和可视化。对随后的运行省略此选项可避免覆盖现有仪表板。", + "home.tutorials.netflow.common.setup.windowsTextPre": "运行:", + "home.tutorials.netflow.common.setup.windowsTitle": "运行 Netflow 模块", + "home.tutorials.netflow.elasticCloudInstructions.title": "入门", + "home.tutorials.netflow.onPremElasticCloudInstructions.title": "入门", + "home.tutorials.netflow.onPremInstructions.title": "入门", + "home.tutorials.netflow.tutorialLongDescription": "Logstash Netflow 模块收集并解析网络流量数据,在 Elasticsearch 中索引事件,并安装一套 Kibana 仪表板。此模块支持 Netflow 版本 5 和 9。[了解详情]({linkUrl})。", + "home.tutorials.netflow.tutorialShortDescription": "收集 Netflow 导出器发送的 Netflow 记录。", + "home.tutorials.nginxLogs.artifacts.dashboards.linkLabel": "Nginx 日志仪表板", + "home.tutorials.nginxLogs.longDescription": "Filebeat 模块 `nginx` 解析 Nginx HTTP 服务器创建的访问和错误日志。[了解详情]({learnMoreLink})。", + "home.tutorials.nginxLogs.nameTitle": "Nginx 日志", + "home.tutorials.nginxLogs.shortDescription": "收集并解析 Nginx HTTP 服务器创建的访问和错误日志。", + "home.tutorials.nginxMetrics.artifacts.dashboards.linkLabel": "Nginx 指标仪表板", + "home.tutorials.nginxMetrics.longDescription": "Metricbeat 模块 `nginx` 从 Nginx HTTP 服务器提取内部指标。该模块从 {statusModuleLink} 生成的网页收集服务器状态数据。[了解详情]({learnMoreLink})。", + "home.tutorials.nginxMetrics.nameTitle": "Nginx 指标", + "home.tutorials.nginxMetrics.shortDescription": "从 Nginx HTTP 服务器提取内部指标。", + "home.tutorials.osqueryLogs.artifacts.dashboards.linkLabel": "Osquery 日志仪表板", + "home.tutorials.osqueryLogs.longDescription": "Filebeat 模块 `osquery` 收集 `osqueryd` 收集的 JSON 结果日志。[了解详情]({learnMoreLink})。", + "home.tutorials.osqueryLogs.nameTitle": "Osquery 日志", + "home.tutorials.osqueryLogs.shortDescription": "收集 osqueryd 创建的结果日志。", + "home.tutorials.phpFpmMetrics.longDescription": "Metricbeat 模块 `php_fpm` 从 PHP-FPM 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.phpFpmMetrics.nameTitle": "PHP-FPM 指标", + "home.tutorials.phpFpmMetrics.shortDescription": "从 PHP-FPM 提取内部指标。", + "home.tutorials.postgresqlLogs.artifacts.dashboards.linkLabel": "PostgreSQL 日志仪表板", + "home.tutorials.postgresqlLogs.longDescription": "Filebeat 模块 `postgresql` 解析 PostgreSQL 创建的错误和慢查询日志。[了解详情]({learnMoreLink})。", + "home.tutorials.postgresqlLogs.nameTitle": "PostgreSQL 日志", + "home.tutorials.postgresqlLogs.shortDescription": "收集并解析 PostgreSQL 创建的错误和慢查询日志。", + "home.tutorials.postgresqlMetrics.longDescription": "Metricbeat 模块 `postgresql` 从 PostgreSQL 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.postgresqlMetrics.nameTitle": "PostgreSQL 指标", + "home.tutorials.postgresqlMetrics.shortDescription": "从 PostgreSQL 提取内部指标。", + "home.tutorials.prometheusMetrics.artifacts.application.label": "Discover", + "home.tutorials.prometheusMetrics.longDescription": "Metricbeat 模块 `{moduleName}` 从 Prometheus 终端节点提取指标。[了解详情]({learnMoreLink})。", + "home.tutorials.prometheusMetrics.nameTitle": "Prometheus 指标", + "home.tutorials.prometheusMetrics.shortDescription": "从 Prometheus 导出器提取指标。", + "home.tutorials.rabbitmqMetrics.artifacts.dashboards.linkLabel": "RabbitMQ 指标仪表板", + "home.tutorials.rabbitmqMetrics.longDescription": "Metricbeat 模块 `rabbitmq` 从 RabbitMQ 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.rabbitmqMetrics.nameTitle": "RabbitMQ 指标", + "home.tutorials.rabbitmqMetrics.shortDescription": "从 RabbitMQ 服务器提取内部指标。", + "home.tutorials.redisLogs.artifacts.dashboards.linkLabel": "Redis 日志仪表板", + "home.tutorials.redisLogs.longDescription": "Filebeat 模块 `redis` 解析 Redis 创建的错误和慢查询日志。为了使 Redis 写入错误日志,确保 Redis 配置文件中的 `logfile` 选项设置为 `redis-server.log`。通过 `SLOWLOG` 命令可直接从 Redis 读取慢查询日志。为了使 Redis 记录慢查询日志,确保设置了 `slowlog-log-slower-than` 选项。请注意,`slowlog` 是实验性文件集。[了解详情]({learnMoreLink})。", + "home.tutorials.redisLogs.nameTitle": "Redis 日志", + "home.tutorials.redisLogs.shortDescription": "收集并解析 Redis 创建的错误和慢查询日志。", + "home.tutorials.redisMetrics.artifacts.dashboards.linkLabel": "Redis 指标仪表板", + "home.tutorials.redisMetrics.longDescription": "Metricbeat 模块 `redis` 从 Redis 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.redisMetrics.nameTitle": "Redis 指标", + "home.tutorials.redisMetrics.shortDescription": "从 Redis 提取内部指标。", + "home.tutorials.suricataLogs.artifacts.dashboards.linkLabel": "Suricata 日志仪表板", + "home.tutorials.suricataLogs.longDescription": "Filebeat 模块 `suricata` 从 [Suricata Eve JSON 输出](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html)收集日志。[了解详情]({learnMoreLink})。", + "home.tutorials.suricataLogs.nameTitle": "Suricata 日志", + "home.tutorials.suricataLogs.shortDescription": "收集 Suricata IDS/IPS/NSM 创建的结果日志。", + "home.tutorials.systemLogs.artifacts.dashboards.linkLabel": "系统日志仪表板", + "home.tutorials.systemLogs.longDescription": "Filebeat 模块 `system` 收集并解析常见 Unix/Linux 型分发的系统日志服务创建的日志。此模块在 Windows 上不可用。[了解详情]({learnMoreLink})。", + "home.tutorials.systemLogs.nameTitle": "系统日志", + "home.tutorials.systemLogs.shortDescription": "收集并解析本地 Syslog 服务器写入的日志。", + "home.tutorials.systemMetrics.artifacts.dashboards.linkLabel": "系统指标仪表板", + "home.tutorials.systemMetrics.longDescription": "Metricbeat 模块 `system` 从主机收集 CPU、内存、网络和磁盘统计信息。其收集系统范围的统计信息以及每个进程和文件系统的统计信息。[了解详情]({learnMoreLink})。", + "home.tutorials.systemMetrics.nameTitle": "系统指标", + "home.tutorials.systemMetrics.shortDescription": "从主机上收集 CPU、内存、网络和磁盘统计信息。", + "home.tutorials.traefikLogs.artifacts.dashboards.linkLabel": "Traefik 日志仪表板", + "home.tutorials.traefikLogs.longDescription": "Filebeat 模块 `traefik` 解析 Traefik 创建的访问日志。[了解详情]({learnMoreLink})。", + "home.tutorials.traefikLogs.nameTitle": "Traefik 日志", + "home.tutorials.traefikLogs.shortDescription": "收集和解析 Traefik 代理创建的访问日志。", + "home.tutorials.uptimeMonitors.artifacts.dashboards.linkLabel": "Uptime 应用", + "home.tutorials.uptimeMonitors.longDescription": "通过主动探测来监测服务的可用性。 通过给定 URL 列表,Heartbeat 仅仅询问:是否保持连接? [了解详情]({learnMoreLink})。", + "home.tutorials.uptimeMonitors.nameTitle": "运行时间监测", + "home.tutorials.uptimeMonitors.shortDescription": "监测服务的可用性", + "home.tutorials.uwsgiMetrics.artifacts.dashboards.linkLabel": "uWSGI 指标仪表板", + "home.tutorials.uwsgiMetrics.longDescription": "Metricbeat 模块 `uwsgi` 从 uWSGI 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.uwsgiMetrics.nameTitle": "uWSGI 指标", + "home.tutorials.uwsgiMetrics.shortDescription": "从 uWSGI 服务器提取内部指标。", + "home.tutorials.vsphereMetrics.artifacts.application.label": "Discover", + "home.tutorials.vsphereMetrics.longDescription": "Metricbeat 模块 `vsphere` 从 vSphere 集群提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.vsphereMetrics.nameTitle": "vSphere 指标", + "home.tutorials.vsphereMetrics.shortDescription": "从 vSphere 提取内部指标。", + "home.tutorials.windowsEventLogs.artifacts.application.label": "SIEM App", + "home.tutorials.windowsEventLogs.longDescription": "使用 Winlogbeat 从 Windows 事件日志收集日志。[了解详情]({learnMoreLink})。", + "home.tutorials.windowsEventLogs.nameTitle": "Windows 事件日志", + "home.tutorials.windowsEventLogs.shortDescription": "从 Windows 事件日志提取日志。", + "home.tutorials.windowsMetrics.artifacts.application.label": "Discover", + "home.tutorials.windowsMetrics.longDescription": "Metricbeat 模块 `windows` 从 Windows 提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.windowsMetrics.nameTitle": "Windows 指标", + "home.tutorials.windowsMetrics.shortDescription": "从 Windows 提取内部指标。", + "home.tutorials.zeekLogs.artifacts.dashboards.linkLabel": "Zeek 日志仪表板", + "home.tutorials.zeekLogs.longDescription": "Filebeat 模块 `zeek` 从 [Zeek](https://www.zeek.org//documentation/index.html) 收集日志。[了解详情]({learnMoreLink})。", + "home.tutorials.zeekLogs.nameTitle": "Zeek 日志", + "home.tutorials.zeekLogs.shortDescription": "收集 Zeek/Bro 创建的日志。", + "home.tutorials.zookeeperMetrics.artifacts.application.label": "Discover", + "home.tutorials.zookeeperMetrics.longDescription": "Metricbeat 模块 `{moduleName}` 从 Zookeeper 服务器提取内部指标。[了解详情]({learnMoreLink})。", + "home.tutorials.zookeeperMetrics.nameTitle": "Zookeeper 指标", + "home.tutorials.zookeeperMetrics.shortDescription": "从 Zookeeper 服务器提取内部指标。", + "visTypeVislib.area.areaDescription": "突出折线图下方的数量", + "visTypeVislib.area.areaTitle": "面积图", + "visTypeVislib.area.countText": "计数", + "visTypeVislib.area.groupTitle": "拆分序列", + "visTypeVislib.area.metricsTitle": "Y 轴", + "visTypeVislib.area.radiusTitle": "点大小", + "visTypeVislib.area.segmentTitle": "X 轴", + "visTypeVislib.area.splitTitle": "拆分图表", + "visTypeVislib.area.tabs.metricsAxesTitle": "指标和轴", + "visTypeVislib.area.tabs.panelSettingsTitle": "面板设置", + "visTypeVislib.axisModes.normalText": "正常", + "visTypeVislib.axisModes.percentageText": "百分比", + "visTypeVislib.axisModes.silhouetteText": "剪影", + "visTypeVislib.axisModes.wiggleText": "扭动", + "visTypeVislib.categoryAxis.rotate.angledText": "带角度", + "visTypeVislib.categoryAxis.rotate.horizontalText": "水平", + "visTypeVislib.categoryAxis.rotate.verticalText": "垂直", + "visTypeVislib.chartModes.normalText": "正常", + "visTypeVislib.chartModes.stackedText": "堆叠", + "visTypeVislib.chartTypes.areaText": "面积图", + "visTypeVislib.chartTypes.barText": "条形图", + "visTypeVislib.chartTypes.lineText": "折线图", + "visTypeVislib.controls.colorRanges.errorText": "每个范围应大于前一范围。", + "visTypeVislib.controls.colorSchema.colorSchemaLabel": "颜色模式", + "visTypeVislib.controls.colorSchema.howToChangeColorsDescription": "可以更改图例中的各个颜色。", + "visTypeVislib.controls.colorSchema.resetColorsButtonLabel": "重置颜色", + "visTypeVislib.controls.colorSchema.reverseColorSchemaLabel": "反转模式", + "visTypeVislib.controls.gaugeOptions.alignmentLabel": "对齐方式", + "visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "自动扩展范围", + "visTypeVislib.controls.gaugeOptions.displayWarningsLabel": "显示警告", + "visTypeVislib.controls.gaugeOptions.extendRangeTooltip": "将数据范围扩展到最大值。", + "visTypeVislib.controls.gaugeOptions.gaugeTypeLabel": "仪表类型", + "visTypeVislib.controls.gaugeOptions.labelsTitle": "标签", + "visTypeVislib.controls.gaugeOptions.percentageModeLabel": "百分比模式", + "visTypeVislib.controls.gaugeOptions.rangesTitle": "范围", + "visTypeVislib.controls.gaugeOptions.showLabelsLabel": "显示标签", + "visTypeVislib.controls.gaugeOptions.showLegendLabel": "显示图例", + "visTypeVislib.controls.gaugeOptions.showScaleLabel": "显示比例", + "visTypeVislib.controls.gaugeOptions.styleTitle": "样式", + "visTypeVislib.controls.gaugeOptions.subTextLabel": "子标签", + "visTypeVislib.controls.gaugeOptions.switchWarningsTooltip": "打开/关闭警告。打开时,如果标签没有全部显示,则显示警告。", + "visTypeVislib.controls.heatmapOptions.colorLabel": "颜色", + "visTypeVislib.controls.heatmapOptions.colorScaleLabel": "色阶", + "visTypeVislib.controls.heatmapOptions.colorsNumberLabel": "颜色个数", + "visTypeVislib.controls.heatmapOptions.labelsTitle": "标签", + "visTypeVislib.controls.heatmapOptions.overwriteAutomaticColorLabel": "覆盖自动配色", + "visTypeVislib.controls.heatmapOptions.percentageModeLabel": "百分比模式", + "visTypeVislib.controls.heatmapOptions.rotateLabel": "旋转", + "visTypeVislib.controls.heatmapOptions.scaleToDataBoundsLabel": "缩放到数据边界", + "visTypeVislib.controls.heatmapOptions.showLabelsTitle": "显示标签", + "visTypeVislib.controls.heatmapOptions.useCustomRangesLabel": "使用定制范围", + "visTypeVislib.controls.pointSeries.categoryAxis.alignLabel": "对齐", + "visTypeVislib.controls.pointSeries.categoryAxis.filterLabelsLabel": "筛选标签", + "visTypeVislib.controls.pointSeries.categoryAxis.labelsTitle": "标签", + "visTypeVislib.controls.pointSeries.categoryAxis.positionLabel": "位置", + "visTypeVislib.controls.pointSeries.categoryAxis.showLabel": "显示", + "visTypeVislib.controls.pointSeries.categoryAxis.showLabelsLabel": "显示标签", + "visTypeVislib.controls.pointSeries.categoryAxis.xAxisTitle": "X 轴", + "visTypeVislib.controls.pointSeries.gridAxis.dontShowLabel": "不显示", + "visTypeVislib.controls.pointSeries.gridAxis.gridText": "网格", + "visTypeVislib.controls.pointSeries.gridAxis.xAxisLinesLabel": "显示 X 轴线", + "visTypeVislib.controls.pointSeries.gridAxis.yAxisLinesDisabledTooltip": "直方图的 X 轴线无法显示。", + "visTypeVislib.controls.pointSeries.gridAxis.yAxisLinesLabel": "Y 轴线", + "visTypeVislib.controls.pointSeries.series.chartTypeLabel": "图表类型", + "visTypeVislib.controls.pointSeries.series.lineModeLabel": "线条模式", + "visTypeVislib.controls.pointSeries.series.lineWidthLabel": "线条宽度", + "visTypeVislib.controls.pointSeries.series.metricsTitle": "指标", + "visTypeVislib.controls.pointSeries.series.modeLabel": "模式", + "visTypeVislib.controls.pointSeries.series.newAxisLabel": "新建轴…...", + "visTypeVislib.controls.pointSeries.series.showDotsLabel": "显示点线", + "visTypeVislib.controls.pointSeries.series.showLineLabel": "显示为线条", + "visTypeVislib.controls.pointSeries.series.valueAxisLabel": "值轴", + "visTypeVislib.controls.pointSeries.seriesAccordionAriaLabel": "切换 {agg} 选项", + "visTypeVislib.controls.pointSeries.valueAxes.addButtonTooltip": "添加 Y 轴", + "visTypeVislib.controls.pointSeries.valueAxes.customExtentsLabel": "定制范围", + "visTypeVislib.controls.pointSeries.valueAxes.maxLabel": "最大值", + "visTypeVislib.controls.pointSeries.valueAxes.minErrorMessage": "最小值应小于最大值。", + "visTypeVislib.controls.pointSeries.valueAxes.minLabel": "最小值", + "visTypeVislib.controls.pointSeries.valueAxes.minNeededScaleText": "如果选择了对数刻度,最小值必须大于 0。", + "visTypeVislib.controls.pointSeries.valueAxes.modeLabel": "模式", + "visTypeVislib.controls.pointSeries.valueAxes.positionLabel": "位置", + "visTypeVislib.controls.pointSeries.valueAxes.removeButtonTooltip": "移除 Y 轴", + "visTypeVislib.controls.pointSeries.valueAxes.scaleToDataBounds.boundsMargin": "边界边距", + "visTypeVislib.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin": "边界边距必须大于或等于 0。", + "visTypeVislib.controls.pointSeries.valueAxes.scaleToDataBoundsLabel": "缩放到数据边界", + "visTypeVislib.controls.pointSeries.valueAxes.scaleTypeLabel": "缩放类型", + "visTypeVislib.controls.pointSeries.valueAxes.setAxisExtentsLabel": "设置轴范围", + "visTypeVislib.controls.pointSeries.valueAxes.showLabel": "显示", + "visTypeVislib.controls.pointSeries.valueAxes.titleLabel": "标题", + "visTypeVislib.controls.pointSeries.valueAxes.toggleCustomExtendsAriaLabel": "切换定制范围", + "visTypeVislib.controls.pointSeries.valueAxes.toggleOptionsAriaLabel": "切换 {axisName} 选项", + "visTypeVislib.controls.pointSeries.valueAxes.yAxisTitle": "Y 轴", + "visTypeVislib.controls.rangeErrorMessage": "值必须是在 {min} 到 {max} 的范围内", + "visTypeVislib.controls.truncateLabel": "截断", + "visTypeVislib.controls.vislibBasicOptions.legendPositionLabel": "图例位置", + "visTypeVislib.controls.vislibBasicOptions.showTooltipLabel": "显示工具提示", + "visTypeVislib.editors.heatmap.basicSettingsTitle": "基本设置", + "visTypeVislib.editors.heatmap.heatmapSettingsTitle": "热图设置", + "visTypeVislib.editors.heatmap.highlightLabel": "高亮范围", + "visTypeVislib.vislib.heatmap.maxBucketsText": "定义了过多的序列 ({nr})。配置的最大值为 {max}。", + "visTypeVislib.editors.heatmap.highlightLabelTooltip": "高亮显示图表中鼠标悬停的范围以及图例中对应的标签。", + "visTypeVislib.editors.pie.donutLabel": "圆环图", + "visTypeVislib.editors.pie.labelsSettingsTitle": "标签设置", + "visTypeVislib.editors.pie.pieSettingsTitle": "饼图设置", + "visTypeVislib.editors.pie.showLabelsLabel": "显示标签", + "visTypeVislib.editors.pie.showTopLevelOnlyLabel": "仅显示顶级", + "visTypeVislib.editors.pie.showValuesLabel": "显示值", + "visTypeVislib.editors.pointSeries.currentTimeMarkerLabel": "当前时间标记", + "visTypeVislib.editors.pointSeries.orderBucketsBySumLabel": "按总计值排序存储桶", + "visTypeVislib.editors.pointSeries.settingsTitle": "设置", + "visTypeVislib.editors.pointSeries.showLabels": "在图表上显示值", + "visTypeVislib.editors.pointSeries.thresholdLine.colorLabel": "线条颜色", + "visTypeVislib.editors.pointSeries.thresholdLine.showLabel": "显示阈值线条", + "visTypeVislib.editors.pointSeries.thresholdLine.styleLabel": "线条样式", + "visTypeVislib.editors.pointSeries.thresholdLine.valueLabel": "阈值", + "visTypeVislib.editors.pointSeries.thresholdLine.widthLabel": "线条宽度", + "visTypeVislib.editors.pointSeries.thresholdLineSettingsTitle": "阈值线条", + "visTypeVislib.functions.pie.help": "饼图可视化", + "visTypeVislib.functions.vislib.help": "Vislib 可视化", + "visTypeVislib.gauge.alignmentAutomaticTitle": "自动", + "visTypeVislib.gauge.alignmentHorizontalTitle": "水平", + "visTypeVislib.gauge.alignmentVerticalTitle": "垂直", + "visTypeVislib.gauge.gaugeDescription": "仪表盘图指示指标的状态。用于显示指标值与参考阈值的相关程度。", + "visTypeVislib.gauge.gaugeTitle": "仪表盘图", + "visTypeVislib.gauge.gaugeTypes.arcText": "弧形", + "visTypeVislib.gauge.gaugeTypes.circleText": "圆形", + "visTypeVislib.gauge.groupTitle": "拆分组", + "visTypeVislib.gauge.metricTitle": "指标", + "visTypeVislib.goal.goalDescription": "目标图指示与最终目标的接近程度。", + "visTypeVislib.goal.goalTitle": "目标图", + "visTypeVislib.goal.groupTitle": "拆分组", + "visTypeVislib.goal.metricTitle": "指标", + "visTypeVislib.heatmap.groupTitle": "Y 轴", + "visTypeVislib.heatmap.heatmapDescription": "为矩阵中的单元格添加阴影", + "visTypeVislib.heatmap.heatmapTitle": "热力图", + "visTypeVislib.heatmap.metricTitle": "值", + "visTypeVislib.heatmap.segmentTitle": "X 轴", + "visTypeVislib.heatmap.splitTitle": "拆分图表", + "visTypeVislib.histogram.groupTitle": "拆分序列", + "visTypeVislib.histogram.histogramDescription": "向每个轴赋予连续变量", + "visTypeVislib.histogram.histogramTitle": "垂直条形图", + "visTypeVislib.histogram.metricTitle": "Y 轴", + "visTypeVislib.histogram.radiusTitle": "点大小", + "visTypeVislib.histogram.segmentTitle": "X 轴", + "visTypeVislib.histogram.splitTitle": "拆分图表", + "visTypeVislib.horizontalBar.groupTitle": "拆分序列", + "visTypeVislib.horizontalBar.horizontalBarDescription": "向每个轴赋予连续变量", + "visTypeVislib.horizontalBar.horizontalBarTitle": "水平条形图", + "visTypeVislib.horizontalBar.metricTitle": "Y 轴", + "visTypeVislib.horizontalBar.radiusTitle": "点大小", + "visTypeVislib.horizontalBar.segmentTitle": "X 轴", + "visTypeVislib.horizontalBar.splitTitle": "拆分图表", + "visTypeVislib.interpolationModes.smoothedText": "平滑", + "visTypeVislib.interpolationModes.steppedText": "渐变", + "visTypeVislib.interpolationModes.straightText": "直线", + "visTypeVislib.legendPositions.bottomText": "下", + "visTypeVislib.legendPositions.leftText": "左", + "visTypeVislib.legendPositions.rightText": "右", + "visTypeVislib.legendPositions.topText": "上", + "visTypeVislib.line.groupTitle": "拆分序列", + "visTypeVislib.line.lineDescription": "突出趋势", + "visTypeVislib.line.lineTitle": "折线图", + "visTypeVislib.line.metricTitle": "Y 轴", + "visTypeVislib.line.radiusTitle": "点大小", + "visTypeVislib.line.segmentTitle": "X 轴", + "visTypeVislib.line.splitTitle": "拆分图表", + "visTypeVislib.pie.metricTitle": "切片大小", + "visTypeVislib.pie.pieDescription": "比较整体的各个部分", + "visTypeVislib.pie.pieTitle": "饼图", + "visTypeVislib.pie.segmentTitle": "拆分切片", + "visTypeVislib.pie.splitTitle": "拆分图表", + "visTypeVislib.scaleTypes.linearText": "线性", + "visTypeVislib.scaleTypes.logText": "对数", + "visTypeVislib.scaleTypes.squareRootText": "平方根", + "visTypeVislib.thresholdLine.style.dashedText": "虚线", + "visTypeVislib.thresholdLine.style.dotdashedText": "点虚线", + "visTypeVislib.thresholdLine.style.fullText": "实线", + "visTypeVislib.vislib.tooltip.fieldLabel": "フィールド", + "visTypeVislib.vislib.tooltip.valueLabel": "値", + "visTypeVislib.vislib.legend.filterForValueButtonAriaLabel": "筛留值 {legendDataLabel}", + "visTypeVislib.vislib.legend.filterOutValueButtonAriaLabel": "筛除值 {legendDataLabel}", + "visTypeVislib.vislib.legend.loadingLabel": "正在加载……", + "visTypeVislib.vislib.legend.setColorScreenReaderDescription": "为值 {legendDataLabel} 设置颜色", + "visTypeVislib.vislib.legend.toggleLegendButtonAriaLabel": "切换图例", + "visTypeVislib.vislib.legend.toggleLegendButtonTitle": "切换图例", + "visTypeVislib.vislib.legend.toggleOptionsButtonAriaLabel": "{legendDataLabel}切换选项", "kibana-react.exitFullScreenButton.exitFullScreenModeButtonLabel": "退出全屏", "kibana-react.exitFullScreenButton.fullScreenModeDescription": "在全屏模式下,按 ESC 键可退出。", "kibana-react.savedObjects.finder.filterButtonLabel": "类型", @@ -4137,6 +4027,112 @@ "xpack.apm.transactionsTable.notFoundLabel": "未找到任何事务。", "xpack.apm.transactionsTable.transactionsPerMinuteColumnLabel": "每分钟事务数", "xpack.apm.transactionsTable.transactionsPerMinuteUnitLabel": "tpm", + "xpack.apm.tutorial.apmAgents.statusCheck.btnLabel": "检查代理状态", + "xpack.apm.tutorial.apmAgents.statusCheck.errorMessage": "尚未从代理收到任何数据", + "xpack.apm.tutorial.apmAgents.statusCheck.successMessage": "从一个或多个代理成功接收数据", + "xpack.apm.tutorial.apmAgents.statusCheck.text": "确保您的应用程序正在运行且代理正在发送数据。", + "xpack.apm.tutorial.apmAgents.statusCheck.title": "代理状态", + "xpack.apm.tutorial.apmAgents.title": "APM 代理", + "xpack.apm.tutorial.apmServer.statusCheck.btnLabel": "检查 APM Server 状态", + "xpack.apm.tutorial.apmServer.statusCheck.errorMessage": "APM Server 仍未连接到 Elasticsearch", + "xpack.apm.tutorial.apmServer.statusCheck.successMessage": "您已正确设置 APM Server", + "xpack.apm.tutorial.apmServer.statusCheck.text": "在开始实施 APM 代理之前,确保 APM Server 正在运行。", + "xpack.apm.tutorial.apmServer.statusCheck.title": "APM Server 状态", + "xpack.apm.tutorial.apmServer.title": "APM Server", + "xpack.apm.tutorial.djangoClient.configure.commands.addAgentComment": "向已安装应用添加代理", + "xpack.apm.tutorial.djangoClient.configure.commands.addTracingMiddlewareComment": "要发送性能指标,请添加我们的跟踪中间件:", + "xpack.apm.tutorial.djangoClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_ 以及空格", + "xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment": "设置定制 APM Server URL(默认值:{defaultApmServerUrl})", + "xpack.apm.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment": "设置所需的服务名称。允许使用的字符:", + "xpack.apm.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server 需要令牌时使用", + "xpack.apm.tutorial.djangoClient.configure.textPost": "有关高级用法,请参阅[文档]({documentationLink})。", + "xpack.apm.tutorial.djangoClient.configure.textPre": "代理是在您的应用程序进程内运行的库。APM 服务是基于 `SERVICE_NAME` 以编程方式创建的。", + "xpack.apm.tutorial.djangoClient.configure.title": "配置代理", + "xpack.apm.tutorial.djangoClient.install.textPre": "将 Python 的 APM 代理安装为依赖项。", + "xpack.apm.tutorial.djangoClient.install.title": "安装 APM 代理", + "xpack.apm.tutorial.dotNetClient.configureAgent.textPost": "如果您未将 `IConfiguration` 实例传递给代理(例如非 ASP.NET Core 应用程序), 您还可以通过环境变量配置代理。\n 有关高级用法,请参阅[文档]({documentationLink})。", + "xpack.apm.tutorial.dotNetClient.configureAgent.title": "样例 appsettings.json 文件:", + "xpack.apm.tutorial.dotNetClient.configureApplication.textPost": "传递 `IConfiguration` 实例为可选操作,通过此操作,代理将通过此`IConfiguration` 实例 读取配置设置(例如,从 `appsettings.json` 文件)。", + "xpack.apm.tutorial.dotNetClient.configureApplication.textPre": "对于具有 `Elastic.Apm.NetCoreAll` 软件包的 ASP.NET Core,请在 `Startup.cs` 文件内的 `Configure` 方法中调用 `UseAllElasticApm`。", + "xpack.apm.tutorial.dotNetClient.configureApplication.title": "将代理添加到应用程序", + "xpack.apm.tutorial.dotNetClient.download.textPre": "将代理软件包从 [NuGet]({allNuGetPackagesLink}) 添加到 .NET 应用程序。有多个 NuGet 软件包可用于不同的用例。\n\n对于具有 Entity Framework Core 的 ASP.NET Core 应用程序,请下载 [Elastic.Apm.NetCoreAll]({netCoreAllApmPackageLink}) 软件包。此软件包将自动将每个 代理组件添加到您的应用程序。\n\n 如果您希望最大程度减少依存关系,您可以将 [Elastic.Apm.AspNetCore]({aspNetCorePackageLink}) 软件包仅用于 ASP.NET Core 监测,或将 [Elastic.Apm.EfCore]({efCorePackageLink}) 软件包仅用于 Entity Framework Core 监测。\n\n 如果仅希望将公共代理 API 用于手动检测,请使用 [Elastic.Apm]({elasticApmPackageLink}) 软件包。", + "xpack.apm.tutorial.dotNetClient.download.title": "下载 APM 代理", + "xpack.apm.tutorial.downloadServer.title": "下载并解压缩 APM Server", + "xpack.apm.tutorial.downloadServerRpm": "寻找 32 位软件包?请参阅[下载页面]({downloadPageLink})。", + "xpack.apm.tutorial.downloadServerTitle": "寻找 32 位软件包?请参阅[下载页面]({downloadPageLink})。", + "xpack.apm.tutorial.editConfig.textPre": "如果您正在使用 Elastic Stack 的 X-Pack 安全版本,则必须在 `apm-server.yml` 配置文件中指定凭据。", + "xpack.apm.tutorial.editConfig.title": "编辑配置", + "xpack.apm.tutorial.elasticCloud.textPre": "要启用 APM Server,请前往 [Elastic Cloud 控制台](https://cloud.elastic.co/deployments?q={cloudId}) 并在部署设置中启用 APM。启用后,请刷新此页面。", + "xpack.apm.tutorial.elasticCloudInstructions.title": "APM 代理", + "xpack.apm.tutorial.flaskClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_ 以及空格", + "xpack.apm.tutorial.flaskClient.configure.commands.configureElasticApmComment": "或进行配置以在您的应用程序设置中使用 ELASTIC_APM", + "xpack.apm.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment": "使用环境变量初始化", + "xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment": "设置定制 APM Server URL(默认值:{defaultApmServerUrl})", + "xpack.apm.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment": "设置所需的服务名称。允许使用的字符:", + "xpack.apm.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server 需要令牌时使用", + "xpack.apm.tutorial.flaskClient.configure.textPost": "有关高级用法,请参阅[文档]({documentationLink})。", + "xpack.apm.tutorial.flaskClient.configure.textPre": "代理是在您的应用程序进程内运行的库。APM 服务是基于 `SERVICE_NAME` 以编程方式创建的。", + "xpack.apm.tutorial.flaskClient.configure.title": "配置代理", + "xpack.apm.tutorial.flaskClient.install.textPre": "将 Python 的 APM 代理安装为依赖项。", + "xpack.apm.tutorial.flaskClient.install.title": "安装 APM 代理", + "xpack.apm.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment": "使用环境变量初始化:", + "xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment": "设置定制 APM Server URL(默认值:{defaultApmServerUrl})", + "xpack.apm.tutorial.goClient.configure.commands.setServiceNameComment": "设置服务名称。允许使用的字符:# a-z、A-Z、0-9、-、_ 和空格。", + "xpack.apm.tutorial.goClient.configure.commands.usedExecutableNameComment": "如果未指定 ELASTIC_APM_SERVICE_NAME,将会使用可执行文件名称。", + "xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment": "APM Server 需要令牌时使用", + "xpack.apm.tutorial.goClient.configure.textPost": "有关高级配置,请参阅[文档]({documentationLink})。", + "xpack.apm.tutorial.goClient.configure.textPre": "代理是在您的应用程序进程内运行的库。APM 服务将基于可执行文件名称或 `ELASTIC_APM_SERVICE_NAME` 环境变量以编程方式进行创建。", + "xpack.apm.tutorial.goClient.configure.title": "配置代理", + "xpack.apm.tutorial.goClient.install.textPre": "安装 Go 的 APM 代理软件包。", + "xpack.apm.tutorial.goClient.install.title": "安装 APM 代理", + "xpack.apm.tutorial.goClient.instrument.textPost": "有关检测 Go 源代码的详细指南,请参阅[文档]({documentationLink})。", + "xpack.apm.tutorial.goClient.instrument.textPre": "使用以下已提供检测模块之一或直接使用跟踪器 API 来检测 Go 应用程序。", + "xpack.apm.tutorial.goClient.instrument.title": "检测您的应用程序", + "xpack.apm.tutorial.introduction": "从您的应用程序内收集深入全面的性能指标和错误。", + "xpack.apm.tutorial.javaClient.download.textPre": "从 [Maven Central]({mavenCentralLink}) 下载代理 jar。**切勿**将该代理添加为您的应用程序的依赖项。", + "xpack.apm.tutorial.javaClient.download.title": "下载 APM 代理", + "xpack.apm.tutorial.javaClient.startApplication.textPost": "有关配置选项和高级用法,请参阅[文档]({documentationLink})。", + "xpack.apm.tutorial.javaClient.startApplication.textPre": "添加 `-javaagent` 标志并使用系统属性配置代理。\n\n * 设置所需的服务名称(允许使用的字符:a-z、A-Z、0-9、-、_ 和空格)\n * 设置定制 APM Server URL(默认值:{customApmServerUrl})\n * 设置您的应用程序的基础软件包", + "xpack.apm.tutorial.javaClient.startApplication.title": "使用 javaagent 标志设置您的应用程序", + "xpack.apm.tutorial.jsClient.enableRealUserMonitoring.textPre": "请参阅[文档]({documentationLink})。", + "xpack.apm.tutorial.jsClient.enableRealUserMonitoring.title": "在 APM 服务器中启用真实用户 Monitoring 支持", + "xpack.apm.tutorial.nodeClient.configure.commands.addThisToTheFileTopComment": "将其添加到您的应用中加载的第一个文件的上面", + "xpack.apm.tutorial.nodeClient.configure.commands.allowedCharactersComment": "允许使用的字符:a-z、A-Z、0-9、-、_ 和空格", + "xpack.apm.tutorial.nodeClient.configure.commands.setCustomApmServerUrlComment": "设置定制 APM Server URL(默认值:{defaultApmServerUrl})", + "xpack.apm.tutorial.nodeClient.configure.commands.setRequiredServiceNameComment": "覆盖来自 package.json 的服务名", + "xpack.apm.tutorial.nodeClient.configure.commands.useIfApmRequiresTokenComment": "APM Server 需要令牌时使用", + "xpack.apm.tutorial.nodeClient.configure.textPost": "请参阅[文档]({documentationLink})以了解高级用法,包括如何使用 [Babel/ES 模块]({babelEsModulesLink})。", + "xpack.apm.tutorial.nodeClient.configure.textPre": "代理是在您的应用程序进程内运行的库。APM 服务是基于 `serviceName` 以编程方式创建的。此代理支持各种框架,而且还可以与您的定制堆栈配合使用。", + "xpack.apm.tutorial.nodeClient.configure.title": "配置代理", + "xpack.apm.tutorial.nodeClient.install.textPre": "将 Node.js 的 APM 代理安装为您的应用程序的依赖项。", + "xpack.apm.tutorial.nodeClient.install.title": "安装 APM 代理", + "xpack.apm.tutorial.rackClient.configure.commands.optionalComment": "可选,默认为 config/elastic_apm.yml", + "xpack.apm.tutorial.rackClient.configure.commands.requiredComment": "必填", + "xpack.apm.tutorial.rackClient.configure.textPre": "对于 Rack 或兼容的框架(例如 Sinatra),在您的应用中加入中间件,然后启动代理。", + "xpack.apm.tutorial.rackClient.configure.title": "配置代理", + "xpack.apm.tutorial.rackClient.createConfig.commands.defaultsToTheNameOfRackAppClassComment": "默认为 Rack 应用的类名称。", + "xpack.apm.tutorial.rackClient.createConfig.commands.setCustomApmServerComment": "设置定制 APM Server URL(默认值:{defaultServerUrl})", + "xpack.apm.tutorial.rackClient.createConfig.commands.setServiceNameComment": "设置服务名称 - 允许使用的字符:a-z、A-Z、0-9、-、_ 和空格", + "xpack.apm.tutorial.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment": "APM Server 需要令牌时使用", + "xpack.apm.tutorial.rackClient.createConfig.textPost": "有关配置选项和高级用法,请参阅[文档]({documentationLink})。\n\n", + "xpack.apm.tutorial.rackClient.createConfig.textPre": "创建配置文件 {configFile}:", + "xpack.apm.tutorial.rackClient.createConfig.title": "创建配置文件", + "xpack.apm.tutorial.rackClient.install.textPre": "将代理添加您的 Gemfile。", + "xpack.apm.tutorial.rackClient.install.title": "安装 APM 代理", + "xpack.apm.tutorial.railsClient.configure.textPost": "有关配置选项和高级用法,请参阅[文档]({documentationLink})。\n\n", + "xpack.apm.tutorial.railsClient.configure.textPre": "您的应用启动时,APM 自动启动。通过创建配置文件 {configFile} 来配置代理", + "xpack.apm.tutorial.railsClient.configure.title": "配置代理", + "xpack.apm.tutorial.railsClient.install.textPre": "将代理添加您的 Gemfile。", + "xpack.apm.tutorial.railsClient.install.title": "安装 APM 代理", + "xpack.apm.tutorial.specProvider.artifacts.application.label": "启动 APM", + "xpack.apm.tutorial.specProvider.artifacts.dashboards.linkLabel": "APM 仪表板", + "xpack.apm.tutorial.specProvider.longDescription": "应用程序性能 Monitoring (APM) 从您的应用程序内收集深入全面的性能指标和错误。其允许您实时监测数以千计的应用程序的性能。[了解详情]({learnMoreLink})。", + "xpack.apm.tutorial.specProvider.name": "APM", + "xpack.apm.tutorial.specProvider.savedObjectsInstallMsg": "APM UI 中的某些功能需要 APM 索引模式。", + "xpack.apm.tutorial.startServer.textPre": "服务器在 Elasticsearch 中处理并存储应用程序性能指标。", + "xpack.apm.tutorial.startServer.title": "启动 APM Server", + "xpack.apm.tutorial.windowsServerInstructions.textPost": "注意:如果您的系统禁用了脚本执行,则需要为当前会话设置执行策略,以允许脚本运行。例如:{command}。", + "xpack.apm.tutorial.windowsServerInstructions.textPre": "1.从[下载页面]({downloadPageLink})下载 APM Server Windows zip 文件。\n2.将 zip 文件的内容解压缩到 {zipFileExtractFolder}。\n3.将 {apmServerDirectory} 目录重命名为 `APM-Server`。\n4.以管理员身份打开 PowerShell 提示符(右键单击 PowerShell 图标,然后选择**以管理员身份运行**)。如果您正在运行 Windows XP,您可能需要下载并安装 PowerShell。\n5.从 PowerShell 提示符处,运行以下命令以将 APM Server 安装为 Windows 服务:", "xpack.apm.waterfall.exceedsMax": "此跟踪中的项目数超过显示的项目数", "xpack.beatsManagement.beat.actionSectionTypeLabel": "类型:{beatType}。", "xpack.beatsManagement.beat.actionSectionVersionLabel": "版本:{beatVersion}。", @@ -5274,7 +5270,6 @@ "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyAriaLabel": "或者,也可以从脚本或使用 {URL} 通过 Watcher 生成 {PDF}。按 Enter 键可将 {URL} 复制到剪贴板。", "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyButtonLabel": "复制 {POST} {URL}", "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyDescription": "或者,复制此 {POST} {URL} 以从 {KIBANA} 外部或从 Watcher 调用生成。", - "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelDisabledDescription": "导出到 PDF 已禁用。必须配置报告,才能使用 Chromium 浏览器。将其添加到您的 {fileName} 文件中。", "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelGenerateButtonLabel": "生成 {PDF}", "xpack.canvas.workpadHeaderWorkpadExport.pdfPanelGenerateDescription": "{PDF} 可能会花费 1 或 2 分钟生成,取决于 Workpad 的大小。", "xpack.canvas.workpadHeaderWorkpadExport.shareDownloadJSONTitle": "下载为 {JSON}", @@ -5670,7 +5665,6 @@ "xpack.fileUpload.jsonIndexFilePicker.filePickerLabel": "选择文件进行上传", "xpack.fileUpload.jsonIndexFilePicker.fileProcessingError": "文件处理错误:{errorMessage}", "xpack.fileUpload.jsonIndexFilePicker.fileSizeError": "文件大小错误:{errorMessage}", - "xpack.fileUpload.jsonIndexFilePicker.formatsAccepted": "接受的格式:.json、.geojson", "xpack.fileUpload.jsonIndexFilePicker.maxSize": "最大大小:{maxFileSize}", "xpack.fileUpload.jsonIndexFilePicker.noFileNameError": "未提供任何文件名称", "xpack.fileUpload.jsonIndexFilePicker.parsingFile": "{featuresProcessed} 特征已解析......", @@ -6641,8 +6635,6 @@ "xpack.infra.metricsExplorer.openInTSVB": "在 Visualize 中打开", "xpack.infra.metricsExplorer.viewNodeDetail": "查看 {name} 的指标", "xpack.infra.node.ariaLabel": "{nodeName},单击打开菜单", - "xpack.infra.nodeContextMenu.viewLogsName": "查看日志", - "xpack.infra.nodeContextMenu.viewMetricsName": "查看指标", "xpack.infra.nodeDetails.labels.availabilityZone": "可用区", "xpack.infra.nodeDetails.labels.cloudProvider": "云服务提供商", "xpack.infra.nodeDetails.labels.containerized": "容器化", @@ -8244,7 +8236,6 @@ "xpack.ml.jobsList.startDatafeedModal.cancelButtonLabel": "取消", "xpack.ml.jobsList.startDatafeedModal.continueFromNowLabel": "从当前继续", "xpack.ml.jobsList.startDatafeedModal.continueFromSpecifiedTimeLabel": "从指定时间继续", - "xpack.ml.jobsList.startDatafeedModal.continueFromStartTimeLabel": "从 {formattedStartTime} 继续", "xpack.ml.jobsList.startDatafeedModal.createWatchDescription": "在数据馈送开始后创建监视", "xpack.ml.jobsList.startDatafeedModal.noEndTimeLabel": "无结束时间(实时搜索)", "xpack.ml.jobsList.startDatafeedModal.searchEndTimeTitle": "搜索结束时间", @@ -10498,7 +10489,6 @@ "xpack.searchProfiler.highlightDetails.totalTimeTooltip": "此查询组件花费的总时间(包括子项)", "xpack.searchProfiler.highlightDetails.typeTitle": "类型", "xpack.searchProfiler.licenseErrorMessageDescription": "分析器可视化需要有效的许可({licenseTypeList}或{platinumLicenseType},但在您的集群中未找到任何许可。", - "xpack.searchProfiler.licenseHasExpiredMessage": "Search Profiler 不可用 - 许可已过期。", "xpack.searchProfiler.pageDisplayName": "Search Profiler", "xpack.searchProfiler.platinumLicenseTitle": "白金级", "xpack.searchProfiler.profileTree.cumulativeTimeTitle": "累计时间:", @@ -10513,8 +10503,6 @@ "xpack.searchProfiler.registryProviderDescription": "快速检查任何 Elasticsearch 查询的性能。", "xpack.searchProfiler.registryProviderTitle": "Search Profiler", "xpack.searchProfiler.trialLicenseTitle": "试用", - "xpack.searchProfiler.unavailableLicenseInformationMessage": "Search Profiler 不可用 - 许可信息当前不可用。", - "xpack.searchProfiler.upgradeLicenseMessage": "Search Profiler 不可用于当前的{licenseInfo}许可。请升级您的许可。", "xpack.security.account.breadcrumb": "帐户管理", "xpack.security.account.changePasswordDescription": "为您的帐户更改密码。", "xpack.security.account.changePasswordForm.cancelButtonLabel": "重置", @@ -10594,17 +10582,6 @@ "xpack.security.management.apiKeys.table.userFilterLabel": "用户", "xpack.security.management.apiKeys.table.userNameColumnName": "用户", "xpack.security.management.apiKeysTitle": "API 密钥", - "xpack.security.management.changePasswordForm.cancelButtonLabel": "取消", - "xpack.security.management.changePasswordForm.changePasswordLinkLabel": "更改密码", - "xpack.security.management.changePasswordForm.confirmPasswordLabel": "确认密码", - "xpack.security.management.changePasswordForm.currentPasswordLabel": "当前密码", - "xpack.security.management.changePasswordForm.incorrectPasswordDescription": "您输入的当前密码不正确。", - "xpack.security.management.changePasswordForm.newPasswordLabel": "新密码", - "xpack.security.management.changePasswordForm.passwordDontMatchDescription": "密码不匹配", - "xpack.security.management.changePasswordForm.passwordLabel": "密码", - "xpack.security.management.changePasswordForm.passwordLengthDescription": "密码长度必须至少为 6 个字符", - "xpack.security.management.changePasswordForm.saveChangesButtonLabel": "保存更改", - "xpack.security.management.changePasswordForm.updateAndRestartKibanaDescription": "更改 Kibana 用户的密码后,必须更新 kibana.yml 文件并重新启动 Kibana", "xpack.security.management.editRole.cancelButtonLabel": "取消", "xpack.security.management.editRole.changeAllPrivilegesLink": "(全部更改)", "xpack.security.management.editRole.collapsiblePanel.hideLinkText": "隐藏", @@ -10729,10 +10706,6 @@ "xpack.security.management.editRolespacePrivilegeForm.createPrivilegeButton": "创建工作区权限", "xpack.security.management.editRolespacePrivilegeForm.updateGlobalPrivilegeButton": "更新全局权限", "xpack.security.management.editRolespacePrivilegeForm.updatePrivilegeButton": "更新工作区权限", - "xpack.security.management.passwordForm.confirmPasswordLabel": "确认密码", - "xpack.security.management.passwordForm.passwordDontMatchDescription": "密码不匹配", - "xpack.security.management.passwordForm.passwordLabel": "密码", - "xpack.security.management.passwordForm.passwordLengthDescription": "密码长度必须至少为 6 个字符", "xpack.security.management.roles.actionsColumnName": "鎿嶄綔", "xpack.security.management.roles.cloneRoleActionName": "克隆 {roleName}", "xpack.security.management.roles.confirmDelete.cancelButtonLabel": "取消", @@ -11058,6 +11031,8 @@ "xpack.siem.dataProviders.toggle": "切换", "xpack.siem.dataProviders.valueAriaLabel": "值", "xpack.siem.dataProviders.valuePlaceholder": "值", + "xpack.siem.detectionEngine.headerPage.pageBadgeLabel": "公测版", + "xpack.siem.detectionEngine.headerPage.pageBadgeTooltip": "SIEM 仍为公测版。请通过在 Kibana 报告中报告问题或错误,帮助我们改进产品。", "xpack.siem.draggables.field.categoryLabel": "类别", "xpack.siem.draggables.field.fieldLabel": "字段", "xpack.siem.draggables.field.typeLabel": "类型", @@ -11355,8 +11330,6 @@ "xpack.siem.overview.packetBeatDnsTitle": "Packetbeat DNS", "xpack.siem.overview.packetBeatFlowTitle": "Packetbeat 流", "xpack.siem.overview.packetbeatTLSTitle": "Packetbeat TLS", - "xpack.siem.overview.pageBadgeLabel": "公测版", - "xpack.siem.overview.pageBadgeTooltip": "SIEM 仍为公测版。请通过在 Kibana 报告中报告问题或错误,帮助我们改进产品。", "xpack.siem.overview.pageSubtitle": "Elastic Stack 的安全信息和事件管理功能", "xpack.siem.overview.pageTitle": "SIEM", "xpack.siem.overview.startedText": "欢迎使用安全信息和事件管理 (SIEM)。首先,查看我们的 {docs} 或 {data}。有关即将推出的功能和教程,确保查看我们的{siemSolution}页。", @@ -11364,7 +11337,6 @@ "xpack.siem.overview.startedText.docsLinkText": "文档", "xpack.siem.overview.startedText.siemSolutionLinkText": "SIEM 解决方案", "xpack.siem.overview.startedTitle": "入门", - "xpack.siem.overview.winlogbeatTitle": "Winlogbeat", "xpack.siem.pages.fourohfour.noContentFoundDescription": "未找到任何内容", "xpack.siem.paginatedTable.rowsButtonLabel": "每页行数", "xpack.siem.paginatedTable.showingSubtitle": "显示", @@ -12911,7 +12883,6 @@ "xpack.watcher.deleteSelectedWatchesConfirmModal.deleteButtonLabel": "删除 {numWatchesToDelete, plural, one {个监视} other {# 个监视}} ", "xpack.watcher.deleteSelectedWatchesConfirmModal.descriptionText": "无法恢复{numWatchesToDelete, plural, one {已删除监视} other {已删除监视}}。", "xpack.watcher.models.actionStatus.actionStatusJsonPropertyMissingBadRequestMessage": "JSON 参数必须包含“{missingProperty}”属性", - "xpack.watcher.models.actionStatus.notDetermineActionStatusBadImplementationMessage": "无法确定操作状态;操作 = {actionStatusJson}", "xpack.watcher.models.baseAction.selectMessageText": "执行操作。", "xpack.watcher.models.baseAction.simulateButtonLabel": "立即模拟此操作", "xpack.watcher.models.baseAction.simulateMessage": "已成功模拟操作 {id}", @@ -13173,11 +13144,7 @@ "xpack.watcher.sections.watchList.errorTitle": "加载监视时出错", "xpack.watcher.sections.watchList.header": "创建阈值告警", "xpack.watcher.sections.watchList.loadingWatchesDescription": "正在加载监视……", - "xpack.watcher.sections.watchList.managementSection.editDisplayName": "编辑", - "xpack.watcher.sections.watchList.managementSection.newWatchDisplayName": "新建监视", - "xpack.watcher.sections.watchList.managementSection.statusDisplayName": "状态", "xpack.watcher.sections.watchList.managementSection.watcherDisplayName": "Watcher", - "xpack.watcher.sections.watchList.managementSection.watchesDisplayName": "监视", "xpack.watcher.sections.watchList.subhead": "特定参数命中时,发出电子邮件、Slack 消息和日志事件", "xpack.watcher.sections.watchList.toggleActivatationErrorNotification.activateDescriptionText": "无法激活监视", "xpack.watcher.sections.watchList.toggleActivatationErrorNotification.deactivateDescriptionText": "无法停用监视", @@ -13233,4 +13200,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} +} \ No newline at end of file diff --git a/x-pack/legacy/plugins/watcher/README.md b/x-pack/plugins/watcher/README.md similarity index 100% rename from x-pack/legacy/plugins/watcher/README.md rename to x-pack/plugins/watcher/README.md diff --git a/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx new file mode 100644 index 00000000000000..f0a2816dd57b16 --- /dev/null +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/app_context.mock.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { of } from 'rxjs'; +import { ComponentType } from 'enzyme'; +import { + chromeServiceMock, + docLinksServiceMock, + uiSettingsServiceMock, + notificationServiceMock, + httpServiceMock, +} from '../../../../../../src/core/public/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { AppContextProvider } from '../../../public/application/app_context'; +import { LicenseStatus } from '../../../common/types/license_status'; + +class MockTimeBuckets { + setBounds(_domain: any) { + return {}; + } + getInterval() { + return { + expression: {}, + }; + } +} +export const mockContextValue = { + licenseStatus$: of({ valid: true }), + docLinks: docLinksServiceMock.createStartContract(), + chrome: chromeServiceMock.createStartContract(), + MANAGEMENT_BREADCRUMB: { text: 'test' }, + createTimeBuckets: () => new MockTimeBuckets(), + uiSettings: uiSettingsServiceMock.createSetupContract(), + toasts: notificationServiceMock.createSetupContract().toasts, + euiUtils: { + useChartsTheme: jest.fn(), + }, + // For our test harness, we don't use this mocked out http service + http: httpServiceMock.createSetupContract(), +}; + +export const withAppContext = (Component: ComponentType) => (props: any) => { + return ( + + + + ); +}; diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/body_response.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/body_response.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/body_response.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/body_response.ts diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/constants.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/constants.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/constants.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/constants.ts diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/http_requests.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/http_requests.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/http_requests.ts diff --git a/x-pack/plugins/watcher/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/index.ts new file mode 100644 index 00000000000000..7c5ec0917494ad --- /dev/null +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { setup as watchListSetup } from './watch_list.helpers'; +import { setup as watchStatusSetup } from './watch_status.helpers'; +import { setup as watchCreateJsonSetup } from './watch_create_json.helpers'; +import { setup as watchCreateThresholdSetup } from './watch_create_threshold.helpers'; +import { setup as watchEditSetup } from './watch_edit.helpers'; + +export { nextTick, getRandomString, findTestSubject, TestBed } from '../../../../../test_utils'; +export { wrapBodyResponse, unwrapBodyResponse } from './body_response'; +export { setupEnvironment } from './setup_environment'; + +export const pageHelpers = { + watchList: { setup: watchListSetup }, + watchStatus: { setup: watchStatusSetup }, + watchCreateJson: { setup: watchCreateJsonSetup }, + watchCreateThreshold: { setup: watchCreateThresholdSetup }, + watchEdit: { setup: watchEditSetup }, +}; diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/setup_environment.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/setup_environment.ts similarity index 92% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/setup_environment.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/setup_environment.ts index 7e748073c1c6b2..c084f87ea8c3ad 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/setup_environment.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/setup_environment.ts @@ -7,7 +7,8 @@ import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import { init as initHttpRequests } from './http_requests'; -import { setHttpClient, setSavedObjectsClient } from '../../../public/np_ready/application/lib/api'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setHttpClient, setSavedObjectsClient } from '../../../public/application/lib/api'; const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); mockHttpClient.interceptors.response.use( diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_create_json.helpers.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_create_json.helpers.ts similarity index 87% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_create_json.helpers.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_create_json.helpers.ts index dafcf3a7070d22..77d5a76257fd2d 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_create_json.helpers.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_create_json.helpers.ts @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ import { withAppContext } from './app_context.mock'; -import { registerTestBed, TestBed, TestBedConfig } from '../../../../../../test_utils'; -import { WatchEdit } from '../../../public/np_ready/application/sections/watch_edit/components/watch_edit'; +import { registerTestBed, TestBed, TestBedConfig } from '../../../../../test_utils'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { WatchEdit } from '../../../public/application/sections/watch_edit/components/watch_edit'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { registerRouter } from '../../../public/application/lib/navigation'; import { ROUTES, WATCH_TYPES } from '../../../common/constants'; -import { registerRouter } from '../../../public/np_ready/application/lib/navigation'; const testBedConfig: TestBedConfig = { memoryRouter: { diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_create_threshold.helpers.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_create_threshold.helpers.ts similarity index 90% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_create_threshold.helpers.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_create_threshold.helpers.ts index 65648ae5f5a959..8262e6702be700 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_create_threshold.helpers.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_create_threshold.helpers.ts @@ -3,10 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed, TestBed, TestBedConfig } from '../../../../../../test_utils'; -import { WatchEdit } from '../../../public/np_ready/application/sections/watch_edit/components/watch_edit'; +import { registerTestBed, TestBed, TestBedConfig } from '../../../../../test_utils'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { WatchEdit } from '../../../public/application/sections/watch_edit/components/watch_edit'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { registerRouter } from '../../../public/application/lib/navigation'; import { ROUTES, WATCH_TYPES } from '../../../common/constants'; -import { registerRouter } from '../../../public/np_ready/application/lib/navigation'; import { withAppContext } from './app_context.mock'; const testBedConfig: TestBedConfig = { diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_edit.helpers.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_edit.helpers.ts similarity index 81% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_edit.helpers.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_edit.helpers.ts index 187f4dcaa0a76f..949d43e7742123 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_edit.helpers.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_edit.helpers.ts @@ -3,10 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed, TestBed, TestBedConfig } from '../../../../../../test_utils'; -import { WatchEdit } from '../../../public/np_ready/application/sections/watch_edit/components/watch_edit'; +import { registerTestBed, TestBed, TestBedConfig } from '../../../../../test_utils'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { WatchEdit } from '../../../public/application/sections/watch_edit/components/watch_edit'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { registerRouter } from '../../../public/application/lib/navigation'; import { ROUTES } from '../../../common/constants'; -import { registerRouter } from '../../../public/np_ready/application/lib/navigation'; import { WATCH_ID } from './constants'; import { withAppContext } from './app_context.mock'; diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_list.helpers.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_list.helpers.ts similarity index 93% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_list.helpers.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_list.helpers.ts index e33327ea42ffe8..b5cf3df9509fc7 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_list.helpers.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_list.helpers.ts @@ -12,8 +12,9 @@ import { TestBed, TestBedConfig, nextTick, -} from '../../../../../../test_utils'; -import { WatchList } from '../../../public/np_ready/application/sections/watch_list/components/watch_list'; +} from '../../../../../test_utils'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { WatchList } from '../../../public/application/sections/watch_list/components/watch_list'; import { ROUTES } from '../../../common/constants'; import { withAppContext } from './app_context.mock'; diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_status.helpers.ts b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_status.helpers.ts similarity index 95% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_status.helpers.ts rename to x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_status.helpers.ts index e7bffe8924e319..e67c98ff9e9a0c 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/helpers/watch_status.helpers.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/helpers/watch_status.helpers.ts @@ -12,8 +12,9 @@ import { TestBed, TestBedConfig, nextTick, -} from '../../../../../../test_utils'; -import { WatchStatus } from '../../../public/np_ready/application/sections/watch_status/components/watch_status'; +} from '../../../../../test_utils'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { WatchStatus } from '../../../public/application/sections/watch_status/components/watch_status'; import { ROUTES } from '../../../common/constants'; import { WATCH_ID } from './constants'; import { withAppContext } from './app_context.mock'; diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts similarity index 98% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts rename to x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts index 4c893978ee5cbc..26be3421b534ed 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts @@ -7,7 +7,7 @@ import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers'; import { WatchCreateJsonTestBed } from './helpers/watch_create_json.helpers'; import { WATCH } from './helpers/constants'; -import defaultWatchJson from '../../public/np_ready/application/models/watch/default_watch.json'; +import defaultWatchJson from '../../public/application/models/watch/default_watch.json'; import { getExecuteDetails } from '../../test/fixtures'; const { setup } = pageHelpers.watchCreateJson; diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx similarity index 99% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx rename to x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx index 2800b0107da240..431eb1cae0608a 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx @@ -48,8 +48,8 @@ const WATCH_VISUALIZE_DATA = { const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); -jest.mock('../../public/np_ready/application/lib/api', () => ({ - ...jest.requireActual('../../public/np_ready/application/lib/api'), +jest.mock('../../public/application/lib/api', () => ({ + ...jest.requireActual('../../public/application/lib/api'), loadIndexPatterns: async () => { const INDEX_PATTERNS = [ { attributes: { title: 'index1' } }, diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_edit.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts similarity index 95% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_edit.test.ts rename to x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts index 131400a8702c46..545bfbdf7cbc28 100644 --- a/x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_edit.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts @@ -9,14 +9,14 @@ import axios from 'axios'; import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers'; import { WatchEditTestBed } from './helpers/watch_edit.helpers'; import { WATCH } from './helpers/constants'; -import defaultWatchJson from '../../public/np_ready/application/models/watch/default_watch.json'; +import defaultWatchJson from '../../public/application/models/watch/default_watch.json'; import { getWatch } from '../../test/fixtures'; -import { getRandomString } from '../../../../../test_utils'; +import { getRandomString } from '../../../../test_utils'; const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); -jest.mock('../../public/np_ready/application/lib/api', () => ({ - ...jest.requireActual('../../public/np_ready/application/lib/api'), +jest.mock('../../public/application/lib/api', () => ({ + ...jest.requireActual('../../public/application/lib/api'), loadIndexPatterns: async () => { const INDEX_PATTERNS = [ { attributes: { title: 'index1' } }, diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_list.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_list.test.ts rename to x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts diff --git a/x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_status.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/__jest__/client_integration/watch_status.test.ts rename to x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/action_modes.ts b/x-pack/plugins/watcher/common/constants/action_modes.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/action_modes.ts rename to x-pack/plugins/watcher/common/constants/action_modes.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/action_states.ts b/x-pack/plugins/watcher/common/constants/action_states.ts similarity index 87% rename from x-pack/legacy/plugins/watcher/common/constants/action_states.ts rename to x-pack/plugins/watcher/common/constants/action_states.ts index e9501fc2a60c4e..ac4da650463f84 100644 --- a/x-pack/legacy/plugins/watcher/common/constants/action_states.ts +++ b/x-pack/plugins/watcher/common/constants/action_states.ts @@ -36,4 +36,9 @@ export const ACTION_STATES: { [key: string]: string } = { CONFIG_ERROR: i18n.translate('xpack.watcher.constants.actionStates.configErrorStateText', { defaultMessage: 'Config error', }), + + // Action status is unknown; we should never end up in this state + UNKNOWN: i18n.translate('xpack.watcher.constants.actionStates.unknownStateText', { + defaultMessage: 'Unknown', + }), }; diff --git a/x-pack/legacy/plugins/watcher/common/constants/action_types.ts b/x-pack/plugins/watcher/common/constants/action_types.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/action_types.ts rename to x-pack/plugins/watcher/common/constants/action_types.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/agg_types.ts b/x-pack/plugins/watcher/common/constants/agg_types.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/agg_types.ts rename to x-pack/plugins/watcher/common/constants/agg_types.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/comparators.ts b/x-pack/plugins/watcher/common/constants/comparators.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/comparators.ts rename to x-pack/plugins/watcher/common/constants/comparators.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/error_codes.ts b/x-pack/plugins/watcher/common/constants/error_codes.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/error_codes.ts rename to x-pack/plugins/watcher/common/constants/error_codes.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/es_scroll_settings.ts b/x-pack/plugins/watcher/common/constants/es_scroll_settings.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/es_scroll_settings.ts rename to x-pack/plugins/watcher/common/constants/es_scroll_settings.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/index.ts b/x-pack/plugins/watcher/common/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/index.ts rename to x-pack/plugins/watcher/common/constants/index.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/index_names.ts b/x-pack/plugins/watcher/common/constants/index_names.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/index_names.ts rename to x-pack/plugins/watcher/common/constants/index_names.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/lists.ts b/x-pack/plugins/watcher/common/constants/lists.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/lists.ts rename to x-pack/plugins/watcher/common/constants/lists.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/pagination.ts b/x-pack/plugins/watcher/common/constants/pagination.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/pagination.ts rename to x-pack/plugins/watcher/common/constants/pagination.ts diff --git a/x-pack/plugins/watcher/common/constants/plugin.ts b/x-pack/plugins/watcher/common/constants/plugin.ts new file mode 100644 index 00000000000000..f89ef95e9261f5 --- /dev/null +++ b/x-pack/plugins/watcher/common/constants/plugin.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { LICENSE_TYPE_GOLD, LicenseType } from '../../../../legacy/common/constants'; + +export const PLUGIN = { + ID: 'watcher', + MINIMUM_LICENSE_REQUIRED: LICENSE_TYPE_GOLD as LicenseType, + getI18nName: (i18n: any): string => { + return i18n.translate('xpack.watcher.appName', { + defaultMessage: 'Watcher', + }); + }, +}; diff --git a/x-pack/legacy/plugins/watcher/common/constants/refresh_intervals.ts b/x-pack/plugins/watcher/common/constants/refresh_intervals.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/refresh_intervals.ts rename to x-pack/plugins/watcher/common/constants/refresh_intervals.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/routes.ts b/x-pack/plugins/watcher/common/constants/routes.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/routes.ts rename to x-pack/plugins/watcher/common/constants/routes.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/sort_orders.ts b/x-pack/plugins/watcher/common/constants/sort_orders.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/sort_orders.ts rename to x-pack/plugins/watcher/common/constants/sort_orders.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/time_units.ts b/x-pack/plugins/watcher/common/constants/time_units.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/time_units.ts rename to x-pack/plugins/watcher/common/constants/time_units.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/watch_history.ts b/x-pack/plugins/watcher/common/constants/watch_history.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/watch_history.ts rename to x-pack/plugins/watcher/common/constants/watch_history.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/watch_state_comments.ts b/x-pack/plugins/watcher/common/constants/watch_state_comments.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/watch_state_comments.ts rename to x-pack/plugins/watcher/common/constants/watch_state_comments.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/watch_states.ts b/x-pack/plugins/watcher/common/constants/watch_states.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/watch_states.ts rename to x-pack/plugins/watcher/common/constants/watch_states.ts diff --git a/x-pack/legacy/plugins/watcher/common/constants/watch_types.ts b/x-pack/plugins/watcher/common/constants/watch_types.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/constants/watch_types.ts rename to x-pack/plugins/watcher/common/constants/watch_types.ts diff --git a/x-pack/legacy/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js b/x-pack/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js similarity index 97% rename from x-pack/legacy/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js rename to x-pack/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js index 164bbab285fce4..1410488ee64131 100644 --- a/x-pack/legacy/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js +++ b/x-pack/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js @@ -6,7 +6,7 @@ import expect from '@kbn/expect'; import { getActionType } from '../get_action_type'; -import { ACTION_TYPES } from '../../../../common/constants'; +import { ACTION_TYPES } from '../../../constants'; describe('get_action_type', () => { describe('getActionType', () => { diff --git a/x-pack/legacy/plugins/watcher/common/lib/get_action_type/get_action_type.ts b/x-pack/plugins/watcher/common/lib/get_action_type/get_action_type.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/get_action_type/get_action_type.ts rename to x-pack/plugins/watcher/common/lib/get_action_type/get_action_type.ts diff --git a/x-pack/legacy/plugins/watcher/common/lib/get_action_type/index.ts b/x-pack/plugins/watcher/common/lib/get_action_type/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/get_action_type/index.ts rename to x-pack/plugins/watcher/common/lib/get_action_type/index.ts diff --git a/x-pack/legacy/plugins/watcher/common/lib/get_moment/__tests__/get_moment.js b/x-pack/plugins/watcher/common/lib/get_moment/__tests__/get_moment.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/get_moment/__tests__/get_moment.js rename to x-pack/plugins/watcher/common/lib/get_moment/__tests__/get_moment.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/get_moment/get_moment.js b/x-pack/plugins/watcher/common/lib/get_moment/get_moment.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/get_moment/get_moment.js rename to x-pack/plugins/watcher/common/lib/get_moment/get_moment.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/get_moment/index.js b/x-pack/plugins/watcher/common/lib/get_moment/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/get_moment/index.js rename to x-pack/plugins/watcher/common/lib/get_moment/index.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/index.d.ts b/x-pack/plugins/watcher/common/lib/serialization/index.d.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/index.d.ts rename to x-pack/plugins/watcher/common/lib/serialization/index.d.ts diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/index.js b/x-pack/plugins/watcher/common/lib/serialization/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/index.js rename to x-pack/plugins/watcher/common/lib/serialization/index.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_actions.js b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_actions.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_actions.js rename to x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_actions.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_condition.js b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_condition.js similarity index 98% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_condition.js rename to x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_condition.js index 472349b87fbc19..620859608bc267 100644 --- a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_condition.js +++ b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_condition.js @@ -5,7 +5,7 @@ */ import { singleLineScript } from './single_line_script'; -import { COMPARATORS } from '../../../../common/constants'; +import { COMPARATORS } from '../../../constants'; const { BETWEEN } = COMPARATORS; /* watch.condition.script.inline diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_input.js b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_input.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_input.js rename to x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_input.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_metadata.js b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_metadata.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_metadata.js rename to x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_metadata.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_transform.js b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_transform.js similarity index 98% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_transform.js rename to x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_transform.js index 1ac4adb8218040..1fcbd75aeaeea6 100644 --- a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_transform.js +++ b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_transform.js @@ -5,7 +5,7 @@ */ import { singleLineScript } from './single_line_script'; -import { COMPARATORS } from '../../../../common/constants'; +import { COMPARATORS } from '../../../constants'; const { BETWEEN } = COMPARATORS; /* watch.transform.script.inline diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_trigger.js b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_trigger.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/build_trigger.js rename to x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/build_trigger.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/index.js b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/index.js rename to x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/index.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/single_line_script.js b/x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/single_line_script.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialization_helpers/single_line_script.js rename to x-pack/plugins/watcher/common/lib/serialization/serialization_helpers/single_line_script.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialize_json_watch.js b/x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialize_json_watch.js rename to x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialize_json_watch.test.js b/x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.test.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialize_json_watch.test.js rename to x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.test.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialize_threshold_watch.js b/x-pack/plugins/watcher/common/lib/serialization/serialize_threshold_watch.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialize_threshold_watch.js rename to x-pack/plugins/watcher/common/lib/serialization/serialize_threshold_watch.js diff --git a/x-pack/legacy/plugins/watcher/common/lib/serialization/serialize_threshold_watch.test.js b/x-pack/plugins/watcher/common/lib/serialization/serialize_threshold_watch.test.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/lib/serialization/serialize_threshold_watch.test.js rename to x-pack/plugins/watcher/common/lib/serialization/serialize_threshold_watch.test.js diff --git a/x-pack/plugins/watcher/common/models/action/action.js b/x-pack/plugins/watcher/common/models/action/action.js new file mode 100644 index 00000000000000..0375b6ebf5d475 --- /dev/null +++ b/x-pack/plugins/watcher/common/models/action/action.js @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { set } from 'lodash'; +import { getActionType } from '../../lib/get_action_type'; +import { ACTION_TYPES } from '../../constants'; +import { LoggingAction } from './logging_action'; +import { EmailAction } from './email_action'; +import { SlackAction } from './slack_action'; +import { IndexAction } from './index_action'; +import { WebhookAction } from './webhook_action'; +import { PagerDutyAction } from './pagerduty_action'; +import { JiraAction } from './jira_action'; +import { UnknownAction } from './unknown_action'; + +const ActionTypes = {}; +set(ActionTypes, ACTION_TYPES.LOGGING, LoggingAction); +set(ActionTypes, ACTION_TYPES.EMAIL, EmailAction); +set(ActionTypes, ACTION_TYPES.SLACK, SlackAction); +set(ActionTypes, ACTION_TYPES.INDEX, IndexAction); +set(ActionTypes, ACTION_TYPES.WEBHOOK, WebhookAction); +set(ActionTypes, ACTION_TYPES.PAGERDUTY, PagerDutyAction); +set(ActionTypes, ACTION_TYPES.JIRA, JiraAction); +set(ActionTypes, ACTION_TYPES.UNKNOWN, UnknownAction); + +export class Action { + static getActionTypes = () => { + return ActionTypes; + }; + + // From Elasticsearch + static fromUpstreamJson(json) { + const type = getActionType(json.actionJson); + const ActionType = ActionTypes[type] || UnknownAction; + const { action } = ActionType.fromUpstreamJson(json); + return action; + } + + // From Kibana + static fromDownstreamJson(json) { + const ActionType = ActionTypes[json.type] || UnknownAction; + const { action } = ActionType.fromDownstreamJson(json); + return action; + } +} diff --git a/x-pack/legacy/plugins/watcher/common/models/action/action.test.js b/x-pack/plugins/watcher/common/models/action/action.test.js similarity index 97% rename from x-pack/legacy/plugins/watcher/common/models/action/action.test.js rename to x-pack/plugins/watcher/common/models/action/action.test.js index ee1265cd2edeec..8a5f47fe0e5caf 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/action.test.js +++ b/x-pack/plugins/watcher/common/models/action/action.test.js @@ -5,7 +5,7 @@ */ import { Action } from './action'; -import { ACTION_TYPES } from '../../../common/constants'; +import { ACTION_TYPES } from '../../constants'; jest.mock('./logging_action', () => ({ LoggingAction: { diff --git a/x-pack/legacy/plugins/watcher/common/models/action/base_action.js b/x-pack/plugins/watcher/common/models/action/base_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/models/action/base_action.js rename to x-pack/plugins/watcher/common/models/action/base_action.js diff --git a/x-pack/legacy/plugins/watcher/common/models/action/email_action.js b/x-pack/plugins/watcher/common/models/action/email_action.js similarity index 98% rename from x-pack/legacy/plugins/watcher/common/models/action/email_action.js rename to x-pack/plugins/watcher/common/models/action/email_action.js index de948100951ad1..918a2d125c09a1 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/email_action.js +++ b/x-pack/plugins/watcher/common/models/action/email_action.js @@ -5,7 +5,7 @@ */ import { BaseAction } from './base_action'; -import { ACTION_TYPES, ERROR_CODES } from '../../../common/constants'; +import { ACTION_TYPES, ERROR_CODES } from '../../constants'; import { i18n } from '@kbn/i18n'; export class EmailAction extends BaseAction { diff --git a/x-pack/legacy/plugins/watcher/common/models/action/index.js b/x-pack/plugins/watcher/common/models/action/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/common/models/action/index.js rename to x-pack/plugins/watcher/common/models/action/index.js diff --git a/x-pack/legacy/plugins/watcher/common/models/action/index_action.js b/x-pack/plugins/watcher/common/models/action/index_action.js similarity index 97% rename from x-pack/legacy/plugins/watcher/common/models/action/index_action.js rename to x-pack/plugins/watcher/common/models/action/index_action.js index 73932079977fd6..3db4e4f9b0dabd 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/index_action.js +++ b/x-pack/plugins/watcher/common/models/action/index_action.js @@ -5,7 +5,7 @@ */ import { BaseAction } from './base_action'; -import { ACTION_TYPES, ERROR_CODES } from '../../../common/constants'; +import { ACTION_TYPES, ERROR_CODES } from '../../constants'; import { i18n } from '@kbn/i18n'; export class IndexAction extends BaseAction { diff --git a/x-pack/legacy/plugins/watcher/common/models/action/jira_action.js b/x-pack/plugins/watcher/common/models/action/jira_action.js similarity index 98% rename from x-pack/legacy/plugins/watcher/common/models/action/jira_action.js rename to x-pack/plugins/watcher/common/models/action/jira_action.js index 75fa60986c49a3..87bca6c480229f 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/jira_action.js +++ b/x-pack/plugins/watcher/common/models/action/jira_action.js @@ -5,7 +5,7 @@ */ import { BaseAction } from './base_action'; -import { ACTION_TYPES, ERROR_CODES } from '../../../common/constants'; +import { ACTION_TYPES, ERROR_CODES } from '../../constants'; import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; diff --git a/x-pack/legacy/plugins/watcher/common/models/action/logging_action.js b/x-pack/plugins/watcher/common/models/action/logging_action.js similarity index 97% rename from x-pack/legacy/plugins/watcher/common/models/action/logging_action.js rename to x-pack/plugins/watcher/common/models/action/logging_action.js index c3754b7ace2384..e9dd0b3d7ddfb5 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/logging_action.js +++ b/x-pack/plugins/watcher/common/models/action/logging_action.js @@ -5,7 +5,7 @@ */ import { BaseAction } from './base_action'; -import { ACTION_TYPES, ERROR_CODES } from '../../../common/constants'; +import { ACTION_TYPES, ERROR_CODES } from '../../constants'; import { i18n } from '@kbn/i18n'; export class LoggingAction extends BaseAction { diff --git a/x-pack/legacy/plugins/watcher/common/models/action/pagerduty_action.js b/x-pack/plugins/watcher/common/models/action/pagerduty_action.js similarity index 97% rename from x-pack/legacy/plugins/watcher/common/models/action/pagerduty_action.js rename to x-pack/plugins/watcher/common/models/action/pagerduty_action.js index cc15d10f7c6225..b92fbf55bda16c 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/pagerduty_action.js +++ b/x-pack/plugins/watcher/common/models/action/pagerduty_action.js @@ -5,7 +5,7 @@ */ import { BaseAction } from './base_action'; -import { ACTION_TYPES, ERROR_CODES } from '../../../common/constants'; +import { ACTION_TYPES, ERROR_CODES } from '../../constants'; import { i18n } from '@kbn/i18n'; export class PagerDutyAction extends BaseAction { diff --git a/x-pack/legacy/plugins/watcher/common/models/action/slack_action.js b/x-pack/plugins/watcher/common/models/action/slack_action.js similarity index 97% rename from x-pack/legacy/plugins/watcher/common/models/action/slack_action.js rename to x-pack/plugins/watcher/common/models/action/slack_action.js index a1986977c4633e..24caa9ccfd5816 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/slack_action.js +++ b/x-pack/plugins/watcher/common/models/action/slack_action.js @@ -5,7 +5,7 @@ */ import { BaseAction } from './base_action'; -import { ACTION_TYPES, ERROR_CODES } from '../../../common/constants'; +import { ACTION_TYPES, ERROR_CODES } from '../../constants'; import { i18n } from '@kbn/i18n'; export class SlackAction extends BaseAction { diff --git a/x-pack/legacy/plugins/watcher/common/models/action/unknown_action.js b/x-pack/plugins/watcher/common/models/action/unknown_action.js similarity index 96% rename from x-pack/legacy/plugins/watcher/common/models/action/unknown_action.js rename to x-pack/plugins/watcher/common/models/action/unknown_action.js index 95ed542e66fa55..4f304be2d58b6d 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/unknown_action.js +++ b/x-pack/plugins/watcher/common/models/action/unknown_action.js @@ -5,7 +5,7 @@ */ import { BaseAction } from './base_action'; -import { ACTION_TYPES, ERROR_CODES } from '../../../common/constants'; +import { ACTION_TYPES, ERROR_CODES } from '../../constants'; import { i18n } from '@kbn/i18n'; export class UnknownAction extends BaseAction { diff --git a/x-pack/legacy/plugins/watcher/common/models/action/webhook_action.js b/x-pack/plugins/watcher/common/models/action/webhook_action.js similarity index 98% rename from x-pack/legacy/plugins/watcher/common/models/action/webhook_action.js rename to x-pack/plugins/watcher/common/models/action/webhook_action.js index d6f921a75a9ea3..f0e9fc9fc44df5 100644 --- a/x-pack/legacy/plugins/watcher/common/models/action/webhook_action.js +++ b/x-pack/plugins/watcher/common/models/action/webhook_action.js @@ -5,7 +5,7 @@ */ import { BaseAction } from './base_action'; -import { ACTION_TYPES, ERROR_CODES } from '../../../common/constants'; +import { ACTION_TYPES, ERROR_CODES } from '../../constants'; import { i18n } from '@kbn/i18n'; export class WebhookAction extends BaseAction { diff --git a/x-pack/legacy/plugins/watcher/common/types/action_types.ts b/x-pack/plugins/watcher/common/types/action_types.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/types/action_types.ts rename to x-pack/plugins/watcher/common/types/action_types.ts diff --git a/x-pack/plugins/watcher/common/types/license_status.ts b/x-pack/plugins/watcher/common/types/license_status.ts new file mode 100644 index 00000000000000..3872559fc00662 --- /dev/null +++ b/x-pack/plugins/watcher/common/types/license_status.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; + * you may not use this file except in compliance with the Elastic License. + */ + +export interface LicenseStatus { + valid: boolean; + message?: string; +} diff --git a/x-pack/legacy/plugins/watcher/common/types/watch_types.ts b/x-pack/plugins/watcher/common/types/watch_types.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/common/types/watch_types.ts rename to x-pack/plugins/watcher/common/types/watch_types.ts diff --git a/x-pack/plugins/watcher/kibana.json b/x-pack/plugins/watcher/kibana.json new file mode 100644 index 00000000000000..93a28f8f59ed5a --- /dev/null +++ b/x-pack/plugins/watcher/kibana.json @@ -0,0 +1,13 @@ +{ + "id": "watcher", + "version": "kibana", + "requiredPlugins": [ + "home", + "licensing", + "management", + "eui_utils", + "data" + ], + "server": true, + "ui": true +} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/app.tsx b/x-pack/plugins/watcher/public/application/app.tsx similarity index 82% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/app.tsx rename to x-pack/plugins/watcher/public/application/app.tsx index 36fa1cce9d6ddc..1f418e4475ed0a 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/app.tsx +++ b/x-pack/plugins/watcher/public/application/app.tsx @@ -4,16 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useEffect, useState } from 'react'; +import { Observable } from 'rxjs'; import { ChromeStart, DocLinksStart, HttpSetup, ToastsSetup, IUiSettingsClient, -} from 'src/core/public'; +} from 'kibana/public'; -import { EuiCallOut, EuiLink } from '@elastic/eui'; import { HashRouter, Switch, @@ -22,15 +22,18 @@ import { withRouter, RouteComponentProps, } from 'react-router-dom'; + +import { EuiCallOut, EuiLink } from '@elastic/eui'; + import { FormattedMessage } from '@kbn/i18n/react'; + +import { LicenseStatus } from '../../common/types/license_status'; import { WatchStatus } from './sections/watch_status/components/watch_status'; import { WatchEdit } from './sections/watch_edit/components/watch_edit'; import { WatchList } from './sections/watch_list/components/watch_list'; import { registerRouter } from './lib/navigation'; import { BASE_PATH } from './constants'; -import { LICENSE_STATUS_VALID } from '../../../../../common/constants'; import { AppContextProvider } from './app_context'; -import { LegacyDependencies } from '../types'; const ShareRouter = withRouter(({ children, history }: RouteComponentProps & { children: any }) => { registerRouter({ history }); @@ -43,14 +46,21 @@ export interface AppDeps { toasts: ToastsSetup; http: HttpSetup; uiSettings: IUiSettingsClient; - legacy: LegacyDependencies; euiUtils: any; + createTimeBuckets: () => any; + licenseStatus$: Observable; + MANAGEMENT_BREADCRUMB: any; } export const App = (deps: AppDeps) => { - const { status, message } = deps.legacy.licenseStatus; + const [{ valid, message }, setLicenseStatus] = useState({ valid: true }); + + useEffect(() => { + const s = deps.licenseStatus$.subscribe(setLicenseStatus); + return () => s.unsubscribe(); + }, [deps.licenseStatus$]); - if (status !== LICENSE_STATUS_VALID) { + if (!valid) { return ( { defaultMessage="License error" /> } - color="warning" + color="danger" iconType="help" > {message}{' '} @@ -72,7 +82,6 @@ export const App = (deps: AppDeps) => { ); } - return ( diff --git a/x-pack/plugins/watcher/public/application/app_context.tsx b/x-pack/plugins/watcher/public/application/app_context.tsx new file mode 100644 index 00000000000000..e5cf4c33b477ac --- /dev/null +++ b/x-pack/plugins/watcher/public/application/app_context.tsx @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { createContext, useContext } from 'react'; +import { DocLinksStart } from 'kibana/public'; +import { ACTION_TYPES } from '../../common/constants'; +import { AppDeps } from './app'; + +interface ContextValue extends Omit { + links: ReturnType; +} + +const AppContext = createContext(null as any); + +const generateDocLinks = ({ ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }: DocLinksStart) => { + const elasticDocLinkBase = `${ELASTIC_WEBSITE_URL}guide/en/`; + const esBase = `${elasticDocLinkBase}elasticsearch/reference/${DOC_LINK_VERSION}`; + const kibanaBase = `${elasticDocLinkBase}kibana/${DOC_LINK_VERSION}`; + const putWatchApiUrl = `${esBase}/watcher-api-put-watch.html`; + const executeWatchApiUrl = `${esBase}/watcher-api-execute-watch.html#watcher-api-execute-watch-action-mode`; + const watcherGettingStartedUrl = `${kibanaBase}/watcher-ui.html`; + const watchActionsConfigurationMap = { + [ACTION_TYPES.SLACK]: `${esBase}/actions-slack.html#configuring-slack`, + [ACTION_TYPES.PAGERDUTY]: `${esBase}/actions-pagerduty.html#configuring-pagerduty`, + [ACTION_TYPES.JIRA]: `${esBase}/actions-jira.html#configuring-jira`, + }; + + return { + putWatchApiUrl, + executeWatchApiUrl, + watcherGettingStartedUrl, + watchActionsConfigurationMap, + }; +}; + +export const AppContextProvider = ({ + children, + value, +}: { + value: AppDeps; + children: React.ReactNode; +}) => { + const { docLinks, ...rest } = value; + return ( + + {children} + + ); +}; + +export const useAppContext = () => { + const ctx = useContext(AppContext); + if (!ctx) { + throw new Error('"useAppContext" can only be called inside of AppContext.Provider!'); + } + return ctx; +}; diff --git a/x-pack/plugins/watcher/public/application/boot.tsx b/x-pack/plugins/watcher/public/application/boot.tsx new file mode 100644 index 00000000000000..8461bd65bbd5e5 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/boot.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { SavedObjectsClientContract } from 'kibana/public'; + +import { App, AppDeps } from './app'; +import { setHttpClient, setSavedObjectsClient } from './lib/api'; + +interface BootDeps extends AppDeps { + element: HTMLElement; + savedObjects: SavedObjectsClientContract; + I18nContext: any; +} + +export const boot = (bootDeps: BootDeps) => { + const { I18nContext, element, savedObjects, ...appDeps } = bootDeps; + + setHttpClient(appDeps.http); + setSavedObjectsClient(savedObjects); + + render( + + + , + element + ); + return () => { + unmountComponentAtNode(element); + }; +}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/confirm_watches_modal.tsx b/x-pack/plugins/watcher/public/application/components/confirm_watches_modal.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/confirm_watches_modal.tsx rename to x-pack/plugins/watcher/public/application/components/confirm_watches_modal.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/delete_watches_modal.tsx b/x-pack/plugins/watcher/public/application/components/delete_watches_modal.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/delete_watches_modal.tsx rename to x-pack/plugins/watcher/public/application/components/delete_watches_modal.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/form_errors.tsx b/x-pack/plugins/watcher/public/application/components/form_errors.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/form_errors.tsx rename to x-pack/plugins/watcher/public/application/components/form_errors.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/index.ts b/x-pack/plugins/watcher/public/application/components/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/index.ts rename to x-pack/plugins/watcher/public/application/components/index.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/page_error/index.ts b/x-pack/plugins/watcher/public/application/components/page_error/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/page_error/index.ts rename to x-pack/plugins/watcher/public/application/components/page_error/index.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/page_error/page_error.tsx b/x-pack/plugins/watcher/public/application/components/page_error/page_error.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/page_error/page_error.tsx rename to x-pack/plugins/watcher/public/application/components/page_error/page_error.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/page_error/page_error_forbidden.tsx b/x-pack/plugins/watcher/public/application/components/page_error/page_error_forbidden.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/page_error/page_error_forbidden.tsx rename to x-pack/plugins/watcher/public/application/components/page_error/page_error_forbidden.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/page_error/page_error_not_exist.tsx b/x-pack/plugins/watcher/public/application/components/page_error/page_error_not_exist.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/page_error/page_error_not_exist.tsx rename to x-pack/plugins/watcher/public/application/components/page_error/page_error_not_exist.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/section_error.tsx b/x-pack/plugins/watcher/public/application/components/section_error.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/section_error.tsx rename to x-pack/plugins/watcher/public/application/components/section_error.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/components/section_loading.tsx b/x-pack/plugins/watcher/public/application/components/section_loading.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/components/section_loading.tsx rename to x-pack/plugins/watcher/public/application/components/section_loading.tsx diff --git a/x-pack/plugins/watcher/public/application/components/watch_status.tsx b/x-pack/plugins/watcher/public/application/components/watch_status.tsx new file mode 100644 index 00000000000000..088f476dfb4cf3 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/components/watch_status.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIcon, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { ACTION_STATES, WATCH_STATES } from '../../../common/constants'; + +function StatusIcon({ status }: { status: string }) { + switch (status) { + case WATCH_STATES.FIRING: + case ACTION_STATES.FIRING: + return ; + case WATCH_STATES.OK: + case ACTION_STATES.OK: + case ACTION_STATES.ACKNOWLEDGED: + return ; + case ACTION_STATES.THROTTLED: + return ; + case WATCH_STATES.DISABLED: + return ; + case WATCH_STATES.CONFIG_ERROR: + case WATCH_STATES.ERROR: + case ACTION_STATES.UNKNOWN: + return ; + case ACTION_STATES.CONFIG_ERROR: + case ACTION_STATES.ERROR: + return ; + } + return null; +} + +export function WatchStatus({ status, size = 's' }: { status: string; size?: 'xs' | 's' | 'm' }) { + return ( + + + + + + {status} + + + ); +} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/constants/base_path.ts b/x-pack/plugins/watcher/public/application/constants/base_path.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/constants/base_path.ts rename to x-pack/plugins/watcher/public/application/constants/base_path.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/constants/index.ts b/x-pack/plugins/watcher/public/application/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/constants/index.ts rename to x-pack/plugins/watcher/public/application/constants/index.ts diff --git a/x-pack/plugins/watcher/public/application/lib/api.ts b/x-pack/plugins/watcher/public/application/lib/api.ts new file mode 100644 index 00000000000000..82ec2925ba6dca --- /dev/null +++ b/x-pack/plugins/watcher/public/application/lib/api.ts @@ -0,0 +1,182 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { HttpSetup, SavedObjectsClientContract } from 'kibana/public'; + +import { Settings } from '../models/settings'; +import { Watch } from '../models/watch'; +import { WatchHistoryItem } from '../models/watch_history_item'; +import { WatchStatus } from '../models/watch_status'; + +import { BaseWatch, ExecutedWatchDetails } from '../../../common/types/watch_types'; +import { useRequest, sendRequest } from './use_request'; + +import { ROUTES } from '../../../common/constants'; + +let httpClient: HttpSetup; + +export const setHttpClient = (anHttpClient: HttpSetup) => { + httpClient = anHttpClient; +}; + +export const getHttpClient = () => { + return httpClient; +}; + +let savedObjectsClient: SavedObjectsClientContract; + +export const setSavedObjectsClient = (aSavedObjectsClient: SavedObjectsClientContract) => { + savedObjectsClient = aSavedObjectsClient; +}; + +export const getSavedObjectsClient = () => savedObjectsClient; + +const basePath = ROUTES.API_ROOT; + +export const useLoadWatches = (pollIntervalMs: number) => { + return useRequest({ + path: `${basePath}/watches`, + method: 'get', + pollIntervalMs, + deserializer: ({ watches = [] }: { watches: any[] }) => { + return watches.map((watch: any) => Watch.fromUpstreamJson(watch)); + }, + }); +}; + +export const useLoadWatchDetail = (id: string) => { + return useRequest({ + path: `${basePath}/watch/${id}`, + method: 'get', + deserializer: ({ watch = {} }: { watch: any }) => Watch.fromUpstreamJson(watch), + }); +}; + +export const useLoadWatchHistory = (id: string, startTime: string) => { + return useRequest({ + query: startTime ? { startTime } : undefined, + path: `${basePath}/watch/${id}/history`, + method: 'get', + deserializer: ({ watchHistoryItems = [] }: { watchHistoryItems: any }) => { + return watchHistoryItems.map((historyItem: any) => + WatchHistoryItem.fromUpstreamJson(historyItem) + ); + }, + }); +}; + +export const useLoadWatchHistoryDetail = (id: string | undefined) => { + return useRequest({ + path: !id ? '' : `${basePath}/history/${id}`, + method: 'get', + deserializer: ({ watchHistoryItem }: { watchHistoryItem: any }) => + WatchHistoryItem.fromUpstreamJson(watchHistoryItem), + }); +}; + +export const deleteWatches = async (watchIds: string[]) => { + const body = JSON.stringify({ + watchIds, + }); + const { results } = await getHttpClient().post(`${basePath}/watches/delete`, { body }); + return results; +}; + +export const deactivateWatch = async (id: string) => { + return sendRequest({ + path: `${basePath}/watch/${id}/deactivate`, + method: 'put', + }); +}; + +export const activateWatch = async (id: string) => { + return sendRequest({ + path: `${basePath}/watch/${id}/activate`, + method: 'put', + }); +}; + +export const loadWatch = async (id: string) => { + const { watch } = await getHttpClient().get(`${basePath}/watch/${id}`); + return Watch.fromUpstreamJson(watch); +}; + +export const getMatchingIndices = async (pattern: string) => { + if (!pattern.startsWith('*')) { + pattern = `*${pattern}`; + } + if (!pattern.endsWith('*')) { + pattern = `${pattern}*`; + } + const body = JSON.stringify({ pattern }); + const { indices } = await getHttpClient().post(`${basePath}/indices`, { body }); + return indices; +}; + +export const fetchFields = async (indexes: string[]) => { + const { fields } = await getHttpClient().post(`${basePath}/fields`, { + body: JSON.stringify({ indexes }), + }); + return fields; +}; + +export const createWatch = async (watch: BaseWatch) => { + return await getHttpClient().put(`${basePath}/watch/${watch.id}`, { + body: JSON.stringify(watch.upstreamJson), + }); +}; + +export const executeWatch = async (executeWatchDetails: ExecutedWatchDetails, watch: BaseWatch) => { + return sendRequest({ + path: `${basePath}/watch/execute`, + method: 'put', + body: JSON.stringify({ + executeDetails: executeWatchDetails.upstreamJson, + watch: watch.upstreamJson, + }), + }); +}; + +export const loadIndexPatterns = async () => { + const { savedObjects } = await getSavedObjectsClient().find({ + type: 'index-pattern', + fields: ['title'], + perPage: 10000, + }); + return savedObjects; +}; + +export const useGetWatchVisualizationData = (watchModel: BaseWatch, visualizeOptions: any) => { + return useRequest({ + path: `${basePath}/watch/visualize`, + method: 'post', + body: JSON.stringify({ + watch: watchModel.upstreamJson, + options: visualizeOptions.upstreamJson, + }), + deserializer: (data: { visualizeData: any }) => data?.visualizeData, + }); +}; + +export const useLoadSettings = () => { + return useRequest({ + path: `${basePath}/settings`, + method: 'get', + deserializer: (data: { + action_types: { + [key: string]: { + enabled: boolean; + }; + }; + }) => Settings.fromUpstreamJson(data), + }); +}; + +export const ackWatchAction = async (watchId: string, actionId: string) => { + const { watchStatus } = await getHttpClient().put( + `${basePath}/watch/${watchId}/action/${actionId}/acknowledge` + ); + return WatchStatus.fromUpstreamJson(watchStatus); +}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/breadcrumbs.ts b/x-pack/plugins/watcher/public/application/lib/breadcrumbs.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/lib/breadcrumbs.ts rename to x-pack/plugins/watcher/public/application/lib/breadcrumbs.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/format_date.ts b/x-pack/plugins/watcher/public/application/lib/format_date.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/lib/format_date.ts rename to x-pack/plugins/watcher/public/application/lib/format_date.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/get_search_value.ts b/x-pack/plugins/watcher/public/application/lib/get_search_value.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/lib/get_search_value.ts rename to x-pack/plugins/watcher/public/application/lib/get_search_value.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/get_time_unit_label.ts b/x-pack/plugins/watcher/public/application/lib/get_time_unit_label.ts similarity index 95% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/lib/get_time_unit_label.ts rename to x-pack/plugins/watcher/public/application/lib/get_time_unit_label.ts index ce3b96ac17def3..5cb78b61488b73 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/get_time_unit_label.ts +++ b/x-pack/plugins/watcher/public/application/lib/get_time_unit_label.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { TIME_UNITS } from '../../../../common/constants'; +import { TIME_UNITS } from '../../../common/constants'; export function getTimeUnitLabel(timeUnit = TIME_UNITS.SECOND, timeValue = '0') { switch (timeUnit) { diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/navigation.ts b/x-pack/plugins/watcher/public/application/lib/navigation.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/lib/navigation.ts rename to x-pack/plugins/watcher/public/application/lib/navigation.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/lib/use_request.ts b/x-pack/plugins/watcher/public/application/lib/use_request.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/lib/use_request.ts rename to x-pack/plugins/watcher/public/application/lib/use_request.ts diff --git a/x-pack/plugins/watcher/public/application/models/action/action.js b/x-pack/plugins/watcher/public/application/models/action/action.js new file mode 100644 index 00000000000000..43874c9ee1dd1a --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/action/action.js @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get, set } from 'lodash'; +import { ACTION_TYPES } from '../../../../common/constants'; +import { EmailAction } from './email_action'; +import { LoggingAction } from './logging_action'; +import { SlackAction } from './slack_action'; +import { WebhookAction } from './webhook_action'; +import { IndexAction } from './index_action'; +import { PagerDutyAction } from './pagerduty_action'; +import { JiraAction } from './jira_action'; +import { UnknownAction } from './unknown_action'; + +const ActionTypes = {}; +set(ActionTypes, ACTION_TYPES.EMAIL, EmailAction); +set(ActionTypes, ACTION_TYPES.LOGGING, LoggingAction); +set(ActionTypes, ACTION_TYPES.SLACK, SlackAction); +set(ActionTypes, ACTION_TYPES.WEBHOOK, WebhookAction); +set(ActionTypes, ACTION_TYPES.INDEX, IndexAction); +set(ActionTypes, ACTION_TYPES.PAGERDUTY, PagerDutyAction); +set(ActionTypes, ACTION_TYPES.JIRA, JiraAction); + +export class Action { + static getActionTypes = () => { + return ActionTypes; + }; + + static fromUpstreamJson(upstreamAction) { + const type = get(upstreamAction, 'type'); + const ActionType = ActionTypes[type] || UnknownAction; + + return ActionType.fromUpstreamJson(upstreamAction); + } +} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/base_action.js b/x-pack/plugins/watcher/public/application/models/action/base_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/base_action.js rename to x-pack/plugins/watcher/public/application/models/action/base_action.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/email_action.js b/x-pack/plugins/watcher/public/application/models/action/email_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/email_action.js rename to x-pack/plugins/watcher/public/application/models/action/email_action.js diff --git a/x-pack/plugins/watcher/public/application/models/action/index.d.ts b/x-pack/plugins/watcher/public/application/models/action/index.d.ts new file mode 100644 index 00000000000000..5415194b729583 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/action/index.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const Action: any; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/index.js b/x-pack/plugins/watcher/public/application/models/action/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/index.js rename to x-pack/plugins/watcher/public/application/models/action/index.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/index_action.js b/x-pack/plugins/watcher/public/application/models/action/index_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/index_action.js rename to x-pack/plugins/watcher/public/application/models/action/index_action.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/jira_action.js b/x-pack/plugins/watcher/public/application/models/action/jira_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/jira_action.js rename to x-pack/plugins/watcher/public/application/models/action/jira_action.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/logging_action.js b/x-pack/plugins/watcher/public/application/models/action/logging_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/logging_action.js rename to x-pack/plugins/watcher/public/application/models/action/logging_action.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/pagerduty_action.js b/x-pack/plugins/watcher/public/application/models/action/pagerduty_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/pagerduty_action.js rename to x-pack/plugins/watcher/public/application/models/action/pagerduty_action.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/slack_action.js b/x-pack/plugins/watcher/public/application/models/action/slack_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/slack_action.js rename to x-pack/plugins/watcher/public/application/models/action/slack_action.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/unknown_action.js b/x-pack/plugins/watcher/public/application/models/action/unknown_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/unknown_action.js rename to x-pack/plugins/watcher/public/application/models/action/unknown_action.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/webhook_action.js b/x-pack/plugins/watcher/public/application/models/action/webhook_action.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action/webhook_action.js rename to x-pack/plugins/watcher/public/application/models/action/webhook_action.js diff --git a/x-pack/plugins/watcher/public/application/models/action_status/action_status.js b/x-pack/plugins/watcher/public/application/models/action_status/action_status.js new file mode 100644 index 00000000000000..f38fa23b68f5a8 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/action_status/action_status.js @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get } from 'lodash'; +import { getMoment } from '../../../../common/lib/get_moment'; + +export class ActionStatus { + constructor(props = {}) { + this.id = get(props, 'id'); + this.state = get(props, 'state'); + this.isAckable = get(props, 'isAckable'); + this.lastAcknowledged = getMoment(get(props, 'lastAcknowledged')); + this.lastThrottled = getMoment(get(props, 'lastThrottled')); + this.lastExecution = getMoment(get(props, 'lastExecution')); + this.lastExecutionSuccessful = get(props, 'lastExecutionSuccessful'); + this.lastExecutionReason = get(props, 'lastExecutionReason'); + this.lastSuccessfulExecution = getMoment(get(props, 'lastSuccessfulExecution')); + + if (this.lastAcknowledged) { + this.lastAcknowledgedHumanized = this.lastAcknowledged.fromNow(); + } + if (this.lastExecution) { + this.lastExecutionHumanized = this.lastExecution.fromNow(); + } + if (this.lastThrottled) { + this.lastThrottledHumanized = this.lastThrottled.fromNow(); + } + } + + static fromUpstreamJson(upstreamActionStatus) { + return new ActionStatus(upstreamActionStatus); + } +} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/action_status/index.js b/x-pack/plugins/watcher/public/application/models/action_status/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/action_status/index.js rename to x-pack/plugins/watcher/public/application/models/action_status/index.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/execute_details/execute_details.js b/x-pack/plugins/watcher/public/application/models/execute_details/execute_details.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/execute_details/execute_details.js rename to x-pack/plugins/watcher/public/application/models/execute_details/execute_details.js diff --git a/x-pack/plugins/watcher/public/application/models/execute_details/index.d.ts b/x-pack/plugins/watcher/public/application/models/execute_details/index.d.ts new file mode 100644 index 00000000000000..417c073cf05681 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/execute_details/index.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const ExecuteDetails: any; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/execute_details/index.js b/x-pack/plugins/watcher/public/application/models/execute_details/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/execute_details/index.js rename to x-pack/plugins/watcher/public/application/models/execute_details/index.js diff --git a/x-pack/plugins/watcher/public/application/models/settings/index.d.ts b/x-pack/plugins/watcher/public/application/models/settings/index.d.ts new file mode 100644 index 00000000000000..92a5de1df413ce --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/settings/index.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const Settings: any; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/settings/index.js b/x-pack/plugins/watcher/public/application/models/settings/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/settings/index.js rename to x-pack/plugins/watcher/public/application/models/settings/index.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/settings/settings.js b/x-pack/plugins/watcher/public/application/models/settings/settings.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/settings/settings.js rename to x-pack/plugins/watcher/public/application/models/settings/settings.js diff --git a/x-pack/plugins/watcher/public/application/models/visualize_options/index.d.ts b/x-pack/plugins/watcher/public/application/models/visualize_options/index.d.ts new file mode 100644 index 00000000000000..cea10ff1e10460 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/visualize_options/index.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const VisualizeOptions: any; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/visualize_options/index.js b/x-pack/plugins/watcher/public/application/models/visualize_options/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/visualize_options/index.js rename to x-pack/plugins/watcher/public/application/models/visualize_options/index.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/visualize_options/visualize_options.js b/x-pack/plugins/watcher/public/application/models/visualize_options/visualize_options.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/visualize_options/visualize_options.js rename to x-pack/plugins/watcher/public/application/models/visualize_options/visualize_options.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/agg_types.ts b/x-pack/plugins/watcher/public/application/models/watch/agg_types.ts similarity index 94% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/agg_types.ts rename to x-pack/plugins/watcher/public/application/models/watch/agg_types.ts index cefaaa3b1abd3a..d2b1ddebf12a27 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/agg_types.ts +++ b/x-pack/plugins/watcher/public/application/models/watch/agg_types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AGG_TYPES } from '../../../../../common/constants'; +import { AGG_TYPES } from '../../../../common/constants'; export interface AggType { text: string; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/base_watch.js b/x-pack/plugins/watcher/public/application/models/watch/base_watch.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/base_watch.js rename to x-pack/plugins/watcher/public/application/models/watch/base_watch.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/comparators.ts b/x-pack/plugins/watcher/public/application/models/watch/comparators.ts similarity index 96% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/comparators.ts rename to x-pack/plugins/watcher/public/application/models/watch/comparators.ts index edc3a03c252271..96904719098a0c 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/comparators.ts +++ b/x-pack/plugins/watcher/public/application/models/watch/comparators.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; -import { COMPARATORS } from '../../../../../common/constants'; +import { COMPARATORS } from '../../../../common/constants'; export interface Comparator { text: string; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/default_watch.json b/x-pack/plugins/watcher/public/application/models/watch/default_watch.json similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/default_watch.json rename to x-pack/plugins/watcher/public/application/models/watch/default_watch.json diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/group_by_types.ts b/x-pack/plugins/watcher/public/application/models/watch/group_by_types.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/group_by_types.ts rename to x-pack/plugins/watcher/public/application/models/watch/group_by_types.ts diff --git a/x-pack/plugins/watcher/public/application/models/watch/index.d.ts b/x-pack/plugins/watcher/public/application/models/watch/index.d.ts new file mode 100644 index 00000000000000..73ee2279d3912f --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch/index.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const Watch: any; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/index.js b/x-pack/plugins/watcher/public/application/models/watch/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/index.js rename to x-pack/plugins/watcher/public/application/models/watch/index.js diff --git a/x-pack/plugins/watcher/public/application/models/watch/json_watch.d.ts b/x-pack/plugins/watcher/public/application/models/watch/json_watch.d.ts new file mode 100644 index 00000000000000..cef21880e63466 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch/json_watch.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const JsonWatch: any; diff --git a/x-pack/plugins/watcher/public/application/models/watch/json_watch.js b/x-pack/plugins/watcher/public/application/models/watch/json_watch.js new file mode 100644 index 00000000000000..19d016fcc48eb5 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch/json_watch.js @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import uuid from 'uuid'; +import { get } from 'lodash'; +import { BaseWatch } from './base_watch'; +import { ACTION_TYPES, WATCH_TYPES } from '../../../../common/constants'; +import defaultWatchJson from './default_watch.json'; +import { i18n } from '@kbn/i18n'; + +/** + * {@code JsonWatch} allows a user to create a Watch by writing the raw JSON. + */ +export class JsonWatch extends BaseWatch { + constructor(props = {}) { + props.type = WATCH_TYPES.JSON; + props.id = typeof props.id === 'undefined' ? uuid.v4() : props.id; + super(props); + const existingWatch = get(props, 'watch'); + this.watch = existingWatch ? existingWatch : defaultWatchJson; + this.watchString = get( + props, + 'watchString', + JSON.stringify(existingWatch ? existingWatch : defaultWatchJson, null, 2) + ); + this.id = props.id; + } + + validate() { + const validationResult = {}; + const idRegex = /^[A-Za-z0-9\-\_]+$/; + const errors = { + id: [], + json: [], + }; + validationResult.errors = errors; + // Watch id validation + if (!this.id) { + errors.id.push( + i18n.translate('xpack.watcher.sections.watchEdit.json.error.requiredIdText', { + defaultMessage: 'ID is required', + }) + ); + } else if (!idRegex.test(this.id)) { + errors.id.push( + i18n.translate('xpack.watcher.sections.watchEdit.json.error.invalidIdText', { + defaultMessage: 'ID can only contain letters, underscores, dashes, and numbers.', + }) + ); + } + // JSON validation + if (!this.watchString || this.watchString === '') { + errors.json.push( + i18n.translate('xpack.watcher.sections.watchEdit.json.error.requiredJsonText', { + defaultMessage: 'JSON is required', + }) + ); + } else { + try { + const parsedJson = JSON.parse(this.watchString); + if (parsedJson && typeof parsedJson === 'object') { + const { actions } = parsedJson; + if (actions) { + // Validate if the action(s) provided is one of the supported actions + const invalidActions = Object.keys(actions).find(actionKey => { + const actionKeys = Object.keys(actions[actionKey]); + let type; + Object.keys(ACTION_TYPES).forEach(actionTypeKey => { + if ( + actionKeys.includes(ACTION_TYPES[actionTypeKey]) && + !actionKeys.includes(ACTION_TYPES.UNKNOWN) + ) { + type = ACTION_TYPES[actionTypeKey]; + } + }); + return !type; + }); + if (invalidActions) { + errors.json.push( + i18n.translate('xpack.watcher.sections.watchEdit.json.error.invalidActionType', { + defaultMessage: 'Unknown action type provided for action "{action}".', + values: { + action: invalidActions, + }, + }) + ); + } + } + } + } catch (e) { + errors.json.push( + i18n.translate('xpack.watcher.sections.watchEdit.json.error.invalidJsonText', { + defaultMessage: 'Invalid JSON', + }) + ); + } + } + return validationResult; + } + + get upstreamJson() { + const result = super.upstreamJson; + Object.assign(result, { + watch: this.watch, + }); + return result; + } + + static fromUpstreamJson(upstreamWatch) { + return new JsonWatch(upstreamWatch); + } + + static defaultWatchJson = defaultWatchJson; + static typeName = i18n.translate('xpack.watcher.models.jsonWatch.typeName', { + defaultMessage: 'Advanced Watch', + }); + static iconClass = ''; + static selectMessage = i18n.translate('xpack.watcher.models.jsonWatch.selectMessageText', { + defaultMessage: 'Set up a custom watch in raw JSON.', + }); + static isCreatable = true; + static selectSortOrder = 100; +} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/lib/check_action_id_collision/check_action_id_collision.js b/x-pack/plugins/watcher/public/application/models/watch/lib/check_action_id_collision/check_action_id_collision.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/lib/check_action_id_collision/check_action_id_collision.js rename to x-pack/plugins/watcher/public/application/models/watch/lib/check_action_id_collision/check_action_id_collision.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/lib/check_action_id_collision/index.js b/x-pack/plugins/watcher/public/application/models/watch/lib/check_action_id_collision/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/lib/check_action_id_collision/index.js rename to x-pack/plugins/watcher/public/application/models/watch/lib/check_action_id_collision/index.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/lib/create_action_id/create_action_id.js b/x-pack/plugins/watcher/public/application/models/watch/lib/create_action_id/create_action_id.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/lib/create_action_id/create_action_id.js rename to x-pack/plugins/watcher/public/application/models/watch/lib/create_action_id/create_action_id.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/lib/create_action_id/index.js b/x-pack/plugins/watcher/public/application/models/watch/lib/create_action_id/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch/lib/create_action_id/index.js rename to x-pack/plugins/watcher/public/application/models/watch/lib/create_action_id/index.js diff --git a/x-pack/plugins/watcher/public/application/models/watch/monitoring_watch.js b/x-pack/plugins/watcher/public/application/models/watch/monitoring_watch.js new file mode 100644 index 00000000000000..82cdffc79edc42 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch/monitoring_watch.js @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { BaseWatch } from './base_watch'; +import { WATCH_TYPES } from '../../../../common/constants'; + +/** + * {@code MonitoringWatch} system defined watches created by the Monitoring plugin. + */ +export class MonitoringWatch extends BaseWatch { + constructor(props = {}) { + props.type = WATCH_TYPES.MONITORING; + super(props); + } + + get upstreamJson() { + const result = super.upstreamJson; + Object.assign(result, { + watch: this.watch, + }); + + return result; + } + + static fromUpstreamJson(upstreamWatch) { + return new MonitoringWatch(upstreamWatch); + } + + static isCreatable = false; +} diff --git a/x-pack/plugins/watcher/public/application/models/watch/threshold_watch.d.ts b/x-pack/plugins/watcher/public/application/models/watch/threshold_watch.d.ts new file mode 100644 index 00000000000000..ae85ae01304d6e --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch/threshold_watch.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const ThresholdWatch: any; diff --git a/x-pack/plugins/watcher/public/application/models/watch/threshold_watch.js b/x-pack/plugins/watcher/public/application/models/watch/threshold_watch.js new file mode 100644 index 00000000000000..c9db4237942b00 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch/threshold_watch.js @@ -0,0 +1,290 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { BaseWatch } from './base_watch'; +import uuid from 'uuid'; +import { WATCH_TYPES, SORT_ORDERS, COMPARATORS } from '../../../../common/constants'; +import { getTimeUnitLabel } from '../../lib/get_time_unit_label'; +import { i18n } from '@kbn/i18n'; +import { aggTypes } from './agg_types'; +import { groupByTypes } from './group_by_types'; +import { comparators } from './comparators'; +const { BETWEEN } = COMPARATORS; +const DEFAULT_VALUES = { + AGG_TYPE: 'count', + TERM_SIZE: 5, + THRESHOLD_COMPARATOR: COMPARATORS.GREATER_THAN, + TIME_WINDOW_SIZE: 5, + TIME_WINDOW_UNIT: 'm', + TRIGGER_INTERVAL_SIZE: 1, + TRIGGER_INTERVAL_UNIT: 'm', + THRESHOLD: [1000, 5000], + GROUP_BY: 'all', +}; + +/** + * {@code ThresholdWatch} allows the user to create a watch by defining a threshold. + */ +export class ThresholdWatch extends BaseWatch { + constructor(props = {}) { + props.id = props.id || uuid.v4(); + props.type = WATCH_TYPES.THRESHOLD; + super(props); + + this.index = props.index; + this.timeField = props.timeField; + this.timeFields = props.timeFields || undefined; + this.triggerIntervalSize = + props.triggerIntervalSize == null + ? DEFAULT_VALUES.TRIGGER_INTERVAL_SIZE + : props.triggerIntervalSize; + this.triggerIntervalUnit = props.triggerIntervalUnit || DEFAULT_VALUES.TRIGGER_INTERVAL_UNIT; + this.aggType = props.aggType || DEFAULT_VALUES.AGG_TYPE; + this.aggField = props.aggField; + this.termSize = props.termSize == null ? DEFAULT_VALUES.TERM_SIZE : props.termSize; + this.termField = props.termField; + this.thresholdComparator = props.thresholdComparator || DEFAULT_VALUES.THRESHOLD_COMPARATOR; + this.timeWindowSize = + props.timeWindowSize == null ? DEFAULT_VALUES.TIME_WINDOW_SIZE : props.timeWindowSize; + this.timeWindowUnit = props.timeWindowUnit || DEFAULT_VALUES.TIME_WINDOW_UNIT; + this.groupBy = props.groupBy || DEFAULT_VALUES.GROUP_BY; + if (this.termField != null) { + this.groupBy = 'top'; + } + + //NOTE: The threshold must be of the appropriate type, i.e.,number/date. + //Conversion from string must occur by consumer when assigning a + //value to this property. + this.threshold = props.threshold == null ? DEFAULT_VALUES.THRESHOLD : props.threshold; + } + + get hasTermsAgg() { + return Boolean(this.termField); + } + + get termOrder() { + return this.thresholdComparator === COMPARATORS.GREATER_THAN + ? SORT_ORDERS.DESCENDING + : SORT_ORDERS.ASCENDING; + } + + get titleDescription() { + const staticPart = i18n.translate( + 'xpack.watcher.models.thresholdWatch.sendAlertOnSpecificConditionTitleDescription', + { + defaultMessage: 'Send an alert when your specified condition is met.', + } + ); + if (isNaN(this.triggerIntervalSize)) { + return staticPart; + } + + const timeUnitLabel = getTimeUnitLabel(this.triggerIntervalUnit, this.triggerIntervalSize); + const dynamicPartText = i18n.translate( + 'xpack.watcher.models.thresholdWatch.thresholdWatchIntervalTitleDescription', + { + defaultMessage: 'Your watch will run every {triggerIntervalSize} {timeUnitLabel}.', + values: { + triggerIntervalSize: this.triggerIntervalSize, + timeUnitLabel, + }, + } + ); + return `${staticPart} ${dynamicPartText}`; + } + validate() { + const validationResult = {}; + const errors = { + name: [], + index: [], + timeField: [], + triggerIntervalSize: [], + aggField: [], + termSize: [], + termField: [], + timeWindowSize: [], + }; + validationResult.errors = errors; + if (!this.name) { + errors.name.push( + i18n.translate('xpack.watcher.sections.watchEdit.threshold.error.requiredNameText', { + defaultMessage: 'Name is required.', + }) + ); + } + if (this.index !== undefined && this.index.length < 1) { + errors.index.push( + i18n.translate( + 'xpack.watcher.sections.watchEdit.threshold.enterOneOrMoreIndicesValidationMessage', + { + defaultMessage: 'Enter one or more indices.', + } + ) + ); + } + if ( + this.index !== undefined && + this.index.length > 0 && + this.timeFields !== undefined && + this.timeFields.length === 1 // first option will have empty value + ) { + errors.index.push( + i18n.translate('xpack.watcher.sections.watchEdit.threshold.invalidIndexValidationMessage', { + defaultMessage: 'Index does not have a time field.', + }) + ); + } + if (!this.timeField) { + errors.timeField.push( + i18n.translate( + 'xpack.watcher.sections.watchEdit.threshold.timeFieldIsRequiredValidationText', + { + defaultMessage: 'A time field is required.', + } + ) + ); + } + if (!this.triggerIntervalSize) { + errors.triggerIntervalSize.push( + i18n.translate( + 'xpack.watcher.sections.watchEdit.threshold.intervalSizeIsRequiredValidationMessage', + { + defaultMessage: 'Interval size is required.', + } + ) + ); + } + if (this.triggerIntervalSize !== undefined && this.triggerIntervalSize < 0) { + errors.triggerIntervalSize.push( + i18n.translate( + 'xpack.watcher.sections.watchEdit.threshold.intervalSizeNegativeNumberValidationMessage', + { + defaultMessage: 'Interval size cannot be a negative number.', + } + ) + ); + } + if (aggTypes[this.aggType].fieldRequired && !this.aggField) { + errors.aggField.push( + i18n.translate( + 'xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage', + { + defaultMessage: 'This field is required.', + } + ) + ); + } + // term field and term size only required if the group by type requires them + if (groupByTypes[this.groupBy].sizeRequired) { + if (!this.termSize) { + errors.termSize.push( + i18n.translate( + 'xpack.watcher.thresholdWatchExpression.aggType.xpack.watcher.thresholdWatchExpression.groupBy.requiredValueValidationMessage', + { + defaultMessage: 'A value is required.', + } + ) + ); + } + if (!this.termField) { + errors.termField.push( + i18n.translate( + 'xpack.watcher.thresholdWatchExpression.groupBy.requiredFieldValidationMessage', + { + defaultMessage: 'This field is required.', + } + ) + ); + } + } + + Array.from(Array(comparators[this.thresholdComparator].requiredValues)).forEach((value, i) => { + const key = `threshold${i}`; + errors[key] = []; + if (this.threshold[i] == null || this.threshold[i] === '') { + errors[key].push( + i18n.translate( + 'xpack.watcher.thresholdWatchExpression.thresholdLevel.valueIsRequiredValidationMessage', + { + defaultMessage: 'A value is required.', + } + ) + ); + } + }); + if ( + this.thresholdComparator === BETWEEN && + this.threshold[0] && + this.threshold[1] && + !(this.threshold[1] > this.threshold[0]) + ) { + errors.threshold1.push( + i18n.translate( + 'xpack.watcher.thresholdWatchExpression.thresholdLevel.secondValueMustBeGreaterMessage', + { + defaultMessage: 'Value must be greater than {lowerBound}.', + values: { + lowerBound: this.threshold[0], + }, + } + ) + ); + } + if (!this.timeWindowSize) { + errors.timeWindowSize.push( + i18n.translate( + 'xpack.watcher.thresholdWatchExpression.timeWindow.durationSizeIsRequiredValidationMessage', + { + defaultMessage: 'Window duration size is required.', + } + ) + ); + } + return validationResult; + } + get upstreamJson() { + const result = super.upstreamJson; + Object.assign(result, { + index: this.index, + timeField: this.timeField, + triggerIntervalSize: this.triggerIntervalSize, + triggerIntervalUnit: this.triggerIntervalUnit, + aggType: this.aggType, + aggField: this.aggField, + termSize: this.termSize, + termField: this.termField, + termOrder: this.termOrder, + thresholdComparator: this.thresholdComparator, + timeWindowSize: this.timeWindowSize, + timeWindowUnit: this.timeWindowUnit, + hasTermsAgg: this.hasTermsAgg, + threshold: + comparators[this.thresholdComparator].requiredValues > 1 + ? this.threshold + : this.threshold[0], + }); + + return result; + } + + static fromUpstreamJson(upstreamWatch) { + return new ThresholdWatch(upstreamWatch); + } + + get DEFAULT_VALUES() { + return DEFAULT_VALUES; + } + + static typeName = i18n.translate('xpack.watcher.models.thresholdWatch.typeName', { + defaultMessage: 'Threshold Alert', + }); + static iconClass = ''; + static selectMessage = i18n.translate('xpack.watcher.models.thresholdWatch.selectMessageText', { + defaultMessage: 'Send an alert on a specific condition', + }); + static isCreatable = true; + static selectSortOrder = 1; +} diff --git a/x-pack/plugins/watcher/public/application/models/watch/watch.js b/x-pack/plugins/watcher/public/application/models/watch/watch.js new file mode 100644 index 00000000000000..934d1e338ed0c6 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch/watch.js @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get, set } from 'lodash'; +import { WATCH_TYPES } from '../../../../common/constants'; +import { JsonWatch } from './json_watch'; +import { ThresholdWatch } from './threshold_watch'; +import { MonitoringWatch } from './monitoring_watch'; + +const WatchTypes = {}; +set(WatchTypes, WATCH_TYPES.JSON, JsonWatch); +set(WatchTypes, WATCH_TYPES.THRESHOLD, ThresholdWatch); +set(WatchTypes, WATCH_TYPES.MONITORING, MonitoringWatch); + +export class Watch { + static getWatchTypes = () => { + return WatchTypes; + }; + + static fromUpstreamJson(upstreamWatch = {}) { + const type = get(upstreamWatch, 'type'); + const WatchType = WatchTypes[type]; + + Object.assign(upstreamWatch, { + isNew: false, + }); + + return WatchType.fromUpstreamJson(upstreamWatch); + } +} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_errors/index.js b/x-pack/plugins/watcher/public/application/models/watch_errors/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_errors/index.js rename to x-pack/plugins/watcher/public/application/models/watch_errors/index.js diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_errors/watch_errors.js b/x-pack/plugins/watcher/public/application/models/watch_errors/watch_errors.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_errors/watch_errors.js rename to x-pack/plugins/watcher/public/application/models/watch_errors/watch_errors.js diff --git a/x-pack/plugins/watcher/public/application/models/watch_history_item/index.d.ts b/x-pack/plugins/watcher/public/application/models/watch_history_item/index.d.ts new file mode 100644 index 00000000000000..48fe71e2c55c03 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch_history_item/index.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const WatchHistoryItem: any; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_history_item/index.js b/x-pack/plugins/watcher/public/application/models/watch_history_item/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_history_item/index.js rename to x-pack/plugins/watcher/public/application/models/watch_history_item/index.js diff --git a/x-pack/plugins/watcher/public/application/models/watch_history_item/watch_history_item.js b/x-pack/plugins/watcher/public/application/models/watch_history_item/watch_history_item.js new file mode 100644 index 00000000000000..36fa9fa5aefe27 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch_history_item/watch_history_item.js @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import 'moment-duration-format'; +import { get } from 'lodash'; +import { getMoment } from '../../../../common/lib/get_moment'; +import { WatchStatus } from '../watch_status'; + +export class WatchHistoryItem { + constructor(props = {}) { + this.id = props.id; + this.watchId = props.watchId; + this.details = props.details; + this.startTime = getMoment(props.startTime); + this.watchStatus = WatchStatus.fromUpstreamJson(get(props, 'watchStatus')); + } + + static fromUpstreamJson(upstreamHistory) { + return new WatchHistoryItem(upstreamHistory); + } +} diff --git a/x-pack/plugins/watcher/public/application/models/watch_status/index.d.ts b/x-pack/plugins/watcher/public/application/models/watch_status/index.d.ts new file mode 100644 index 00000000000000..f8ff6889612992 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch_status/index.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const WatchStatus: any; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_status/index.js b/x-pack/plugins/watcher/public/application/models/watch_status/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/models/watch_status/index.js rename to x-pack/plugins/watcher/public/application/models/watch_status/index.js diff --git a/x-pack/plugins/watcher/public/application/models/watch_status/watch_status.js b/x-pack/plugins/watcher/public/application/models/watch_status/watch_status.js new file mode 100644 index 00000000000000..8cbdc1b5b30cc8 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch_status/watch_status.js @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get } from 'lodash'; +import { getMoment } from '../../../../common/lib/get_moment'; +import { ActionStatus } from '../action_status'; + +export class WatchStatus { + constructor(props = {}) { + this.id = get(props, 'id'); + this.state = get(props, 'state'); + this.comment = get(props, 'comment'); + this.isActive = get(props, 'isActive'); + this.lastFired = getMoment(get(props, 'lastFired')); + this.lastChecked = getMoment(get(props, 'lastChecked')); + this.lastMetCondition = getMoment(get(props, 'lastMetCondition')); + + if (this.lastFired) { + this.lastFiredHumanized = this.lastFired.fromNow(); + } + + if (this.lastChecked) { + this.lastCheckedHumanized = this.lastChecked.fromNow(); + } + + const actionStatuses = get(props, 'actionStatuses', []); + this.actionStatuses = actionStatuses.map(actionStatus => + ActionStatus.fromUpstreamJson(actionStatus) + ); + } + + static fromUpstreamJson(upstreamWatchStatus) { + return new WatchStatus(upstreamWatchStatus); + } +} diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/index.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/index.ts rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/index.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx similarity index 92% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx index 010e430c0719a1..b87fc355c3eade 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit.tsx @@ -16,10 +16,10 @@ import { EuiTitle, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ExecuteDetails } from 'plugins/watcher/np_ready/application/models/execute_details/execute_details'; -import { getActionType } from '../../../../../../../common/lib/get_action_type'; -import { BaseWatch, ExecutedWatchDetails } from '../../../../../../../common/types/watch_types'; -import { ACTION_MODES, TIME_UNITS } from '../../../../../../../common/constants'; +import { ExecuteDetails } from '../../../../models/execute_details'; +import { getActionType } from '../../../../../../common/lib/get_action_type'; +import { BaseWatch, ExecutedWatchDetails } from '../../../../../../common/types/watch_types'; +import { ACTION_MODES, TIME_UNITS } from '../../../../../../common/constants'; import { JsonWatchEditForm } from './json_watch_edit_form'; import { JsonWatchEditSimulate } from './json_watch_edit_simulate'; import { WatchContext } from '../../watch_context'; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx similarity index 99% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx index 376aeb205b855c..91185ac604b345 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { serializeJsonWatch } from '../../../../../../../common/lib/serialization'; +import { serializeJsonWatch } from '../../../../../../common/lib/serialization'; import { ErrableFormRow, SectionError, Error as ServerError } from '../../../../components'; import { onWatchSave } from '../../watch_edit_actions'; import { WatchContext } from '../../watch_context'; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx similarity index 97% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx index 9ea2b3bcd1e9a4..8bb1770d2f44da 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx @@ -24,13 +24,15 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ExecuteDetails } from 'plugins/watcher/np_ready/application/models/execute_details/execute_details'; -import { WatchHistoryItem } from 'plugins/watcher/np_ready/application/models/watch_history_item'; -import { ACTION_MODES, TIME_UNITS } from '../../../../../../../common/constants'; + +import { WatchHistoryItem } from '../../../../models/watch_history_item'; + +import { ACTION_MODES, TIME_UNITS } from '../../../../../../common/constants'; +import { ExecuteDetails } from '../../../../models/execute_details'; import { ExecutedWatchDetails, ExecutedWatchResults, -} from '../../../../../../../common/types/watch_types'; +} from '../../../../../../common/types/watch_types'; import { ErrableFormRow } from '../../../../components/form_errors'; import { executeWatch } from '../../../../lib/api'; import { WatchContext } from '../../watch_context'; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate_results.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate_results.tsx similarity index 99% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate_results.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate_results.tsx index c3f11c6c3fa465..0a61e4401fdf12 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate_results.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate_results.tsx @@ -21,7 +21,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { ExecutedWatchDetails, ExecutedWatchResults, -} from '../../../../../../../common/types/watch_types'; +} from '../../../../../../common/types/watch_types'; import { getTypeFromAction } from '../../watch_edit_actions'; import { WatchContext } from '../../watch_context'; import { WatchStatus, SectionError } from '../../../../components'; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/monitoring_watch_edit/index.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/monitoring_watch_edit/index.ts rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/index.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/monitoring_watch_edit/monitoring_watch_edit.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/request_flyout.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/request_flyout.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/request_flyout.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/request_flyout.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/email_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/email_action_fields.tsx similarity index 97% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/email_action_fields.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/email_action_fields.tsx index 3e70e49f423504..a94055271ff5b8 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/email_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/email_action_fields.tsx @@ -8,7 +8,7 @@ import React, { Fragment } from 'react'; import { EuiComboBox, EuiFieldText, EuiFormRow, EuiTextArea } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ErrableFormRow } from '../../../../../components/form_errors'; -import { EmailAction } from '../../../../../../../../common/types/action_types'; +import { EmailAction } from '../../../../../../../common/types/action_types'; interface Props { action: EmailAction; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index.ts rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index_action_fields.tsx similarity index 94% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index_action_fields.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index_action_fields.tsx index b7ab76d9890bcf..f1d36bce415d3e 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/index_action_fields.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiFieldText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ErrableFormRow } from '../../../../../components/form_errors'; -import { IndexAction } from '../../../../../../../../common/types/action_types'; +import { IndexAction } from '../../../../../../../common/types/action_types'; interface Props { action: IndexAction; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/jira_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/jira_action_fields.tsx similarity index 97% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/jira_action_fields.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/jira_action_fields.tsx index c09b3c44fde65c..2bfc4f2eb1b5d3 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/jira_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/jira_action_fields.tsx @@ -8,7 +8,7 @@ import React, { Fragment } from 'react'; import { EuiFieldText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ErrableFormRow } from '../../../../../components/form_errors'; -import { JiraAction } from '../../../../../../../../common/types/action_types'; +import { JiraAction } from '../../../../../../../common/types/action_types'; interface Props { action: JiraAction; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/logging_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/logging_action_fields.tsx similarity index 94% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/logging_action_fields.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/logging_action_fields.tsx index 7da2a22ecd6c45..17c69a7b05bb3c 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/logging_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/logging_action_fields.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiFieldText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ErrableFormRow } from '../../../../../components/form_errors'; -import { LoggingAction } from '../../../../../../../../common/types/action_types'; +import { LoggingAction } from '../../../../../../../common/types/action_types'; interface Props { action: LoggingAction; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/pagerduty_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/pagerduty_action_fields.tsx similarity index 95% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/pagerduty_action_fields.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/pagerduty_action_fields.tsx index 3287bdefa08aa5..95215e8eac763d 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/pagerduty_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/pagerduty_action_fields.tsx @@ -7,7 +7,7 @@ import React, { Fragment } from 'react'; import { EuiFieldText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ErrableFormRow } from '../../../../../components/form_errors'; -import { PagerDutyAction } from '../../../../../../../../common/types/action_types'; +import { PagerDutyAction } from '../../../../../../../common/types/action_types'; interface Props { action: PagerDutyAction; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/slack_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/slack_action_fields.tsx similarity index 96% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/slack_action_fields.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/slack_action_fields.tsx index a72cf232d8d093..5e8aaf8415898a 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/slack_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/slack_action_fields.tsx @@ -6,7 +6,7 @@ import React, { Fragment } from 'react'; import { EuiComboBox, EuiTextArea, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { SlackAction } from '../../../../../../../../common/types/action_types'; +import { SlackAction } from '../../../../../../../common/types/action_types'; interface Props { action: SlackAction; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx similarity index 98% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx index be0b551f4a39c8..c1ebcdc2628637 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ErrableFormRow } from '../../../../../components/form_errors'; -import { WebhookAction } from '../../../../../../../../common/types/action_types'; +import { WebhookAction } from '../../../../../../../common/types/action_types'; interface Props { action: WebhookAction; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/index.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/index.ts rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/index.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_accordion.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_accordion.tsx similarity index 94% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_accordion.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_accordion.tsx index 4fca772a182175..36ca706ed1be2c 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_accordion.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_accordion.tsx @@ -21,13 +21,16 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ExecuteDetails } from 'plugins/watcher/np_ready/application/models/execute_details/execute_details'; -import { Action } from 'plugins/watcher/np_ready/application/models/action'; -import { WatchHistoryItem } from 'plugins/watcher/np_ready/application/models/watch_history_item'; -import { ThresholdWatch } from 'plugins/watcher/np_ready/application/models/watch/threshold_watch'; -import { ActionType } from '../../../../../../../common/types/action_types'; -import { ACTION_TYPES, ACTION_MODES } from '../../../../../../../common/constants'; + +import { Action } from '../../../../models/action'; +import { WatchHistoryItem } from '../../../../models/watch_history_item'; +import { ThresholdWatch } from '../../../../models/watch/threshold_watch'; +import { ExecuteDetails } from '../../../../models/execute_details'; + +import { ActionType } from '../../../../../../common/types/action_types'; +import { ACTION_TYPES, ACTION_MODES } from '../../../../../../common/constants'; import { WatchContext } from '../../watch_context'; + import { WebhookActionFields, LoggingActionFields, diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_dropdown.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_dropdown.tsx similarity index 96% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_dropdown.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_dropdown.tsx index d92cccfa00f148..7a760ee58acbc9 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_dropdown.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_dropdown.tsx @@ -16,9 +16,10 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useContext, useState } from 'react'; -import { Action } from 'plugins/watcher/np_ready/application/models/action'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ACTION_TYPES } from '../../../../../../../common/constants'; + +import { Action } from '../../../../models/action'; +import { ACTION_TYPES } from '../../../../../../common/constants'; import { WatchContext } from '../../watch_context'; const disabledMessage = i18n.translate( diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_panel.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_panel.tsx similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_panel.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_panel.tsx diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx similarity index 99% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx index f1b5d2c9eab7b8..e3d729c33fddff 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx @@ -26,8 +26,8 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { TIME_UNITS } from '../../../../../../../common/constants'; -import { serializeThresholdWatch } from '../../../../../../../common/lib/serialization'; +import { TIME_UNITS } from '../../../../../../common/constants'; +import { serializeThresholdWatch } from '../../../../../../common/lib/serialization'; import { ErrableFormRow, SectionError, Error as ServerError } from '../../../../components'; import { fetchFields, getMatchingIndices, loadIndexPatterns } from '../../../../lib/api'; import { aggTypes } from '../../../../models/watch/agg_types'; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/watch_visualization.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/watch_visualization.tsx similarity index 93% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/watch_visualization.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/watch_visualization.tsx index 3901f84f506ef6..35d9efd36ad0fe 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/threshold_watch_edit/watch_visualization.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/watch_visualization.tsx @@ -17,11 +17,12 @@ import { } from '@elastic/charts'; import dateMath from '@elastic/datemath'; import moment from 'moment-timezone'; -import { IUiSettingsClient } from 'src/core/public'; +import { IUiSettingsClient } from 'kibana/public'; import { EuiCallOut, EuiLoadingChart, EuiSpacer, EuiEmptyPrompt, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisualizeOptions } from 'plugins/watcher/np_ready/application/models/visualize_options'; -import { ThresholdWatch } from 'plugins/watcher/np_ready/application/models/watch/threshold_watch'; + +import { VisualizeOptions } from '../../../../models/visualize_options'; +import { ThresholdWatch } from '../../../../models/watch/threshold_watch'; import { useGetWatchVisualizationData } from '../../../../lib/api'; import { WatchContext } from '../../watch_context'; @@ -85,11 +86,7 @@ const getTimeBuckets = (watch: any, timeBuckets: any) => { }; export const WatchVisualization = () => { - const { - legacy: { TimeBuckets }, - euiUtils, - uiSettings, - } = useAppContext(); + const { createTimeBuckets, euiUtils, uiSettings } = useAppContext(); const { watch } = useContext(WatchContext); const chartsTheme = euiUtils.useChartsTheme(); const { @@ -109,7 +106,7 @@ export const WatchVisualization = () => { } = watch; const domain = getDomain(watch); - const timeBuckets = new TimeBuckets(); + const timeBuckets = createTimeBuckets(); timeBuckets.setBounds(domain); const interval = timeBuckets.getInterval().expression; const visualizeOptions = new VisualizeOptions({ @@ -196,8 +193,8 @@ export const WatchVisualization = () => { const actualThreshold = getThreshold(watch); let maxY = actualThreshold[actualThreshold.length - 1]; - (Object.values(watchVisualizationData) as number[][][]).forEach(data => { - data.forEach(([, y]) => { + (Object.values(watchVisualizationData) as number[][][]).forEach(watchData => { + watchData.forEach(([, y]) => { if (y > maxY) { maxY = y; } @@ -206,7 +203,7 @@ export const WatchVisualization = () => { const dateFormatter = (d: number) => { return moment(d) .tz(timezone) - .format(getTimeBuckets(watch, new TimeBuckets()).getScaledDateFormat()); + .format(getTimeBuckets(watch, createTimeBuckets()).getScaledDateFormat()); }; const aggLabel = aggTypes[watch.aggType].text; return ( diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/watch_edit.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/watch_edit.tsx similarity index 94% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/watch_edit.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_edit/components/watch_edit.tsx index 9f252d3e542e0e..59a6079d74b428 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/components/watch_edit.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/watch_edit.tsx @@ -10,10 +10,10 @@ import { isEqual } from 'lodash'; import { EuiPageContent } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { Watch } from 'plugins/watcher/np_ready/application/models/watch'; import { FormattedMessage } from '@kbn/i18n/react'; -import { WATCH_TYPES } from '../../../../../../common/constants'; -import { BaseWatch } from '../../../../../../common/types/watch_types'; +import { Watch } from '../../../models/watch'; +import { WATCH_TYPES } from '../../../../../common/constants'; +import { BaseWatch } from '../../../../../common/types/watch_types'; import { getPageErrorCode, PageError, SectionLoading, SectionError } from '../../../components'; import { loadWatch } from '../../../lib/api'; import { listBreadcrumb, editBreadcrumb, createBreadcrumb } from '../../../lib/breadcrumbs'; @@ -96,10 +96,7 @@ export const WatchEdit = ({ }; }) => { // hooks - const { - legacy: { MANAGEMENT_BREADCRUMB }, - chrome, - } = useAppContext(); + const { MANAGEMENT_BREADCRUMB, chrome } = useAppContext(); const [{ watch, loadError }, dispatch] = useReducer(watchReducer, { watch: null }); const setWatchProperty = (property: string, value: any) => { diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/watch_context.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/watch_context.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/watch_context.ts rename to x-pack/plugins/watcher/public/application/sections/watch_edit/watch_context.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/watch_edit_actions.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/watch_edit_actions.ts similarity index 95% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/watch_edit_actions.ts rename to x-pack/plugins/watcher/public/application/sections/watch_edit/watch_edit_actions.ts index b93c2c510047db..ba2a3a7ce84e50 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_edit/watch_edit_actions.ts +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/watch_edit_actions.ts @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ToastsSetup } from 'src/core/public'; +import { ToastsSetup } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; -import { ACTION_TYPES, WATCH_TYPES } from '../../../../../common/constants'; -import { BaseWatch } from '../../../../../common/types/watch_types'; +import { ACTION_TYPES, WATCH_TYPES } from '../../../../common/constants'; +import { BaseWatch } from '../../../../common/types/watch_types'; import { createWatch } from '../../lib/api'; import { goToWatchList } from '../../lib/navigation'; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_list/components/watch_list.tsx b/x-pack/plugins/watcher/public/application/sections/watch_list/components/watch_list.tsx similarity index 99% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_list/components/watch_list.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_list/components/watch_list.tsx index 5165915aa84065..9f6a8ddbc843e8 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_list/components/watch_list.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_list/components/watch_list.tsx @@ -28,7 +28,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { Moment } from 'moment'; -import { REFRESH_INTERVALS, PAGINATION, WATCH_TYPES } from '../../../../../../common/constants'; +import { REFRESH_INTERVALS, PAGINATION, WATCH_TYPES } from '../../../../../common/constants'; import { listBreadcrumb } from '../../../lib/breadcrumbs'; import { getPageErrorCode, @@ -47,7 +47,7 @@ export const WatchList = () => { // hooks const { chrome, - legacy: { MANAGEMENT_BREADCRUMB }, + MANAGEMENT_BREADCRUMB, links: { watcherGettingStartedUrl }, } = useAppContext(); const [selection, setSelection] = useState([]); diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_detail.tsx b/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_detail.tsx similarity index 99% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_detail.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_detail.tsx index 197342bba4180c..ce52114fd5fdfd 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_detail.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_detail.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { ackWatchAction } from '../../../lib/api'; import { WatchStatus } from '../../../components'; -import { PAGINATION } from '../../../../../../common/constants'; +import { PAGINATION } from '../../../../../common/constants'; import { WatchDetailsContext } from '../watch_details_context'; import { useAppContext } from '../../../app_context'; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_history.tsx b/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_history.tsx similarity index 99% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_history.tsx rename to x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_history.tsx index 16897d74665ef7..b78a2e4230171f 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/components/watch_history.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_history.tsx @@ -23,7 +23,7 @@ import { EuiTitle, } from '@elastic/eui'; -import { PAGINATION } from '../../../../../../common/constants'; +import { PAGINATION } from '../../../../../common/constants'; import { WatchStatus, SectionError, Error } from '../../../components'; import { useLoadWatchHistory, useLoadWatchHistoryDetail } from '../../../lib/api'; import { WatchDetailsContext } from '../watch_details_context'; diff --git a/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_status.tsx b/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_status.tsx new file mode 100644 index 00000000000000..b15c047d06f67c --- /dev/null +++ b/x-pack/plugins/watcher/public/application/sections/watch_status/components/watch_status.tsx @@ -0,0 +1,254 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useEffect, useState } from 'react'; +import { + EuiPageContent, + EuiSpacer, + EuiTabs, + EuiTab, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiToolTip, + EuiBadge, + EuiButtonEmpty, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { WatchDetail } from './watch_detail'; +import { WatchHistory } from './watch_history'; +import { listBreadcrumb, statusBreadcrumb } from '../../../lib/breadcrumbs'; +import { useLoadWatchDetail, deactivateWatch, activateWatch } from '../../../lib/api'; +import { WatchDetailsContext } from '../watch_details_context'; +import { + getPageErrorCode, + PageError, + SectionLoading, + DeleteWatchesModal, +} from '../../../components'; +import { goToWatchList } from '../../../lib/navigation'; +import { useAppContext } from '../../../app_context'; + +interface WatchStatusTab { + id: string; + name: string; +} + +const WATCH_EXECUTION_HISTORY_TAB = 'watchExecutionHistoryTab'; +const WATCH_ACTIONS_TAB = 'watchActionsTab'; + +const WATCH_STATUS_TABS: WatchStatusTab[] = [ + { + id: WATCH_EXECUTION_HISTORY_TAB, + name: i18n.translate('xpack.watcher.sections.watchStatus.executionHistoryTabLabel', { + defaultMessage: 'Execution history', + }), + }, + { + id: WATCH_ACTIONS_TAB, + name: i18n.translate('xpack.watcher.sections.watchStatus.actionsTabLabel', { + defaultMessage: 'Action statuses', + }), + }, +]; + +export const WatchStatus = ({ + match: { + params: { id }, + }, +}: { + match: { + params: { + id: string; + }; + }; +}) => { + const { chrome, MANAGEMENT_BREADCRUMB, toasts } = useAppContext(); + const { + error: watchDetailError, + data: watchDetail, + isLoading: isWatchDetailLoading, + } = useLoadWatchDetail(id); + + const [selectedTab, setSelectedTab] = useState(WATCH_EXECUTION_HISTORY_TAB); + const [isActivated, setIsActivated] = useState(undefined); + const [watchesToDelete, setWatchesToDelete] = useState([]); + const [isTogglingActivation, setIsTogglingActivation] = useState(false); + + useEffect(() => { + chrome.setBreadcrumbs([MANAGEMENT_BREADCRUMB, listBreadcrumb, statusBreadcrumb]); + }, [id, chrome, MANAGEMENT_BREADCRUMB]); + + const errorCode = getPageErrorCode(watchDetailError); + + if (isWatchDetailLoading) { + return ( + + + + ); + } + + if (errorCode) { + return ( + + + + ); + } + + if (watchDetail) { + const { isSystemWatch, id: watchId, watchStatus, name: watchName } = watchDetail; + + if (isActivated === undefined) { + // Set initial value for isActivated based on the watch we just loaded. + setIsActivated(typeof watchStatus.isActive !== 'undefined' ? watchStatus.isActive : false); + } + + const activationButtonText = isActivated ? ( + + ) : ( + + ); + + const toggleWatchActivation = async () => { + const toggleActivation = isActivated ? deactivateWatch : activateWatch; + + setIsTogglingActivation(true); + + const { error } = await toggleActivation(watchId); + + setIsTogglingActivation(false); + + if (error) { + const message = isActivated + ? i18n.translate( + 'xpack.watcher.sections.watchList.toggleActivatationErrorNotification.deactivateDescriptionText', + { + defaultMessage: "Couldn't deactivate watch", + } + ) + : i18n.translate( + 'xpack.watcher.sections.watchList.toggleActivatationErrorNotification.activateDescriptionText', + { + defaultMessage: "Couldn't activate watch", + } + ); + return toasts.addDanger(message); + } + + setIsActivated(!isActivated); + }; + + return ( + + + { + if (deleted) { + goToWatchList(); + } + setWatchesToDelete([]); + }} + watchesToDelete={watchesToDelete} + /> + + + +

    + +

    +
    +
    + {isSystemWatch ? ( + + + } + > + + + + + + ) : ( + + + + toggleWatchActivation()} + isLoading={isTogglingActivation} + > + {activationButtonText} + + + + { + setWatchesToDelete([watchId]); + }} + color="danger" + disabled={false} + > + + + + + + )} +
    + + + {WATCH_STATUS_TABS.map((tab, index) => ( + { + setSelectedTab(tab.id); + }} + isSelected={tab.id === selectedTab} + key={index} + data-test-subj="tab" + > + {tab.name} + + ))} + + + {selectedTab === WATCH_ACTIONS_TAB ? : } +
    +
    + ); + } + + return null; +}; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/watch_details_context.ts b/x-pack/plugins/watcher/public/application/sections/watch_status/watch_details_context.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/sections/watch_status/watch_details_context.ts rename to x-pack/plugins/watcher/public/application/sections/watch_status/watch_details_context.ts diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/application/shared_imports.ts b/x-pack/plugins/watcher/public/application/shared_imports.ts similarity index 79% rename from x-pack/legacy/plugins/watcher/public/np_ready/application/shared_imports.ts rename to x-pack/plugins/watcher/public/application/shared_imports.ts index 60445b00c09858..cbc4dde7448ff0 100644 --- a/x-pack/legacy/plugins/watcher/public/np_ready/application/shared_imports.ts +++ b/x-pack/plugins/watcher/public/application/shared_imports.ts @@ -10,4 +10,4 @@ export { UseRequestConfig, sendRequest, useRequest, -} from '../../../../../../../src/plugins/es_ui_shared/public/request/np_ready_request'; +} from '../../../../../src/plugins/es_ui_shared/public/request/np_ready_request'; diff --git a/x-pack/legacy/plugins/watcher/public/np_ready/index.ts b/x-pack/plugins/watcher/public/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/public/np_ready/index.ts rename to x-pack/plugins/watcher/public/index.ts diff --git a/x-pack/plugins/watcher/public/legacy/calc_auto_interval.ts b/x-pack/plugins/watcher/public/legacy/calc_auto_interval.ts new file mode 100644 index 00000000000000..c910f1e6752d4a --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/calc_auto_interval.ts @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import moment from 'moment'; + +const boundsDescending = [ + { + bound: Infinity, + interval: Number(moment.duration(1, 'year')), + }, + { + bound: Number(moment.duration(1, 'year')), + interval: Number(moment.duration(1, 'month')), + }, + { + bound: Number(moment.duration(3, 'week')), + interval: Number(moment.duration(1, 'week')), + }, + { + bound: Number(moment.duration(1, 'week')), + interval: Number(moment.duration(1, 'd')), + }, + { + bound: Number(moment.duration(24, 'hour')), + interval: Number(moment.duration(12, 'hour')), + }, + { + bound: Number(moment.duration(6, 'hour')), + interval: Number(moment.duration(3, 'hour')), + }, + { + bound: Number(moment.duration(2, 'hour')), + interval: Number(moment.duration(1, 'hour')), + }, + { + bound: Number(moment.duration(45, 'minute')), + interval: Number(moment.duration(30, 'minute')), + }, + { + bound: Number(moment.duration(20, 'minute')), + interval: Number(moment.duration(10, 'minute')), + }, + { + bound: Number(moment.duration(9, 'minute')), + interval: Number(moment.duration(5, 'minute')), + }, + { + bound: Number(moment.duration(3, 'minute')), + interval: Number(moment.duration(1, 'minute')), + }, + { + bound: Number(moment.duration(45, 'second')), + interval: Number(moment.duration(30, 'second')), + }, + { + bound: Number(moment.duration(15, 'second')), + interval: Number(moment.duration(10, 'second')), + }, + { + bound: Number(moment.duration(7.5, 'second')), + interval: Number(moment.duration(5, 'second')), + }, + { + bound: Number(moment.duration(5, 'second')), + interval: Number(moment.duration(1, 'second')), + }, + { + bound: Number(moment.duration(500, 'ms')), + interval: Number(moment.duration(100, 'ms')), + }, +]; + +function getPerBucketMs(count: number, duration: number) { + const ms = duration / count; + return isFinite(ms) ? ms : NaN; +} + +function normalizeMinimumInterval(targetMs: number) { + const value = isNaN(targetMs) ? 0 : Math.max(Math.floor(targetMs), 1); + return moment.duration(value); +} + +/** + * Using some simple rules we pick a "pretty" interval that will + * produce around the number of buckets desired given a time range. + * + * @param targetBucketCount desired number of buckets + * @param duration time range the agg covers + */ +export function calcAutoIntervalNear(targetBucketCount: number, duration: number) { + const targetPerBucketMs = getPerBucketMs(targetBucketCount, duration); + + // Find the first bound which is smaller than our target. + const lowerBoundIndex = boundsDescending.findIndex(({ bound }) => { + const boundMs = Number(bound); + return boundMs <= targetPerBucketMs; + }); + + // The bound immediately preceeding that lower bound contains the + // interval most closely matching our target. + if (lowerBoundIndex !== -1) { + const nearestInterval = boundsDescending[lowerBoundIndex - 1].interval; + return moment.duration(nearestInterval); + } + + // If the target is smaller than any of our bounds, then we'll use it for the interval as-is. + return normalizeMinimumInterval(targetPerBucketMs); +} + +/** + * Pick a "pretty" interval that produces no more than the maxBucketCount + * for the given time range. + * + * @param maxBucketCount maximum number of buckets to create + * @param duration amount of time covered by the agg + */ +export function calcAutoIntervalLessThan(maxBucketCount: number, duration: number) { + const maxPerBucketMs = getPerBucketMs(maxBucketCount, duration); + + for (const { interval } of boundsDescending) { + // Find the highest interval which meets our per bucket limitation. + if (interval <= maxPerBucketMs) { + return moment.duration(interval); + } + } + + // If the max is smaller than any of our intervals, then we'll use it for the interval as-is. + return normalizeMinimumInterval(maxPerBucketMs); +} diff --git a/x-pack/plugins/watcher/public/legacy/calc_es_interval.js b/x-pack/plugins/watcher/public/legacy/calc_es_interval.js new file mode 100644 index 00000000000000..234fb67772fef8 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/calc_es_interval.js @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import dateMath from '@elastic/datemath'; + +import { parseEsInterval } from './index'; + +const unitsDesc = dateMath.unitsDesc; +const largeMax = unitsDesc.indexOf('M'); + +/** + * Convert a moment.duration into an es + * compatible expression, and provide + * associated metadata + * + * @param {moment.duration} duration + * @return {object} + */ +export function convertDurationToNormalizedEsInterval(duration) { + for (let i = 0; i < unitsDesc.length; i++) { + const unit = unitsDesc[i]; + const val = duration.as(unit); + // find a unit that rounds neatly + if (val >= 1 && Math.floor(val) === val) { + // if the unit is "large", like years, but + // isn't set to 1 ES will puke. So keep going until + // we get out of the "large" units + if (i <= largeMax && val !== 1) { + continue; + } + + return { + value: val, + unit: unit, + expression: val + unit, + }; + } + } + + const ms = duration.as('ms'); + return { + value: ms, + unit: 'ms', + expression: ms + 'ms', + }; +} + +export function convertIntervalToEsInterval(interval) { + const { value, unit } = parseEsInterval(interval); + return { + value, + unit, + expression: interval, + }; +} diff --git a/x-pack/plugins/watcher/public/legacy/index.d.ts b/x-pack/plugins/watcher/public/legacy/index.d.ts new file mode 100644 index 00000000000000..307e365040fb7d --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/index.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export declare const MANAGEMENT_BREADCRUMB: { text: string; href?: string }; diff --git a/x-pack/plugins/watcher/public/legacy/index.ts b/x-pack/plugins/watcher/public/legacy/index.ts new file mode 100644 index 00000000000000..d14081a667acc4 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { i18n } from '@kbn/i18n'; + +export { TimeBuckets } from './time_buckets'; + +export const MANAGEMENT_BREADCRUMB = Object.freeze({ + text: i18n.translate('xpack.watcher.management.breadcrumb', { + defaultMessage: 'Management', + }), + href: '#/management', +}); diff --git a/x-pack/plugins/watcher/public/legacy/parse_es_interval/index.ts b/x-pack/plugins/watcher/public/legacy/parse_es_interval/index.ts new file mode 100644 index 00000000000000..6c8e29211078c5 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/parse_es_interval/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { parseEsInterval, ParsedInterval } from './parse_es_interval'; +export { InvalidEsCalendarIntervalError } from './invalid_es_calendar_interval_error'; +export { InvalidEsIntervalFormatError } from './invalid_es_interval_format_error'; +export { isValidEsInterval } from './is_valid_es_interval'; diff --git a/x-pack/plugins/watcher/public/legacy/parse_es_interval/invalid_es_calendar_interval_error.ts b/x-pack/plugins/watcher/public/legacy/parse_es_interval/invalid_es_calendar_interval_error.ts new file mode 100644 index 00000000000000..62864c91756c48 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/parse_es_interval/invalid_es_calendar_interval_error.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Unit } from '@elastic/datemath'; +import { i18n } from '@kbn/i18n'; + +export class InvalidEsCalendarIntervalError extends Error { + constructor( + public readonly interval: string, + public readonly value: number, + public readonly unit: Unit, + public readonly type: string + ) { + super( + i18n.translate('xpack.watcher.data.parseEsInterval.invalidEsCalendarIntervalErrorMessage', { + defaultMessage: 'Invalid calendar interval: {interval}, value must be 1', + values: { interval }, + }) + ); + + this.name = 'InvalidEsCalendarIntervalError'; + this.value = value; + this.unit = unit; + this.type = type; + + // captureStackTrace is only available in the V8 engine, so any browser using + // a different JS engine won't have access to this method. + if (Error.captureStackTrace) { + Error.captureStackTrace(this, InvalidEsCalendarIntervalError); + } + + // Babel doesn't support traditional `extends` syntax for built-in classes. + // https://babeljs.io/docs/en/caveats/#classes + Object.setPrototypeOf(this, InvalidEsCalendarIntervalError.prototype); + } +} diff --git a/x-pack/plugins/watcher/public/legacy/parse_es_interval/invalid_es_interval_format_error.ts b/x-pack/plugins/watcher/public/legacy/parse_es_interval/invalid_es_interval_format_error.ts new file mode 100644 index 00000000000000..894a4fd5d69224 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/parse_es_interval/invalid_es_interval_format_error.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export class InvalidEsIntervalFormatError extends Error { + constructor(public readonly interval: string) { + super( + i18n.translate('xpack.watcher.data.parseEsInterval.invalidEsIntervalFormatErrorMessage', { + defaultMessage: 'Invalid interval format: {interval}', + values: { interval }, + }) + ); + + this.name = 'InvalidEsIntervalFormatError'; + + // captureStackTrace is only available in the V8 engine, so any browser using + // a different JS engine won't have access to this method. + if (Error.captureStackTrace) { + Error.captureStackTrace(this, InvalidEsIntervalFormatError); + } + + // Babel doesn't support traditional `extends` syntax for built-in classes. + // https://babeljs.io/docs/en/caveats/#classes + Object.setPrototypeOf(this, InvalidEsIntervalFormatError.prototype); + } +} diff --git a/x-pack/plugins/watcher/public/legacy/parse_es_interval/is_valid_es_interval.ts b/x-pack/plugins/watcher/public/legacy/parse_es_interval/is_valid_es_interval.ts new file mode 100644 index 00000000000000..1bdb65740409a2 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/parse_es_interval/is_valid_es_interval.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { parseEsInterval } from './parse_es_interval'; + +/** + * Checks whether a given interval string (e.g. 1w, 24h, ...) is a valid Elasticsearch interval. + * Will return false if the interval is not valid in Elasticsearch, otherwise true. + * Invalid intervals might be: 2f, since there is no unit 'f'; 2w, since weeks and month intervals + * are only allowed with a value of 1, etc. + * + * @param interval The interval string like 1w, 24h + * @returns True if the interval is valid for Elasticsearch + */ +export function isValidEsInterval(interval: string): boolean { + try { + parseEsInterval(interval); + return true; + } catch { + return false; + } +} diff --git a/x-pack/plugins/watcher/public/legacy/parse_es_interval/parse_es_interval.test.ts b/x-pack/plugins/watcher/public/legacy/parse_es_interval/parse_es_interval.test.ts new file mode 100644 index 00000000000000..76de807101559b --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/parse_es_interval/parse_es_interval.test.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { InvalidEsCalendarIntervalError } from './invalid_es_calendar_interval_error'; +import { InvalidEsIntervalFormatError } from './invalid_es_interval_format_error'; +import { parseEsInterval } from './parse_es_interval'; + +describe('parseEsInterval', () => { + it('should correctly parse an interval containing unit and single value', () => { + expect(parseEsInterval('1ms')).toEqual({ value: 1, unit: 'ms', type: 'fixed' }); + expect(parseEsInterval('1s')).toEqual({ value: 1, unit: 's', type: 'fixed' }); + expect(parseEsInterval('1m')).toEqual({ value: 1, unit: 'm', type: 'calendar' }); + expect(parseEsInterval('1h')).toEqual({ value: 1, unit: 'h', type: 'calendar' }); + expect(parseEsInterval('1d')).toEqual({ value: 1, unit: 'd', type: 'calendar' }); + expect(parseEsInterval('1w')).toEqual({ value: 1, unit: 'w', type: 'calendar' }); + expect(parseEsInterval('1M')).toEqual({ value: 1, unit: 'M', type: 'calendar' }); + expect(parseEsInterval('1y')).toEqual({ value: 1, unit: 'y', type: 'calendar' }); + }); + + it('should correctly parse an interval containing unit and multiple value', () => { + expect(parseEsInterval('250ms')).toEqual({ value: 250, unit: 'ms', type: 'fixed' }); + expect(parseEsInterval('90s')).toEqual({ value: 90, unit: 's', type: 'fixed' }); + expect(parseEsInterval('60m')).toEqual({ value: 60, unit: 'm', type: 'fixed' }); + expect(parseEsInterval('12h')).toEqual({ value: 12, unit: 'h', type: 'fixed' }); + expect(parseEsInterval('7d')).toEqual({ value: 7, unit: 'd', type: 'fixed' }); + }); + + it('should throw a InvalidEsCalendarIntervalError for intervals containing calendar unit and multiple value', () => { + const intervals = ['4w', '12M', '10y']; + expect.assertions(intervals.length); + + intervals.forEach(interval => { + try { + parseEsInterval(interval); + } catch (error) { + expect(error instanceof InvalidEsCalendarIntervalError).toBe(true); + } + }); + }); + + it('should throw a InvalidEsIntervalFormatError for invalid interval formats', () => { + const intervals = ['1', 'h', '0m', '0.5h']; + expect.assertions(intervals.length); + + intervals.forEach(interval => { + try { + parseEsInterval(interval); + } catch (error) { + expect(error instanceof InvalidEsIntervalFormatError).toBe(true); + } + }); + }); +}); diff --git a/x-pack/plugins/watcher/public/legacy/parse_es_interval/parse_es_interval.ts b/x-pack/plugins/watcher/public/legacy/parse_es_interval/parse_es_interval.ts new file mode 100644 index 00000000000000..19ac03da034111 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/parse_es_interval/parse_es_interval.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import dateMath, { Unit } from '@elastic/datemath'; + +import { InvalidEsCalendarIntervalError } from './invalid_es_calendar_interval_error'; +import { InvalidEsIntervalFormatError } from './invalid_es_interval_format_error'; + +const ES_INTERVAL_STRING_REGEX = new RegExp( + '^([1-9][0-9]*)\\s*(' + dateMath.units.join('|') + ')$' +); + +export type ParsedInterval = ReturnType; + +/** + * Extracts interval properties from an ES interval string. Disallows unrecognized interval formats + * and fractional values. Converts some intervals from "calendar" to "fixed" when the number of + * units is larger than 1, and throws an error for others. + * + * Conversion rules: + * + * | Interval | Single unit type | Multiple units type | + * | -------- | ---------------- | ------------------- | + * | ms | fixed | fixed | + * | s | fixed | fixed | + * | m | calendar | fixed | + * | h | calendar | fixed | + * | d | calendar | fixed | + * | w | calendar | N/A - disallowed | + * | M | calendar | N/A - disallowed | + * | y | calendar | N/A - disallowed | + * + */ +export function parseEsInterval(interval: string) { + const matches = String(interval) + .trim() + .match(ES_INTERVAL_STRING_REGEX); + + if (!matches) { + throw new InvalidEsIntervalFormatError(interval); + } + + const value = parseFloat(matches[1]); + const unit = matches[2] as Unit; + const type = dateMath.unitsMap[unit].type; + + if (type === 'calendar' && value !== 1) { + throw new InvalidEsCalendarIntervalError(interval, value, unit, type); + } + + return { + value, + unit, + type: + (type === 'mixed' && value === 1) || type === 'calendar' + ? ('calendar' as 'calendar') + : ('fixed' as 'fixed'), + }; +} diff --git a/x-pack/plugins/watcher/public/legacy/time_buckets.d.ts b/x-pack/plugins/watcher/public/legacy/time_buckets.d.ts new file mode 100644 index 00000000000000..e84051b0863443 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/time_buckets.d.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export declare const TimeBuckets: any; diff --git a/x-pack/plugins/watcher/public/legacy/time_buckets.js b/x-pack/plugins/watcher/public/legacy/time_buckets.js new file mode 100644 index 00000000000000..8b7e4be784fe72 --- /dev/null +++ b/x-pack/plugins/watcher/public/legacy/time_buckets.js @@ -0,0 +1,397 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import moment from 'moment'; +import { parseInterval, FIELD_FORMAT_IDS } from '../../../../../src/plugins/data/public'; +import { calcAutoIntervalLessThan, calcAutoIntervalNear } from './calc_auto_interval'; +import { + convertDurationToNormalizedEsInterval, + convertIntervalToEsInterval, +} from './calc_es_interval'; + +function isValidMoment(m) { + return m && 'isValid' in m && m.isValid(); +} + +/** + * Helper class for wrapping the concept of an "Interval", + * which describes a timespan that will separate moments. + * + * @param {state} object - one of "" + * @param {[type]} display [description] + */ +function TimeBuckets(uiSettings, data) { + this.data = data; + this.getConfig = (...args) => uiSettings.get(...args); + return TimeBuckets.__cached__(this); +} + +/**** + * PUBLIC API + ****/ + +/** + * Set the bounds that these buckets are expected to cover. + * This is required to support interval "auto" as well + * as interval scaling. + * + * @param {object} input - an object with properties min and max, + * representing the edges for the time span + * we should cover + * + * @returns {undefined} + */ +TimeBuckets.prototype.setBounds = function(input) { + if (!input) return this.clearBounds(); + + let bounds; + if (_.isPlainObject(input)) { + // accept the response from timefilter.getActiveBounds() + bounds = [input.min, input.max]; + } else { + bounds = Array.isArray(input) ? input : []; + } + + const moments = _(bounds) + .map(_.ary(moment, 1)) + .sortBy(Number); + + const valid = moments.size() === 2 && moments.every(isValidMoment); + if (!valid) { + this.clearBounds(); + throw new Error('invalid bounds set: ' + input); + } + + this._lb = moments.shift(); + this._ub = moments.pop(); + if (this.getDuration().asSeconds() < 0) { + throw new TypeError('Intervals must be positive'); + } +}; + +/** + * Clear the stored bounds + * + * @return {undefined} + */ +TimeBuckets.prototype.clearBounds = function() { + this._lb = this._ub = null; +}; + +/** + * Check to see if we have received bounds yet + * + * @return {Boolean} + */ +TimeBuckets.prototype.hasBounds = function() { + return isValidMoment(this._ub) && isValidMoment(this._lb); +}; + +/** + * Return the current bounds, if we have any. + * + * THIS DOES NOT CLONE THE BOUNDS, so editing them + * may have unexpected side-effects. Always + * call bounds.min.clone() before editing + * + * @return {object|undefined} - If bounds are not defined, this + * returns undefined, else it returns the bounds + * for these buckets. This object has two props, + * min and max. Each property will be a moment() + * object + * + */ +TimeBuckets.prototype.getBounds = function() { + if (!this.hasBounds()) return; + return { + min: this._lb, + max: this._ub, + }; +}; + +/** + * Get a moment duration object representing + * the distance between the bounds, if the bounds + * are set. + * + * @return {moment.duration|undefined} + */ +TimeBuckets.prototype.getDuration = function() { + if (!this.hasBounds()) return; + return moment.duration(this._ub - this._lb, 'ms'); +}; + +/** + * Update the interval at which buckets should be + * generated. + * + * Input can be one of the following: + * - Any object from src/legacy/ui/agg_types/buckets/_interval_options.js + * - "auto" + * - Pass a valid moment unit + * - a moment.duration object. + * + * @param {object|string|moment.duration} input - see desc + */ +TimeBuckets.prototype.setInterval = function(input) { + // Preserve the original units because they're lost when the interval is converted to a + // moment duration object. + this.originalInterval = input; + + let interval = input; + + // selection object -> val + if (_.isObject(input)) { + interval = input.val; + } + + if (!interval || interval === 'auto') { + this._i = 'auto'; + return; + } + + if (_.isString(interval)) { + input = interval; + interval = parseInterval(interval); + if (+interval === 0) { + interval = null; + } + } + + // if the value wasn't converted to a duration, and isn't + // already a duration, we have a problem + if (!moment.isDuration(interval)) { + throw new TypeError('"' + input + '" is not a valid interval.'); + } + + this._i = interval; +}; + +/** + * Get the interval for the buckets. If the + * number of buckets created by the interval set + * is larger than config:histogram:maxBars then the + * interval will be scaled up. If the number of buckets + * created is less than one, the interval is scaled back. + * + * The interval object returned is a moment.duration + * object that has been decorated with the following + * properties. + * + * interval.description: a text description of the interval. + * designed to be used list "field per {{ desc }}". + * - "minute" + * - "10 days" + * - "3 years" + * + * interval.expr: the elasticsearch expression that creates this + * interval. If the interval does not properly form an elasticsearch + * expression it will be forced into one. + * + * interval.scaled: the interval was adjusted to + * accommodate the maxBars setting. + * + * interval.scale: the number that y-values should be + * multiplied by + * + * interval.scaleDescription: a description that reflects + * the values which will be produced by using the + * interval.scale. + * + * + * @return {[type]} [description] + */ +TimeBuckets.prototype.getInterval = function(useNormalizedEsInterval = true) { + const self = this; + const duration = self.getDuration(); + const parsedInterval = readInterval(); + + if (useNormalizedEsInterval) { + return decorateInterval(maybeScaleInterval(parsedInterval)); + } else { + return decorateInterval(parsedInterval); + } + + // either pull the interval from state or calculate the auto-interval + function readInterval() { + const interval = self._i; + if (moment.isDuration(interval)) return interval; + return calcAutoIntervalNear(self.getConfig('histogram:barTarget'), Number(duration)); + } + + // check to see if the interval should be scaled, and scale it if so + function maybeScaleInterval(interval) { + if (!self.hasBounds()) return interval; + + const maxLength = self.getConfig('histogram:maxBars'); + const approxLen = duration / interval; + let scaled; + + if (approxLen > maxLength) { + scaled = calcAutoIntervalLessThan(maxLength, Number(duration)); + } else { + return interval; + } + + if (+scaled === +interval) return interval; + + decorateInterval(interval); + return _.assign(scaled, { + preScaled: interval, + scale: interval / scaled, + scaled: true, + }); + } + + // append some TimeBuckets specific props to the interval + function decorateInterval(interval) { + const esInterval = useNormalizedEsInterval + ? convertDurationToNormalizedEsInterval(interval) + : convertIntervalToEsInterval(self.originalInterval); + interval.esValue = esInterval.value; + interval.esUnit = esInterval.unit; + interval.expression = esInterval.expression; + interval.overflow = duration > interval ? moment.duration(interval - duration) : false; + + const prettyUnits = moment.normalizeUnits(esInterval.unit); + if (esInterval.value === 1) { + interval.description = prettyUnits; + } else { + interval.description = esInterval.value + ' ' + prettyUnits + 's'; + } + + return interval; + } +}; + +/** + * Get a date format string that will represent dates that + * progress at our interval. + * + * Since our interval can be as small as 1ms, the default + * date format is usually way too much. with `dateFormat:scaled` + * users can modify how dates are formatted within series + * produced by TimeBuckets + * + * @return {string} + */ +TimeBuckets.prototype.getScaledDateFormat = function() { + const interval = this.getInterval(); + const rules = this.getConfig('dateFormat:scaled'); + + for (let i = rules.length - 1; i >= 0; i--) { + const rule = rules[i]; + if (!rule[0] || interval >= moment.duration(rule[0])) { + return rule[1]; + } + } + + return this.getConfig('dateFormat'); +}; + +TimeBuckets.prototype.getScaledDateFormatter = function() { + const fieldFormats = this.data.fieldFormats; + const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); + + return new DateFieldFormat( + { + pattern: this.getScaledDateFormat(), + }, + this.getConfig.bind(this) + ); +}; + +TimeBuckets.__cached__ = function(self) { + let cache = {}; + const sameMoment = same(moment.isMoment); + const sameDuration = same(moment.isDuration); + + const desc = { + __cached__: { + value: self, + }, + }; + + const breakers = { + setBounds: 'bounds', + clearBounds: 'bounds', + setInterval: 'interval', + }; + + const resources = { + bounds: { + setup: function() { + return [self._lb, self._ub]; + }, + changes: function(prev) { + return !sameMoment(prev[0], self._lb) || !sameMoment(prev[1], self._ub); + }, + }, + interval: { + setup: function() { + return self._i; + }, + changes: function(prev) { + return !sameDuration(prev, this._i); + }, + }, + }; + + function cachedGetter(prop) { + return { + value: function cachedGetter(...rest) { + if (cache.hasOwnProperty(prop)) { + return cache[prop]; + } + + return (cache[prop] = self[prop](...rest)); + }, + }; + } + + function cacheBreaker(prop) { + const resource = resources[breakers[prop]]; + const setup = resource.setup; + const changes = resource.changes; + const fn = self[prop]; + + return { + value: function cacheBreaker() { + const prev = setup.call(self); + const ret = fn.apply(self, arguments); + + if (changes.call(self, prev)) { + cache = {}; + } + + return ret; + }, + }; + } + + function same(checkType) { + return function(a, b) { + if (a === b) return true; + if (checkType(a) === checkType(b)) return +a === +b; + return false; + }; + } + + _.forOwn(TimeBuckets.prototype, function(fn, prop) { + if (prop[0] === '_') return; + + if (breakers.hasOwnProperty(prop)) { + desc[prop] = cacheBreaker(prop); + } else { + desc[prop] = cachedGetter(prop); + } + }); + + return Object.create(self, desc); +}; + +export { TimeBuckets }; diff --git a/x-pack/plugins/watcher/public/plugin.ts b/x-pack/plugins/watcher/public/plugin.ts new file mode 100644 index 00000000000000..7bb422f9a6eb19 --- /dev/null +++ b/x-pack/plugins/watcher/public/plugin.ts @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { i18n } from '@kbn/i18n'; +import { CoreSetup, Plugin, CoreStart } from 'kibana/public'; +import { first, map, skip } from 'rxjs/operators'; + +import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public'; + +import { LicenseStatus } from '../common/types/license_status'; + +import { ILicense, LICENSE_CHECK_STATE } from '../../licensing/public'; +import { TimeBuckets, MANAGEMENT_BREADCRUMB } from './legacy'; +import { PLUGIN } from '../common/constants'; +import { Dependencies } from './types'; + +const licenseToLicenseStatus = (license: ILicense): LicenseStatus => { + const { state, message } = license.check(PLUGIN.ID, PLUGIN.MINIMUM_LICENSE_REQUIRED); + return { + valid: state === LICENSE_CHECK_STATE.Valid && license.getFeature(PLUGIN.ID).isAvailable, + message, + }; +}; + +export class WatcherUIPlugin implements Plugin { + setup( + { application, notifications, http, uiSettings, getStartServices }: CoreSetup, + { licensing, management, data, home }: Dependencies + ) { + const esSection = management.sections.getSection('elasticsearch'); + + const watcherESApp = esSection!.registerApp({ + id: 'watcher', + title: i18n.translate( + 'xpack.watcher.sections.watchList.managementSection.watcherDisplayName', + { defaultMessage: 'Watcher' } + ), + mount: async ({ element }) => { + const [core, plugins] = await getStartServices(); + const { chrome, i18n: i18nDep, docLinks, savedObjects } = core; + const { eui_utils } = plugins as any; + const { boot } = await import('./application/boot'); + + return boot({ + // Skip the first license status, because that's already been used to determine + // whether to include Watcher. + licenseStatus$: licensing.license$.pipe(skip(1), map(licenseToLicenseStatus)), + element, + toasts: notifications.toasts, + http, + uiSettings, + docLinks, + chrome, + euiUtils: eui_utils, + savedObjects: savedObjects.client, + I18nContext: i18nDep.Context, + createTimeBuckets: () => new TimeBuckets(uiSettings, data), + MANAGEMENT_BREADCRUMB, + }); + }, + }); + + watcherESApp.disable(); + + // TODO: Fix the below dependency on `home` plugin inner workings + // Because the home feature catalogue does not have enable/disable functionality we pass + // the config in but keep a reference for enabling and disabling showing on home based on + // license updates. + const watcherHome = { + id: 'watcher', + title: 'Watcher', // This is a product name so we don't translate it. + category: FeatureCatalogueCategory.ADMIN, + description: i18n.translate('xpack.watcher.watcherDescription', { + defaultMessage: 'Detect changes in your data by creating, managing, and monitoring alerts.', + }), + icon: 'watchesApp', + path: '/app/kibana#/management/elasticsearch/watcher/watches', + showOnHomePage: true, + }; + + home.featureCatalogue.register(watcherHome); + + licensing.license$.pipe(first(), map(licenseToLicenseStatus)).subscribe(({ valid }) => { + if (valid) { + watcherESApp.enable(); + watcherHome.showOnHomePage = true; + } else { + watcherESApp.disable(); + watcherHome.showOnHomePage = false; + } + }); + } + + start(core: CoreStart) {} + + stop() {} +} diff --git a/x-pack/plugins/watcher/public/types.ts b/x-pack/plugins/watcher/public/types.ts new file mode 100644 index 00000000000000..930185051514a9 --- /dev/null +++ b/x-pack/plugins/watcher/public/types.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ManagementSetup } from 'src/plugins/management/public'; +import { EuiUtilsStart } from 'src/plugins/eui_utils/public'; +import { LicensingPluginSetup } from '../../licensing/public'; +import { DataPublicPluginSetup } from '../../../../src/plugins/data/public'; +import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; + +export interface Dependencies { + home: HomePublicPluginSetup; + management: ManagementSetup; + licensing: LicensingPluginSetup; + eui_utils: EuiUtilsStart; + data: DataPublicPluginSetup; +} diff --git a/x-pack/plugins/watcher/server/index.ts b/x-pack/plugins/watcher/server/index.ts new file mode 100644 index 00000000000000..51eb7bfa543fe1 --- /dev/null +++ b/x-pack/plugins/watcher/server/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; + * you may not use this file except in compliance with the Elastic License. + */ +import { PluginInitializerContext } from 'kibana/server'; +import { WatcherServerPlugin } from './plugin'; + +export const plugin = (ctx: PluginInitializerContext) => new WatcherServerPlugin(ctx); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/call_with_request_factory.ts b/x-pack/plugins/watcher/server/lib/call_with_request_factory.ts similarity index 93% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/call_with_request_factory.ts rename to x-pack/plugins/watcher/server/lib/call_with_request_factory.ts index eaec9cd91b23cd..4884c75436c246 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/lib/call_with_request_factory.ts +++ b/x-pack/plugins/watcher/server/lib/call_with_request_factory.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ElasticsearchServiceSetup } from 'src/core/server'; +import { ElasticsearchServiceSetup } from 'kibana/server'; import { once } from 'lodash'; import { elasticsearchJsPlugin } from './elasticsearch_js_plugin'; diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/elasticsearch_js_plugin.ts b/x-pack/plugins/watcher/server/lib/elasticsearch_js_plugin.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/elasticsearch_js_plugin.ts rename to x-pack/plugins/watcher/server/lib/elasticsearch_js_plugin.ts diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js rename to x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts similarity index 92% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts rename to x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts index d762b05f01d79e..de01bd59655040 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts +++ b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts @@ -5,7 +5,7 @@ */ import { get } from 'lodash'; -import { ES_SCROLL_SETTINGS } from '../../../../common/constants'; +import { ES_SCROLL_SETTINGS } from '../../../common/constants'; export function fetchAllFromScroll(response: any, callWithRequest: any, hits: any[] = []) { const newHits = get(response, 'hits.hits', []); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/fetch_all_from_scroll/index.ts b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/fetch_all_from_scroll/index.ts rename to x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/index.ts diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/is_es_error/index.ts b/x-pack/plugins/watcher/server/lib/is_es_error/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/is_es_error/index.ts rename to x-pack/plugins/watcher/server/lib/is_es_error/index.ts diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/is_es_error/is_es_error.ts b/x-pack/plugins/watcher/server/lib/is_es_error/is_es_error.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/is_es_error/is_es_error.ts rename to x-pack/plugins/watcher/server/lib/is_es_error/is_es_error.ts diff --git a/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.test.js b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.test.js new file mode 100644 index 00000000000000..be6873a61e902d --- /dev/null +++ b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.test.js @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { kibanaResponseFactory } from '../../../../../../../src/core/server'; +import { licensePreRoutingFactory } from '../license_pre_routing_factory'; + +describe('license_pre_routing_factory', () => { + describe('#reportingFeaturePreRoutingFactory', () => { + let mockDeps; + let licenseStatus; + + beforeEach(() => { + mockDeps = { getLicenseStatus: () => licenseStatus }; + }); + + describe('status is not valid', () => { + it('replies with 403', () => { + licenseStatus = { hasRequired: false }; + const routeWithLicenseCheck = licensePreRoutingFactory(mockDeps, () => {}); + const stubRequest = {}; + const response = routeWithLicenseCheck({}, stubRequest, kibanaResponseFactory); + expect(response.status).to.be(403); + }); + }); + + describe('status is valid', () => { + it('replies with nothing', () => { + licenseStatus = { hasRequired: true }; + const routeWithLicenseCheck = licensePreRoutingFactory(mockDeps, () => null); + const stubRequest = {}; + const response = routeWithLicenseCheck({}, stubRequest, kibanaResponseFactory); + expect(response).to.be(null); + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/license_pre_routing_factory/index.ts b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/license_pre_routing_factory/index.ts rename to x-pack/plugins/watcher/server/lib/license_pre_routing_factory/index.ts diff --git a/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts new file mode 100644 index 00000000000000..d010a239527254 --- /dev/null +++ b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + KibanaRequest, + KibanaResponseFactory, + RequestHandler, + RequestHandlerContext, +} from 'kibana/server'; +import { RouteDependencies } from '../../types'; + +export const licensePreRoutingFactory = ( + { getLicenseStatus }: RouteDependencies, + handler: RequestHandler +) => { + return function licenseCheck( + ctx: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory + ) { + const licenseStatus = getLicenseStatus(); + if (!licenseStatus.hasRequired) { + return response.customError({ + body: { + message: licenseStatus.message || '', + }, + statusCode: 403, + }); + } + + return handler(ctx, request, response); + }; +}; diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/normalized_field_types/index.ts b/x-pack/plugins/watcher/server/lib/normalized_field_types/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/normalized_field_types/index.ts rename to x-pack/plugins/watcher/server/lib/normalized_field_types/index.ts diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/lib/normalized_field_types/normalized_field_types.ts b/x-pack/plugins/watcher/server/lib/normalized_field_types/normalized_field_types.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/lib/normalized_field_types/normalized_field_types.ts rename to x-pack/plugins/watcher/server/lib/normalized_field_types/normalized_field_types.ts diff --git a/x-pack/plugins/watcher/server/models/action_status/__tests__/action_status.js b/x-pack/plugins/watcher/server/models/action_status/__tests__/action_status.js new file mode 100644 index 00000000000000..cc5f11da1b5d2c --- /dev/null +++ b/x-pack/plugins/watcher/server/models/action_status/__tests__/action_status.js @@ -0,0 +1,359 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { ActionStatus } from '../action_status'; +import { ACTION_STATES } from '../../../../common/constants'; +import moment from 'moment'; + +describe('action_status', () => { + describe('ActionStatus', () => { + describe('fromUpstreamJson factory method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-action', + actionStatusJson: { + ack: { + timestamp: '2017-03-01T20:56:58.442Z', + state: 'acked', + }, + last_execution: { + timestamp: '2017-03-01T20:55:49.679Z', + successful: true, + reason: 'reasons', + }, + last_throttle: { + timestamp: '2017-03-01T20:55:49.679Z', + }, + last_successful_execution: { + timestamp: '2017-03-01T20:55:49.679Z', + successful: true, + }, + }, + }; + }); + + it(`throws an error if no 'id' property in json`, () => { + delete upstreamJson.id; + expect(ActionStatus.fromUpstreamJson) + .withArgs(upstreamJson) + .to.throwError('JSON argument must contain an "id" property'); + }); + + it(`throws an error if no 'actionStatusJson' property in json`, () => { + delete upstreamJson.actionStatusJson; + expect(ActionStatus.fromUpstreamJson) + .withArgs(upstreamJson) + .to.throwError('JSON argument must contain an "actionStatusJson" property'); + }); + + it('returns correct ActionStatus instance', () => { + const actionStatus = ActionStatus.fromUpstreamJson({ + ...upstreamJson, + errors: { foo: 'bar' }, + }); + + expect(actionStatus.id).to.be(upstreamJson.id); + expect(actionStatus.lastAcknowledged).to.eql( + moment(upstreamJson.actionStatusJson.ack.timestamp) + ); + expect(actionStatus.lastExecution).to.eql( + moment(upstreamJson.actionStatusJson.last_execution.timestamp) + ); + expect(actionStatus.lastExecutionSuccessful).to.eql( + upstreamJson.actionStatusJson.last_execution.successful + ); + expect(actionStatus.lastExecutionReason).to.be( + upstreamJson.actionStatusJson.last_execution.reason + ); + expect(actionStatus.lastThrottled).to.eql( + moment(upstreamJson.actionStatusJson.last_throttle.timestamp) + ); + expect(actionStatus.lastSuccessfulExecution).to.eql( + moment(upstreamJson.actionStatusJson.last_successful_execution.timestamp) + ); + expect(actionStatus.errors).to.eql({ foo: 'bar' }); + }); + }); + + describe('state getter method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-action', + actionStatusJson: { + ack: { + timestamp: '2017-03-01T20:56:58.442Z', + state: 'acked', + }, + last_execution: { + timestamp: '2017-03-01T20:55:49.679Z', + successful: true, + reason: 'reasons', + }, + last_throttle: { + timestamp: '2017-03-01T20:55:49.679Z', + }, + last_successful_execution: { + timestamp: '2017-03-01T20:55:49.679Z', + successful: true, + }, + }, + }; + }); + + describe(`correctly calculates ACTION_STATES.ERROR`, () => { + it('lastExecutionSuccessful is equal to false', () => { + upstreamJson.actionStatusJson.last_execution.successful = false; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + expect(actionStatus.state).to.be(ACTION_STATES.ERROR); + }); + + it('action is acked and lastAcknowledged is less than lastExecution', () => { + const actionStatus = ActionStatus.fromUpstreamJson({ + ...upstreamJson, + actionStatusJson: { + ack: { + state: 'acked', + timestamp: '2017-03-01T00:00:00.000Z', + }, + last_execution: { + timestamp: '2017-03-02T00:00:00.000Z', + }, + }, + }); + expect(actionStatus.state).to.be(ACTION_STATES.ERROR); + }); + + it('action is ackable and lastSuccessfulExecution is less than lastExecution', () => { + delete upstreamJson.actionStatusJson.last_throttle; + upstreamJson.actionStatusJson.ack.state = 'ackable'; + upstreamJson.actionStatusJson.last_successful_execution.timestamp = + '2017-03-01T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-02T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.ERROR); + }); + }); + + it('correctly calculates ACTION_STATES.CONFIG_ERROR', () => { + const actionStatus = ActionStatus.fromUpstreamJson({ + ...upstreamJson, + errors: { foo: 'bar' }, + }); + expect(actionStatus.state).to.be(ACTION_STATES.CONFIG_ERROR); + }); + + it(`correctly calculates ACTION_STATES.OK`, () => { + upstreamJson.actionStatusJson.ack.state = 'awaits_successful_execution'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.OK); + }); + + describe(`correctly calculates ACTION_STATES.ACKNOWLEDGED`, () => { + it(`when lastAcknowledged is equal to lastExecution`, () => { + upstreamJson.actionStatusJson.ack.state = 'acked'; + upstreamJson.actionStatusJson.ack.timestamp = '2017-03-01T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.ACKNOWLEDGED); + }); + + it(`when lastAcknowledged is greater than lastExecution`, () => { + upstreamJson.actionStatusJson.ack.state = 'acked'; + upstreamJson.actionStatusJson.ack.timestamp = '2017-03-02T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.ACKNOWLEDGED); + }); + }); + + describe(`correctly calculates ACTION_STATES.THROTTLED`, () => { + it(`when lastThrottled is equal to lastExecution`, () => { + upstreamJson.actionStatusJson.ack.state = 'ackable'; + upstreamJson.actionStatusJson.last_throttle.timestamp = '2017-03-01T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.THROTTLED); + }); + + it(`when lastThrottled is greater than lastExecution`, () => { + upstreamJson.actionStatusJson.ack.state = 'ackable'; + upstreamJson.actionStatusJson.last_throttle.timestamp = '2017-03-02T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.THROTTLED); + }); + }); + + describe(`correctly calculates ACTION_STATES.FIRING`, () => { + it(`when lastSuccessfulExecution is equal to lastExecution`, () => { + delete upstreamJson.actionStatusJson.last_throttle; + upstreamJson.actionStatusJson.ack.state = 'ackable'; + upstreamJson.actionStatusJson.last_successful_execution.timestamp = + '2017-03-01T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.FIRING); + }); + + it(`when lastSuccessfulExecution is greater than lastExecution`, () => { + delete upstreamJson.actionStatusJson.last_throttle; + upstreamJson.actionStatusJson.ack.state = 'ackable'; + upstreamJson.actionStatusJson.last_successful_execution.timestamp = + '2017-03-02T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.FIRING); + }); + }); + + it(`correctly calculates ACTION_STATES.UNKNOWN if it can not determine state`, () => { + upstreamJson = { + id: 'my-action', + actionStatusJson: { + ack: { state: 'foo' }, + last_successful_execution: { successful: true }, + }, + }; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.UNKNOWN); + }); + }); + + describe('isAckable getter method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-action', + actionStatusJson: { + ack: { + timestamp: '2017-03-01T20:56:58.442Z', + state: 'acked', + }, + last_execution: { + timestamp: '2017-03-01T20:55:49.679Z', + successful: true, + reason: 'reasons', + }, + last_throttle: { + timestamp: '2017-03-01T20:55:49.679Z', + }, + last_successful_execution: { + timestamp: '2017-03-01T20:55:49.679Z', + successful: true, + }, + }, + }; + }); + + it(`correctly calculated isAckable when in ACTION_STATES.OK`, () => { + upstreamJson.actionStatusJson.ack.state = 'awaits_successful_execution'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.OK); + expect(actionStatus.isAckable).to.be(false); + }); + + it(`correctly calculated isAckable when in ACTION_STATES.ACKNOWLEDGED`, () => { + upstreamJson.actionStatusJson.ack.state = 'acked'; + upstreamJson.actionStatusJson.ack.timestamp = '2017-03-01T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.ACKNOWLEDGED); + expect(actionStatus.isAckable).to.be(false); + }); + + it(`correctly calculated isAckable when in ACTION_STATES.THROTTLED`, () => { + upstreamJson.actionStatusJson.ack.state = 'ackable'; + upstreamJson.actionStatusJson.last_throttle.timestamp = '2017-03-01T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.THROTTLED); + expect(actionStatus.isAckable).to.be(true); + }); + + it(`correctly calculated isAckable when in ACTION_STATES.FIRING`, () => { + delete upstreamJson.actionStatusJson.last_throttle; + upstreamJson.actionStatusJson.ack.state = 'ackable'; + upstreamJson.actionStatusJson.last_successful_execution.timestamp = + '2017-03-01T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-01T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.FIRING); + expect(actionStatus.isAckable).to.be(true); + }); + + it(`correctly calculated isAckable when in ACTION_STATES.ERROR`, () => { + delete upstreamJson.actionStatusJson.last_throttle; + upstreamJson.actionStatusJson.ack.state = 'ackable'; + upstreamJson.actionStatusJson.last_successful_execution.timestamp = + '2017-03-01T00:00:00.000Z'; + upstreamJson.actionStatusJson.last_execution.timestamp = '2017-03-02T00:00:00.000Z'; + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + expect(actionStatus.state).to.be(ACTION_STATES.ERROR); + expect(actionStatus.isAckable).to.be(false); + }); + }); + + describe('downstreamJson getter method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-action', + actionStatusJson: { + ack: { + timestamp: '2017-03-01T20:56:58.442Z', + state: 'acked', + }, + last_execution: { + timestamp: '2017-03-01T20:55:49.679Z', + successful: true, + reason: 'reasons', + }, + last_throttle: { + timestamp: '2017-03-01T20:55:49.679Z', + }, + last_successful_execution: { + timestamp: '2017-03-01T20:55:49.679Z', + successful: true, + }, + }, + }; + }); + + it('returns correct JSON for client', () => { + const actionStatus = ActionStatus.fromUpstreamJson(upstreamJson); + + const json = actionStatus.downstreamJson; + + expect(json.id).to.be(actionStatus.id); + expect(json.state).to.be(actionStatus.state); + expect(json.isAckable).to.be(actionStatus.isAckable); + expect(json.lastAcknowledged).to.be(actionStatus.lastAcknowledged); + expect(json.lastThrottled).to.be(actionStatus.lastThrottled); + expect(json.lastExecution).to.be(actionStatus.lastExecution); + expect(json.lastExecutionSuccessful).to.be(actionStatus.lastExecutionSuccessful); + expect(json.lastExecutionReason).to.be(actionStatus.lastExecutionReason); + expect(json.lastSuccessfulExecution).to.be(actionStatus.lastSuccessfulExecution); + }); + }); + }); +}); diff --git a/x-pack/plugins/watcher/server/models/action_status/action_status.js b/x-pack/plugins/watcher/server/models/action_status/action_status.js new file mode 100644 index 00000000000000..01ec9a436675db --- /dev/null +++ b/x-pack/plugins/watcher/server/models/action_status/action_status.js @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get } from 'lodash'; +import { badRequest } from 'boom'; +import { getMoment } from '../../../common/lib/get_moment'; +import { ACTION_STATES } from '../../../common/constants'; +import { i18n } from '@kbn/i18n'; + +export class ActionStatus { + constructor(props) { + this.id = props.id; + this.actionStatusJson = props.actionStatusJson; + this.errors = props.errors; + + this.lastAcknowledged = getMoment(get(this.actionStatusJson, 'ack.timestamp')); + this.lastExecution = getMoment(get(this.actionStatusJson, 'last_execution.timestamp')); + this.lastExecutionSuccessful = get(this.actionStatusJson, 'last_execution.successful'); + this.lastExecutionReason = get(this.actionStatusJson, 'last_execution.reason'); + this.lastThrottled = getMoment(get(this.actionStatusJson, 'last_throttle.timestamp')); + this.lastSuccessfulExecution = getMoment( + get(this.actionStatusJson, 'last_successful_execution.timestamp') + ); + } + + get state() { + const actionStatusJson = this.actionStatusJson; + const ackState = actionStatusJson.ack.state; + + if (this.lastExecutionSuccessful === false) { + return ACTION_STATES.ERROR; + } + + if (this.errors) { + return ACTION_STATES.CONFIG_ERROR; + } + + if (ackState === 'awaits_successful_execution') { + return ACTION_STATES.OK; + } + + if (ackState === 'acked' && this.lastAcknowledged >= this.lastExecution) { + return ACTION_STATES.ACKNOWLEDGED; + } + + // A user could potentially land in this state if running on multiple nodes and timing is off + if (ackState === 'acked' && this.lastAcknowledged < this.lastExecution) { + return ACTION_STATES.ERROR; + } + + if (ackState === 'ackable' && this.lastThrottled >= this.lastExecution) { + return ACTION_STATES.THROTTLED; + } + + if (ackState === 'ackable' && this.lastSuccessfulExecution >= this.lastExecution) { + return ACTION_STATES.FIRING; + } + + if (ackState === 'ackable' && this.lastSuccessfulExecution < this.lastExecution) { + return ACTION_STATES.ERROR; + } + + // At this point, we cannot determine the action status so mark it as "unknown". + // We should never get to this point in the code. If we do, it means we are + // missing an action status and the logic to determine it. + return ACTION_STATES.UNKNOWN; + } + + get isAckable() { + if (this.state === ACTION_STATES.THROTTLED || this.state === ACTION_STATES.FIRING) { + return true; + } + + return false; + } + + // generate object to send to kibana + get downstreamJson() { + const json = { + id: this.id, + state: this.state, + isAckable: this.isAckable, + lastAcknowledged: this.lastAcknowledged, + lastThrottled: this.lastThrottled, + lastExecution: this.lastExecution, + lastExecutionSuccessful: this.lastExecutionSuccessful, + lastExecutionReason: this.lastExecutionReason, + lastSuccessfulExecution: this.lastSuccessfulExecution, + }; + + return json; + } + + // generate object from elasticsearch response + static fromUpstreamJson(json) { + const missingPropertyError = missingProperty => + i18n.translate( + 'xpack.watcher.models.actionStatus.actionStatusJsonPropertyMissingBadRequestMessage', + { + defaultMessage: 'JSON argument must contain an "{missingProperty}" property', + values: { missingProperty }, + } + ); + + if (!json.id) { + throw badRequest(missingPropertyError('id')); + } + + if (!json.actionStatusJson) { + throw badRequest(missingPropertyError('actionStatusJson')); + } + + return new ActionStatus(json); + } + + /* + json.actionStatusJson should have the following structure: + { + "ack": { + "timestamp": "2017-03-01T20:56:58.442Z", + "state": "acked" + }, + "last_execution": { + "timestamp": "2017-03-01T20:55:49.679Z", + "successful": true + }, + "last_successful_execution": { + "timestamp": "2017-03-01T20:55:49.679Z", + "successful": true + } + } + */ +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/action_status/index.js b/x-pack/plugins/watcher/server/models/action_status/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/action_status/index.js rename to x-pack/plugins/watcher/server/models/action_status/index.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/execute_details/__tests__/execute_details.js b/x-pack/plugins/watcher/server/models/execute_details/__tests__/execute_details.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/execute_details/__tests__/execute_details.js rename to x-pack/plugins/watcher/server/models/execute_details/__tests__/execute_details.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/execute_details/execute_details.js b/x-pack/plugins/watcher/server/models/execute_details/execute_details.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/execute_details/execute_details.js rename to x-pack/plugins/watcher/server/models/execute_details/execute_details.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/execute_details/index.js b/x-pack/plugins/watcher/server/models/execute_details/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/execute_details/index.js rename to x-pack/plugins/watcher/server/models/execute_details/index.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/fields/__tests__/fields.js b/x-pack/plugins/watcher/server/models/fields/__tests__/fields.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/fields/__tests__/fields.js rename to x-pack/plugins/watcher/server/models/fields/__tests__/fields.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/fields/fields.js b/x-pack/plugins/watcher/server/models/fields/fields.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/fields/fields.js rename to x-pack/plugins/watcher/server/models/fields/fields.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/fields/index.js b/x-pack/plugins/watcher/server/models/fields/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/fields/index.js rename to x-pack/plugins/watcher/server/models/fields/index.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/settings/__tests__/settings.js b/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/settings/__tests__/settings.js rename to x-pack/plugins/watcher/server/models/settings/__tests__/settings.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/settings/index.js b/x-pack/plugins/watcher/server/models/settings/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/settings/index.js rename to x-pack/plugins/watcher/server/models/settings/index.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/settings/settings.js b/x-pack/plugins/watcher/server/models/settings/settings.js similarity index 97% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/settings/settings.js rename to x-pack/plugins/watcher/server/models/settings/settings.js index 4aa524731d88da..42fbda9cbe91de 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/settings/settings.js +++ b/x-pack/plugins/watcher/server/models/settings/settings.js @@ -5,7 +5,7 @@ */ import { merge } from 'lodash'; -import { ACTION_TYPES } from '../../../../common/constants'; +import { ACTION_TYPES } from '../../../common/constants'; function isEnabledByDefault(actionType) { switch (actionType) { diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/visualize_options/index.js b/x-pack/plugins/watcher/server/models/visualize_options/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/visualize_options/index.js rename to x-pack/plugins/watcher/server/models/visualize_options/index.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/visualize_options/visualize_options.js b/x-pack/plugins/watcher/server/models/visualize_options/visualize_options.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/visualize_options/visualize_options.js rename to x-pack/plugins/watcher/server/models/visualize_options/visualize_options.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/base_watch.js b/x-pack/plugins/watcher/server/models/watch/base_watch.js similarity index 98% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/base_watch.js rename to x-pack/plugins/watcher/server/models/watch/base_watch.js index d77e6d6caa2fa8..ea09fac6f85236 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/base_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/base_watch.js @@ -6,7 +6,7 @@ import { get, map, pick } from 'lodash'; import { badRequest } from 'boom'; -import { Action } from '../../../../common/models/action'; +import { Action } from '../../../common/models/action'; import { WatchStatus } from '../watch_status'; import { i18n } from '@kbn/i18n'; import { WatchErrors } from '../watch_errors'; diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/base_watch.test.js b/x-pack/plugins/watcher/server/models/watch/base_watch.test.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/base_watch.test.js rename to x-pack/plugins/watcher/server/models/watch/base_watch.test.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/index.js b/x-pack/plugins/watcher/server/models/watch/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/index.js rename to x-pack/plugins/watcher/server/models/watch/index.js diff --git a/x-pack/plugins/watcher/server/models/watch/json_watch.js b/x-pack/plugins/watcher/server/models/watch/json_watch.js new file mode 100644 index 00000000000000..dbb34e971f94ac --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch/json_watch.js @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { isEmpty, cloneDeep, has, merge } from 'lodash'; +import { BaseWatch } from './base_watch'; +import { WATCH_TYPES } from '../../../common/constants'; +import { serializeJsonWatch } from '../../../common/lib/serialization'; + +export class JsonWatch extends BaseWatch { + // This constructor should not be used directly. + // JsonWatch objects should be instantiated using the + // fromUpstreamJson and fromDownstreamJson static methods + constructor(props) { + super(props); + + this.watch = props.watch; + } + + get watchJson() { + return serializeJsonWatch(this.name, this.watch); + } + + // To Kibana + get downstreamJson() { + const result = merge({}, super.downstreamJson, { + watch: this.watch, + }); + + return result; + } + + // From Elasticsearch + static fromUpstreamJson(json, options) { + const baseProps = super.getPropsFromUpstreamJson(json, options); + const watch = cloneDeep(baseProps.watchJson); + + if (has(watch, 'metadata.name')) { + delete watch.metadata.name; + } + if (has(watch, 'metadata.xpack')) { + delete watch.metadata.xpack; + } + + if (isEmpty(watch.metadata)) { + delete watch.metadata; + } + + const props = merge({}, baseProps, { + type: WATCH_TYPES.JSON, + watch, + }); + + return new JsonWatch(props); + } + + // From Kibana + static fromDownstreamJson(json) { + const props = merge({}, super.getPropsFromDownstreamJson(json), { + type: WATCH_TYPES.JSON, + watch: json.watch, + }); + + return new JsonWatch(props); + } +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/json_watch.test.js b/x-pack/plugins/watcher/server/models/watch/json_watch.test.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/json_watch.test.js rename to x-pack/plugins/watcher/server/models/watch/json_watch.test.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/lib/get_watch_type/get_watch_type.js b/x-pack/plugins/watcher/server/models/watch/lib/get_watch_type/get_watch_type.js similarity index 88% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/lib/get_watch_type/get_watch_type.js rename to x-pack/plugins/watcher/server/models/watch/lib/get_watch_type/get_watch_type.js index 72c725eda2bd18..2bdd03e23c6dcd 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/lib/get_watch_type/get_watch_type.js +++ b/x-pack/plugins/watcher/server/models/watch/lib/get_watch_type/get_watch_type.js @@ -5,7 +5,7 @@ */ import { get, contains, values } from 'lodash'; -import { WATCH_TYPES } from '../../../../../../common/constants'; +import { WATCH_TYPES } from '../../../../../common/constants'; export function getWatchType(watchJson) { const type = get(watchJson, 'metadata.xpack.type'); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/lib/get_watch_type/index.js b/x-pack/plugins/watcher/server/models/watch/lib/get_watch_type/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/lib/get_watch_type/index.js rename to x-pack/plugins/watcher/server/models/watch/lib/get_watch_type/index.js diff --git a/x-pack/plugins/watcher/server/models/watch/monitoring_watch.js b/x-pack/plugins/watcher/server/models/watch/monitoring_watch.js new file mode 100644 index 00000000000000..8f32621bfbb867 --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch/monitoring_watch.js @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { merge } from 'lodash'; +import { badRequest } from 'boom'; +import { BaseWatch } from './base_watch'; +import { WATCH_TYPES } from '../../../common/constants'; +import { i18n } from '@kbn/i18n'; + +export class MonitoringWatch extends BaseWatch { + // This constructor should not be used directly. + // JsonWatch objects should be instantiated using the + // fromUpstreamJson and fromDownstreamJson static methods + constructor(props) { + super(props); + + this.isSystemWatch = true; + } + + get watchJson() { + const result = merge({}, super.watchJson); + + return result; + } + + getVisualizeQuery() { + throw badRequest( + i18n.translate( + 'xpack.watcher.models.monitoringWatch.getVisualizeQueryCalledBadRequestMessage', + { + defaultMessage: '{getVisualizeQuery} called for monitoring watch', + values: { + getVisualizeQuery: 'getVisualizeQuery', + }, + } + ) + ); + } + + formatVisualizeData() { + throw badRequest( + i18n.translate( + 'xpack.watcher.models.monitoringWatch.formatVisualizeDataCalledBadRequestMessage', + { + defaultMessage: '{formatVisualizeData} called for monitoring watch', + values: { + formatVisualizeData: 'formatVisualizeData', + }, + } + ) + ); + } + + // To Elasticsearch + get upstreamJson() { + throw badRequest( + i18n.translate('xpack.watcher.models.monitoringWatch.upstreamJsonCalledBadRequestMessage', { + defaultMessage: '{upstreamJson} called for monitoring watch', + values: { + upstreamJson: 'upstreamJson', + }, + }) + ); + } + + // To Kibana + get downstreamJson() { + const result = merge({}, super.downstreamJson); + + return result; + } + + // From Elasticsearch + static fromUpstreamJson(json) { + const props = merge({}, super.getPropsFromUpstreamJson(json), { + type: WATCH_TYPES.MONITORING, + }); + + return new MonitoringWatch(props); + } + + // From Kibana + static fromDownstreamJson() { + throw badRequest( + i18n.translate( + 'xpack.watcher.models.monitoringWatch.fromDownstreamJsonCalledBadRequestMessage', + { + defaultMessage: '{fromDownstreamJson} called for monitoring watch', + values: { + fromDownstreamJson: 'fromDownstreamJson', + }, + } + ) + ); + } +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/monitoring_watch.test.js b/x-pack/plugins/watcher/server/models/watch/monitoring_watch.test.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/monitoring_watch.test.js rename to x-pack/plugins/watcher/server/models/watch/monitoring_watch.test.js diff --git a/x-pack/plugins/watcher/server/models/watch/threshold_watch/__tests__/format_visualize_data.js b/x-pack/plugins/watcher/server/models/watch/threshold_watch/__tests__/format_visualize_data.js new file mode 100644 index 00000000000000..99e88c3628ea8e --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch/threshold_watch/__tests__/format_visualize_data.js @@ -0,0 +1,325 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { AGG_TYPES } from '../../../../../common/constants'; +import { formatVisualizeData } from '../format_visualize_data'; + +describe('watch', () => { + describe('formatVisualizeData', () => { + it('correctly formats data from a Count query', () => { + const watch = { + aggType: AGG_TYPES.COUNT, + termField: undefined, + }; + + const response = { + aggregations: { + dateAgg: { + buckets: [ + { + key_as_string: '2017-06-17T00:00:00.000-05:00', + key: 1497675600000, + doc_count: 13622, + }, + { + key_as_string: '2017-06-17T12:00:00.000-05:00', + key: 1497718800000, + doc_count: 13639, + }, + { + key_as_string: '2017-06-18T00:00:00.000-05:00', + key: 1497762000000, + doc_count: 13811, + }, + { + key_as_string: '2017-06-18T12:00:00.000-05:00', + key: 1497805200000, + doc_count: 13461, + }, + ], + }, + }, + }; + + const expected = { + count: [ + [1497675600000, 13622], + [1497718800000, 13639], + [1497762000000, 13811], + [1497805200000, 13461], + ], + }; + + const actual = formatVisualizeData(watch, response); + + expect(actual).to.eql(expected); + }); + + it('correctly formats data from a Count Terms query', () => { + const watch = { + aggType: AGG_TYPES.COUNT, + termField: 'foo_term_field', + }; + + const response = { + aggregations: { + bucketAgg: { + buckets: [ + { + key: 'foo_term', + dateAgg: { + buckets: [ + { + key: 1498366800000, + doc_count: 8878, + }, + { + key: 1498410000000, + doc_count: 8674, + }, + { + key: 1498453200000, + doc_count: 8720, + }, + ], + }, + }, + { + key: 'bar_term', + dateAgg: { + buckets: [ + { + key: 1498366800000, + doc_count: 2163, + }, + { + key: 1498410000000, + doc_count: 2202, + }, + { + key: 1498453200000, + doc_count: 2311, + }, + ], + }, + }, + { + key: 'baz_term', + dateAgg: { + buckets: [ + { + key: 1497675600000, + doc_count: 891, + }, + { + key: 1497718800000, + doc_count: 866, + }, + { + key: 1497762000000, + doc_count: 906, + }, + ], + }, + }, + ], + }, + }, + }; + + const expected = { + foo_term: [ + [1498366800000, 8878], + [1498410000000, 8674], + [1498453200000, 8720], + ], + bar_term: [ + [1498366800000, 2163], + [1498410000000, 2202], + [1498453200000, 2311], + ], + baz_term: [ + [1497675600000, 891], + [1497718800000, 866], + [1497762000000, 906], + ], + }; + + const actual = formatVisualizeData(watch, response); + + expect(actual).to.eql(expected); + }); + + it('correctly formats data from a Non-Count query', () => { + const watch = { + aggType: AGG_TYPES.AVERAGE, + termField: undefined, + }; + + const response = { + aggregations: { + dateAgg: { + buckets: [ + { + key: 1497675600000, + metricAgg: { + value: 5721.5481573924535, + }, + }, + { + key: 1497718800000, + metricAgg: { + value: 5696.727765965246, + }, + }, + { + key: 1497762000000, + metricAgg: { + value: 5725.888567084208, + }, + }, + ], + }, + }, + }; + + const expected = { + [AGG_TYPES.AVERAGE]: [ + [1497675600000, 5721.5481573924535], + [1497718800000, 5696.727765965246], + [1497762000000, 5725.888567084208], + ], + }; + + const actual = formatVisualizeData(watch, response); + + expect(actual).to.eql(expected); + }); + + it('correctly formats data from a Non-Count Terms query', () => { + const watch = { + aggType: AGG_TYPES.AVERAGE, + termField: 'foo_term_field', + }; + + const response = { + aggregations: { + bucketAgg: { + buckets: [ + { + key: 'foo_term', + dateAgg: { + buckets: [ + { + key: 1498366800000, + metricAgg: { + value: 10741.000753579503, + }, + }, + { + key: 1498410000000, + metricAgg: { + value: 10350.321100917432, + }, + }, + { + key: 1498453200000, + metricAgg: { + value: 10534.54078549849, + }, + }, + ], + }, + metricAgg: { + value: 10477.102294853963, + }, + }, + { + key: 'bar_term', + dateAgg: { + buckets: [ + { + key: 1498366800000, + metricAgg: { + value: 5629.317614424411, + }, + }, + { + key: 1498410000000, + metricAgg: { + value: 5548.141689373297, + }, + }, + { + key: 1498453200000, + metricAgg: { + value: 5603.887494591086, + }, + }, + ], + }, + metricAgg: { + value: 5595.034518438806, + }, + }, + { + key: 'baz_term', + dateAgg: { + buckets: [ + { + key: 1498366800000, + metricAgg: { + value: 5577.867537733724, + }, + }, + { + key: 1498410000000, + metricAgg: { + value: 5543.652870647913, + }, + }, + { + key: 1498453200000, + metricAgg: { + value: 5553.1327981651375, + }, + }, + ], + }, + metricAgg: { + value: 5567.288459750643, + }, + }, + ], + }, + }, + }; + + const expected = { + foo_term: [ + [1498366800000, 10741.000753579503], + [1498410000000, 10350.321100917432], + [1498453200000, 10534.54078549849], + ], + bar_term: [ + [1498366800000, 5629.317614424411], + [1498410000000, 5548.141689373297], + [1498453200000, 5603.887494591086], + ], + baz_term: [ + [1498366800000, 5577.867537733724], + [1498410000000, 5543.652870647913], + [1498453200000, 5553.1327981651375], + ], + }; + + const actual = formatVisualizeData(watch, response); + + expect(actual).to.eql(expected); + }); + }); +}); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/build_visualize_query.js b/x-pack/plugins/watcher/server/models/watch/threshold_watch/build_visualize_query.js similarity index 95% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/build_visualize_query.js rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/build_visualize_query.js index cc79aec682400d..84bdae6ad95fdf 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/build_visualize_query.js +++ b/x-pack/plugins/watcher/server/models/watch/threshold_watch/build_visualize_query.js @@ -5,8 +5,8 @@ */ import { cloneDeep } from 'lodash'; -import { buildInput } from '../../../../../common/lib/serialization'; -import { AGG_TYPES } from '../../../../../common/constants'; +import { buildInput } from '../../../../common/lib/serialization'; +import { AGG_TYPES } from '../../../../common/constants'; /* input.search.request.body.query.bool.filter.range diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count.query.date.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count.query.date.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count.query.date.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count.query.date.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count.query.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count.query.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count.query.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count.query.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count_terms.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count_terms.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count_terms.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count_terms.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count_terms.query.date.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count_terms.query.date.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count_terms.query.date.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count_terms.query.date.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count_terms.query.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count_terms.query.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/count_terms.query.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/count_terms.query.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count.query.date.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count.query.date.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count.query.date.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count.query.date.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count.query.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count.query.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count.query.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count.query.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count_terms.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count_terms.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count_terms.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count_terms.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count_terms.query.date.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count_terms.query.date.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count_terms.query.date.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count_terms.query.date.json diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count_terms.query.json b/x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count_terms.query.json similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/data_samples/non_count_terms.query.json rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/data_samples/non_count_terms.query.json diff --git a/x-pack/plugins/watcher/server/models/watch/threshold_watch/format_visualize_data.js b/x-pack/plugins/watcher/server/models/watch/threshold_watch/format_visualize_data.js new file mode 100644 index 00000000000000..c93add71bfe38f --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch/threshold_watch/format_visualize_data.js @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { AGG_TYPES } from '../../../../common/constants'; + +export function formatVisualizeData({ aggType, termField }, results) { + if (aggType === AGG_TYPES.COUNT && !Boolean(termField)) { + return formatCount(aggType, results); + } + + if (aggType === AGG_TYPES.COUNT && Boolean(termField)) { + return formatCountTerms(results); + } + + if (aggType !== AGG_TYPES.COUNT && !Boolean(termField)) { + return formatNonCount(aggType, results); + } + + if (aggType !== AGG_TYPES.COUNT && Boolean(termField)) { + return formatNonCountTerms(results); + } +} + +// Count without terms +// See ./data_samples/count.json +function formatCount(aggType, results) { + const result = {}; + const buckets = results.aggregations.dateAgg.buckets; + + buckets.forEach(({ key: date, doc_count: value }) => { + result[aggType] = result[aggType] || []; + result[aggType].push([date, value]); + }); + + return result; +} + +// Count with terms +// See ./data_samples/count_terms.json +function formatCountTerms(results) { + const result = {}; + const buckets = results.aggregations.bucketAgg.buckets; + + buckets.forEach(({ key: term, dateAgg: { buckets: subBuckets } }) => { + subBuckets.forEach(({ key: date, doc_count: value }) => { + result[term] = result[term] || []; + result[term].push([date, value]); + }); + }); + + return result; +} + +// Other metric without terms +// See ./data_samples/non_count.json +function formatNonCount(aggType, results) { + const result = {}; + const buckets = results.aggregations.dateAgg.buckets; + + buckets.forEach(({ key: date, metricAgg: { value } }) => { + result[aggType] = result[aggType] || []; + result[aggType].push([date, value]); + }); + + return result; +} + +// Other metric with terms +// See ./data_samples/non_count_terms.json +function formatNonCountTerms(results) { + const result = {}; + const buckets = results.aggregations.bucketAgg.buckets; + + buckets.forEach(({ key: term, dateAgg: { buckets: subBuckets } }) => { + subBuckets.forEach(({ key: date, metricAgg: { value } }) => { + result[term] = result[term] || []; + result[term].push([date, value]); + }); + }); + + return result; +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/index.js b/x-pack/plugins/watcher/server/models/watch/threshold_watch/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/index.js rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/index.js diff --git a/x-pack/plugins/watcher/server/models/watch/threshold_watch/threshold_watch.js b/x-pack/plugins/watcher/server/models/watch/threshold_watch/threshold_watch.js new file mode 100644 index 00000000000000..ebef741200e003 --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch/threshold_watch/threshold_watch.js @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { merge } from 'lodash'; +import { BaseWatch } from '../base_watch'; +import { WATCH_TYPES, COMPARATORS, SORT_ORDERS } from '../../../../common/constants'; +import { serializeThresholdWatch } from '../../../../common/lib/serialization'; + +import { buildVisualizeQuery } from './build_visualize_query'; +import { formatVisualizeData } from './format_visualize_data'; + +export class ThresholdWatch extends BaseWatch { + // This constructor should not be used directly. + // JsonWatch objects should be instantiated using the + // fromUpstreamJson and fromDownstreamJson static methods + constructor(props) { + super(props); + + this.index = props.index; + this.timeField = props.timeField; + this.triggerIntervalSize = props.triggerIntervalSize; + this.triggerIntervalUnit = props.triggerIntervalUnit; + this.aggType = props.aggType; + this.aggField = props.aggField; + this.termSize = props.termSize; + this.termField = props.termField; + this.thresholdComparator = props.thresholdComparator; + this.timeWindowSize = props.timeWindowSize; + this.timeWindowUnit = props.timeWindowUnit; + this.threshold = props.threshold; + } + + get hasTermsAgg() { + return Boolean(this.termField); + } + + get termOrder() { + return this.thresholdComparator === COMPARATORS.GREATER_THAN + ? SORT_ORDERS.DESCENDING + : SORT_ORDERS.ASCENDING; + } + + get watchJson() { + return serializeThresholdWatch(this); + } + + getVisualizeQuery(visualizeOptions) { + return buildVisualizeQuery(this, visualizeOptions); + } + + formatVisualizeData(results) { + return formatVisualizeData(this, results); + } + + // To Kibana + get downstreamJson() { + const result = merge({}, super.downstreamJson, { + index: this.index, + timeField: this.timeField, + triggerIntervalSize: this.triggerIntervalSize, + triggerIntervalUnit: this.triggerIntervalUnit, + aggType: this.aggType, + aggField: this.aggField, + termSize: this.termSize, + termField: this.termField, + thresholdComparator: this.thresholdComparator, + timeWindowSize: this.timeWindowSize, + timeWindowUnit: this.timeWindowUnit, + threshold: this.threshold, + }); + + return result; + } + + // from Elasticsearch + static fromUpstreamJson(json) { + const metadata = json.watchJson.metadata.watcherui; + + const props = merge({}, super.getPropsFromUpstreamJson(json), { + type: WATCH_TYPES.THRESHOLD, + index: metadata.index, + timeField: metadata.time_field, + triggerIntervalSize: metadata.trigger_interval_size, + triggerIntervalUnit: metadata.trigger_interval_unit, + aggType: metadata.agg_type, + aggField: metadata.agg_field, + termSize: metadata.term_size, + termField: metadata.term_field, + thresholdComparator: metadata.threshold_comparator, + timeWindowSize: metadata.time_window_size, + timeWindowUnit: metadata.time_window_unit, + threshold: Array.isArray(metadata.threshold) ? metadata.threshold : [metadata.threshold], + }); + + return new ThresholdWatch(props); + } + + // from Kibana + static fromDownstreamJson({ + id, + name, + actions, + index, + timeField, + triggerIntervalSize, + triggerIntervalUnit, + aggType, + aggField, + termSize, + termField, + thresholdComparator, + timeWindowSize, + timeWindowUnit, + threshold, + }) { + const props = { + type: WATCH_TYPES.THRESHOLD, + id, + name, + actions, + index, + timeField, + triggerIntervalSize, + triggerIntervalUnit, + aggType, + aggField, + termSize, + termField, + thresholdComparator, + timeWindowSize, + timeWindowUnit, + threshold, + }; + + return new ThresholdWatch(props); + } +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/threshold_watch.test.js b/x-pack/plugins/watcher/server/models/watch/threshold_watch/threshold_watch.test.js similarity index 99% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/threshold_watch.test.js rename to x-pack/plugins/watcher/server/models/watch/threshold_watch/threshold_watch.test.js index e65342708c9d5a..af4aae54fbfeac 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/threshold_watch/threshold_watch.test.js +++ b/x-pack/plugins/watcher/server/models/watch/threshold_watch/threshold_watch.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { COMPARATORS, SORT_ORDERS } from '../../../../../common/constants'; +import { COMPARATORS, SORT_ORDERS } from '../../../../common/constants'; import { WatchErrors } from '../../watch_errors'; import { ThresholdWatch } from './threshold_watch'; diff --git a/x-pack/plugins/watcher/server/models/watch/watch.js b/x-pack/plugins/watcher/server/models/watch/watch.js new file mode 100644 index 00000000000000..febf9c20b07a65 --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch/watch.js @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { set } from 'lodash'; +import { badRequest } from 'boom'; +import { WATCH_TYPES } from '../../../common/constants'; +import { JsonWatch } from './json_watch'; +import { MonitoringWatch } from './monitoring_watch'; +import { ThresholdWatch } from './threshold_watch'; +import { getWatchType } from './lib/get_watch_type'; +import { i18n } from '@kbn/i18n'; + +const WatchTypes = {}; +set(WatchTypes, WATCH_TYPES.JSON, JsonWatch); +set(WatchTypes, WATCH_TYPES.MONITORING, MonitoringWatch); +set(WatchTypes, WATCH_TYPES.THRESHOLD, ThresholdWatch); + +export class Watch { + static getWatchTypes = () => { + return WatchTypes; + }; + + // from Kibana + static fromDownstreamJson(json) { + if (!json.type) { + throw badRequest( + i18n.translate('xpack.watcher.models.watch.typePropertyMissingBadRequestMessage', { + defaultMessage: 'JSON argument must contain an {type} property', + values: { + type: 'type', + }, + }) + ); + } + + const WatchType = WatchTypes[json.type]; + if (!WatchType) { + throw badRequest( + i18n.translate( + 'xpack.watcher.models.watch.unknownWatchTypeLoadingAttemptBadRequestMessage', + { + defaultMessage: 'Attempted to load unknown type {jsonType}', + values: { jsonType: json.type }, + } + ) + ); + } + + return WatchType.fromDownstreamJson(json); + } + + // from Elasticsearch + static fromUpstreamJson(json, options) { + if (!json.watchJson) { + throw badRequest( + i18n.translate('xpack.watcher.models.watch.watchJsonPropertyMissingBadRequestMessage', { + defaultMessage: 'JSON argument must contain a {watchJson} property', + values: { + watchJson: 'watchJson', + }, + }) + ); + } + + const type = getWatchType(json.watchJson); + const WatchType = WatchTypes[type]; + + return WatchType.fromUpstreamJson(json, options); + } +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/watch.test.js b/x-pack/plugins/watcher/server/models/watch/watch.test.js similarity index 98% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch/watch.test.js rename to x-pack/plugins/watcher/server/models/watch/watch.test.js index d6e23e727d5750..51eeb6a8c05386 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch/watch.test.js +++ b/x-pack/plugins/watcher/server/models/watch/watch.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { WATCH_TYPES } from '../../../../common/constants'; +import { WATCH_TYPES } from '../../../common/constants'; import { Watch } from './watch'; import { JsonWatch } from './json_watch'; import { MonitoringWatch } from './monitoring_watch'; diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_errors/index.js b/x-pack/plugins/watcher/server/models/watch_errors/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch_errors/index.js rename to x-pack/plugins/watcher/server/models/watch_errors/index.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_errors/watch_errors.js b/x-pack/plugins/watcher/server/models/watch_errors/watch_errors.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch_errors/watch_errors.js rename to x-pack/plugins/watcher/server/models/watch_errors/watch_errors.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_errors/watch_errors.test.js b/x-pack/plugins/watcher/server/models/watch_errors/watch_errors.test.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch_errors/watch_errors.test.js rename to x-pack/plugins/watcher/server/models/watch_errors/watch_errors.test.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_history_item/__tests__/watch_history_item.js b/x-pack/plugins/watcher/server/models/watch_history_item/__tests__/watch_history_item.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch_history_item/__tests__/watch_history_item.js rename to x-pack/plugins/watcher/server/models/watch_history_item/__tests__/watch_history_item.js diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_history_item/index.js b/x-pack/plugins/watcher/server/models/watch_history_item/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch_history_item/index.js rename to x-pack/plugins/watcher/server/models/watch_history_item/index.js diff --git a/x-pack/plugins/watcher/server/models/watch_history_item/watch_history_item.js b/x-pack/plugins/watcher/server/models/watch_history_item/watch_history_item.js new file mode 100644 index 00000000000000..134b201628195e --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch_history_item/watch_history_item.js @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { badRequest } from 'boom'; +import { getMoment } from '../../../common/lib/get_moment'; +import { get, cloneDeep } from 'lodash'; +import { WatchStatus } from '../watch_status'; +import { i18n } from '@kbn/i18n'; + +export class WatchHistoryItem { + constructor(props) { + this.id = props.id; + this.watchId = props.watchId; + this.watchHistoryItemJson = props.watchHistoryItemJson; + this.includeDetails = Boolean(props.includeDetails); + + this.details = cloneDeep(this.watchHistoryItemJson); + this.startTime = getMoment(get(this.watchHistoryItemJson, 'result.execution_time')); + + const watchStatusJson = get(this.watchHistoryItemJson, 'status'); + const state = get(this.watchHistoryItemJson, 'state'); + this.watchStatus = WatchStatus.fromUpstreamJson({ id: this.watchId, watchStatusJson, state }); + } + + get downstreamJson() { + return { + id: this.id, + watchId: this.watchId, + details: this.includeDetails ? this.details : null, + startTime: this.startTime.toISOString(), + watchStatus: this.watchStatus.downstreamJson, + }; + } + + // generate object from elasticsearch response + static fromUpstreamJson(json, opts) { + if (!json.id) { + throw badRequest( + i18n.translate('xpack.watcher.models.watchHistoryItem.idPropertyMissingBadRequestMessage', { + defaultMessage: 'JSON argument must contain an {id} property', + values: { + id: 'id', + }, + }) + ); + } + if (!json.watchId) { + throw badRequest( + i18n.translate( + 'xpack.watcher.models.watchHistoryItem.watchIdPropertyMissingBadRequestMessage', + { + defaultMessage: 'JSON argument must contain a {watchId} property', + values: { + watchId: 'watchId', + }, + } + ) + ); + } + if (!json.watchHistoryItemJson) { + throw badRequest( + i18n.translate( + 'xpack.watcher.models.watchHistoryItem.watchHistoryItemJsonPropertyMissingBadRequestMessage', + { + defaultMessage: 'JSON argument must contain a {watchHistoryItemJson} property', + values: { + watchHistoryItemJson: 'watchHistoryItemJson', + }, + } + ) + ); + } + + const props = { ...json, ...opts }; + return new WatchHistoryItem(props); + } +} diff --git a/x-pack/plugins/watcher/server/models/watch_status/__tests__/watch_status.js b/x-pack/plugins/watcher/server/models/watch_status/__tests__/watch_status.js new file mode 100644 index 00000000000000..0d6731b90abe65 --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch_status/__tests__/watch_status.js @@ -0,0 +1,314 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { WatchStatus } from '../watch_status'; +import { ACTION_STATES, WATCH_STATES, WATCH_STATE_COMMENTS } from '../../../../common/constants'; +import moment from 'moment'; + +describe('watch_status', () => { + describe('WatchStatus', () => { + describe('fromUpstreamJson factory method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-watch', + watchStatusJson: { + state: { + active: true, + }, + last_checked: '2017-03-02T14:25:31.139Z', + last_met_condition: '2017-07-05T14:25:31.139Z', + actions: { + foo: {}, + bar: {}, + }, + }, + }; + }); + + it(`throws an error if no 'id' property in json`, () => { + delete upstreamJson.id; + expect(WatchStatus.fromUpstreamJson) + .withArgs(upstreamJson) + .to.throwError(/must contain an id property/i); + }); + + it(`throws an error if no 'watchStatusJson' property in json`, () => { + delete upstreamJson.watchStatusJson; + expect(WatchStatus.fromUpstreamJson) + .withArgs(upstreamJson) + .to.throwError(/must contain a watchStatusJson property/i); + }); + + it('returns correct WatchStatus instance', () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + expect(watchStatus.id).to.be(upstreamJson.id); + expect(watchStatus.watchStatusJson).to.eql(upstreamJson.watchStatusJson); + expect(watchStatus.isActive).to.eql(true); + expect(watchStatus.lastChecked).to.eql(moment(upstreamJson.watchStatusJson.last_checked)); + expect(watchStatus.lastMetCondition).to.eql( + moment(upstreamJson.watchStatusJson.last_met_condition) + ); + expect(watchStatus.actionStatuses.length).to.be(2); + + expect(watchStatus.actionStatuses[0].constructor.name).to.be('ActionStatus'); + expect(watchStatus.actionStatuses[1].constructor.name).to.be('ActionStatus'); + }); + }); + + describe('lastFired getter method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-watch', + watchStatusJson: { + actions: { + foo: { + last_execution: { + timestamp: '2017-07-05T00:00:00.000Z', + }, + }, + bar: { + last_execution: { + timestamp: '2025-07-05T00:00:00.000Z', + }, + }, + baz: {}, + }, + }, + }; + }); + + it(`returns the latest lastExecution from it's actions`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + expect(watchStatus.lastFired).to.eql( + moment(upstreamJson.watchStatusJson.actions.bar.last_execution.timestamp) + ); + }); + }); + + describe('comment getter method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-watch', + watchStatusJson: { + state: { + active: true, + }, + }, + }; + }); + + it(`correctly calculates WATCH_STATE_COMMENTS.OK there are no actions`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + watchStatus.isActive = true; + expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.OK); + }); + + it(`correctly calculates WATCH_STATE_COMMENTS.PARTIALLY_THROTTLED`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.FIRING }, + { state: ACTION_STATES.OK }, + ]; + + expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.PARTIALLY_THROTTLED); + }); + + it(`correctly calculates WATCH_STATE_COMMENTS.THROTTLED`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.THROTTLED }, + ]; + + expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.THROTTLED); + }); + + it(`correctly calculates WATCH_STATE_COMMENTS.PARTIALLY_ACKNOWLEDGED`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.ACKNOWLEDGED }, + { state: ACTION_STATES.OK }, + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.FIRING }, + ]; + + expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.PARTIALLY_ACKNOWLEDGED); + }); + + it(`correctly calculates WATCH_STATE_COMMENTS.ACKNOWLEDGED`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.ACKNOWLEDGED }, + { state: ACTION_STATES.ACKNOWLEDGED }, + { state: ACTION_STATES.ACKNOWLEDGED }, + ]; + + expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.ACKNOWLEDGED); + }); + + it(`correctly calculates WATCH_STATE_COMMENTS.FAILING`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.OK }, + { state: ACTION_STATES.ACKNOWLEDGED }, + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.FIRING }, + { state: ACTION_STATES.ERROR }, + ]; + + expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.FAILING); + }); + + it(`correctly calculates WATCH_STATE_COMMENTS.OK when watch is inactive`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + watchStatus.isActive = false; + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.OK }, + { state: ACTION_STATES.ACKNOWLEDGED }, + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.FIRING }, + { state: ACTION_STATES.ERROR }, + ]; + + expect(watchStatus.comment).to.be(WATCH_STATE_COMMENTS.OK); + }); + }); + + describe('state getter method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-watch', + watchStatusJson: { + state: { + active: true, + }, + }, + }; + }); + + it(`correctly calculates WATCH_STATES.OK there are no actions`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + watchStatus.isActive = true; + expect(watchStatus.state).to.be(WATCH_STATES.OK); + }); + + it(`correctly calculates WATCH_STATES.FIRING`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + watchStatus.actionStatuses = [{ state: ACTION_STATES.OK }, { state: ACTION_STATES.FIRING }]; + expect(watchStatus.state).to.be(WATCH_STATES.FIRING); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.OK }, + { state: ACTION_STATES.FIRING }, + { state: ACTION_STATES.THROTTLED }, + ]; + expect(watchStatus.state).to.be(WATCH_STATES.FIRING); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.OK }, + { state: ACTION_STATES.FIRING }, + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.ACKNOWLEDGED }, + ]; + expect(watchStatus.state).to.be(WATCH_STATES.FIRING); + }); + + it(`correctly calculates WATCH_STATES.ERROR`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.OK }, + { state: ACTION_STATES.FIRING }, + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.ACKNOWLEDGED }, + { state: ACTION_STATES.ERROR }, + ]; + + expect(watchStatus.state).to.be(WATCH_STATES.ERROR); + }); + + it('correctly calculates WATCH_STATE.CONFIG_ERROR', () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.OK }, + { state: ACTION_STATES.CONFIG_ERROR }, + ]; + + expect(watchStatus.state).to.be(WATCH_STATES.CONFIG_ERROR); + }); + + it(`correctly calculates WATCH_STATES.DISABLED when watch is inactive`, () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + watchStatus.isActive = false; + + watchStatus.actionStatuses = [ + { state: ACTION_STATES.OK }, + { state: ACTION_STATES.FIRING }, + { state: ACTION_STATES.THROTTLED }, + { state: ACTION_STATES.ACKNOWLEDGED }, + { state: ACTION_STATES.ERROR }, + ]; + + expect(watchStatus.state).to.be(WATCH_STATES.DISABLED); + }); + }); + + describe('downstreamJson getter method', () => { + let upstreamJson; + beforeEach(() => { + upstreamJson = { + id: 'my-watch', + watchStatusJson: { + state: { + active: true, + }, + last_checked: '2017-03-02T14:25:31.139Z', + last_met_condition: '2017-07-05T14:25:31.139Z', + actions: { + foo: {}, + bar: {}, + }, + }, + }; + }); + + it('returns correct downstream JSON object', () => { + const watchStatus = WatchStatus.fromUpstreamJson(upstreamJson); + watchStatus.actionStatuses = [ + { id: 'foo', state: ACTION_STATES.OK }, + { id: 'bar', state: ACTION_STATES.OK }, + ]; + + const actual = watchStatus.downstreamJson; + + expect(actual.id).to.be(watchStatus.id); + expect(actual.state).to.be(watchStatus.state); + expect(actual.comment).to.be(watchStatus.comment); + expect(actual.isActive).to.be(watchStatus.isActive); + expect(actual.lastChecked).to.be(watchStatus.lastChecked); + expect(actual.lastMetCondition).to.be(watchStatus.lastMetCondition); + expect(actual.lastFired).to.be(watchStatus.lastFired); + expect(actual.actionStatuses.length).to.be(2); + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/models/watch_status/index.js b/x-pack/plugins/watcher/server/models/watch_status/index.js similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/models/watch_status/index.js rename to x-pack/plugins/watcher/server/models/watch_status/index.js diff --git a/x-pack/plugins/watcher/server/models/watch_status/watch_status.js b/x-pack/plugins/watcher/server/models/watch_status/watch_status.js new file mode 100644 index 00000000000000..a346885965a166 --- /dev/null +++ b/x-pack/plugins/watcher/server/models/watch_status/watch_status.js @@ -0,0 +1,200 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get, map, forEach, max } from 'lodash'; +import { badRequest } from 'boom'; +import { getMoment } from '../../../common/lib/get_moment'; +import { ActionStatus } from '../action_status'; +import { ACTION_STATES, WATCH_STATES, WATCH_STATE_COMMENTS } from '../../../common/constants'; +import { i18n } from '@kbn/i18n'; + +function getActionStatusTotals(watchStatus) { + const result = {}; + + forEach(ACTION_STATES, state => { + result[state] = 0; + }); + forEach(watchStatus.actionStatuses, actionStatus => { + result[actionStatus.state] = result[actionStatus.state] + 1; + }); + + return result; +} + +const WATCH_STATE_FAILED = 'failed'; + +export class WatchStatus { + constructor(props) { + this.id = props.id; + this.watchState = props.state; + this.watchStatusJson = props.watchStatusJson; + this.watchErrors = props.watchErrors || {}; + + this.isActive = Boolean(get(this.watchStatusJson, 'state.active')); + this.lastChecked = getMoment(get(this.watchStatusJson, 'last_checked')); + this.lastMetCondition = getMoment(get(this.watchStatusJson, 'last_met_condition')); + + const actionStatusesJson = get(this.watchStatusJson, 'actions', {}); + this.actionStatuses = map(actionStatusesJson, (actionStatusJson, id) => { + const json = { + id, + actionStatusJson, + errors: this.watchErrors.actions && this.watchErrors.actions[id], + }; + return ActionStatus.fromUpstreamJson(json); + }); + } + + get state() { + if (!this.isActive) { + return WATCH_STATES.DISABLED; + } + + if (this.watchState === WATCH_STATE_FAILED) { + return WATCH_STATES.ERROR; + } + + const totals = getActionStatusTotals(this); + + if (totals[ACTION_STATES.ERROR] > 0) { + return WATCH_STATES.ERROR; + } + + if (totals[ACTION_STATES.CONFIG_ERROR] > 0) { + return WATCH_STATES.CONFIG_ERROR; + } + + const firingTotal = + totals[ACTION_STATES.FIRING] + + totals[ACTION_STATES.ACKNOWLEDGED] + + totals[ACTION_STATES.THROTTLED]; + + if (firingTotal > 0) { + return WATCH_STATES.FIRING; + } + + return WATCH_STATES.OK; + } + + get comment() { + const totals = getActionStatusTotals(this); + const totalActions = this.actionStatuses.length; + let result = WATCH_STATE_COMMENTS.OK; + + if (totals[ACTION_STATES.THROTTLED] > 0 && totals[ACTION_STATES.THROTTLED] < totalActions) { + result = WATCH_STATE_COMMENTS.PARTIALLY_THROTTLED; + } + + if (totals[ACTION_STATES.THROTTLED] > 0 && totals[ACTION_STATES.THROTTLED] === totalActions) { + result = WATCH_STATE_COMMENTS.THROTTLED; + } + + if ( + totals[ACTION_STATES.ACKNOWLEDGED] > 0 && + totals[ACTION_STATES.ACKNOWLEDGED] < totalActions + ) { + result = WATCH_STATE_COMMENTS.PARTIALLY_ACKNOWLEDGED; + } + + if ( + totals[ACTION_STATES.ACKNOWLEDGED] > 0 && + totals[ACTION_STATES.ACKNOWLEDGED] === totalActions + ) { + result = WATCH_STATE_COMMENTS.ACKNOWLEDGED; + } + + if (totals[ACTION_STATES.ERROR] > 0) { + result = WATCH_STATE_COMMENTS.FAILING; + } + + if (!this.isActive) { + result = WATCH_STATE_COMMENTS.OK; + } + + return result; + } + + get lastFired() { + const actionStatus = max(this.actionStatuses, 'lastExecution'); + if (actionStatus) { + return actionStatus.lastExecution; + } + } + + // generate object to send to kibana + get downstreamJson() { + const json = { + id: this.id, + state: this.state, + comment: this.comment, + isActive: this.isActive, + lastChecked: this.lastChecked, + lastMetCondition: this.lastMetCondition, + lastFired: this.lastFired, + actionStatuses: map(this.actionStatuses, actionStatus => actionStatus.downstreamJson), + }; + + return json; + } + + // generate object from elasticsearch response + static fromUpstreamJson(json) { + if (!json.id) { + throw badRequest( + i18n.translate('xpack.watcher.models.watchStatus.idPropertyMissingBadRequestMessage', { + defaultMessage: 'JSON argument must contain an {id} property', + values: { + id: 'id', + }, + }) + ); + } + if (!json.watchStatusJson) { + throw badRequest( + i18n.translate( + 'xpack.watcher.models.watchStatus.watchStatusJsonPropertyMissingBadRequestMessage', + { + defaultMessage: 'JSON argument must contain a {watchStatusJson} property', + values: { + watchStatusJson: 'watchStatusJson', + }, + } + ) + ); + } + + return new WatchStatus(json); + } + + /* + json.watchStatusJson should have the following structure: + { + "state": { + "active": true, + "timestamp": "2017-03-01T19:05:49.400Z" + }, + "actions": { + "log-me-something": { + "ack": { + "timestamp": "2017-03-01T20:56:58.442Z", + "state": "acked" + }, + "last_execution": { + "timestamp": "2017-03-01T20:55:49.679Z", + "successful": true + }, + "last_successful_execution": { + "timestamp": "2017-03-01T20:55:49.679Z", + "successful": true + } + } + }, + "version": 15, + "last_checked": "2017-03-02T14:25:31.139Z", + "last_met_condition": "2017-03-02T14:25:31.139Z" + } + */ +} diff --git a/x-pack/plugins/watcher/server/plugin.ts b/x-pack/plugins/watcher/server/plugin.ts new file mode 100644 index 00000000000000..1f7b3823609eca --- /dev/null +++ b/x-pack/plugins/watcher/server/plugin.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; + * you may not use this file except in compliance with the Elastic License. + */ +import { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'kibana/server'; +import { PLUGIN } from '../common/constants'; +import { Dependencies, LicenseStatus, RouteDependencies } from './types'; +import { LICENSE_CHECK_STATE } from '../../licensing/server'; + +import { registerSettingsRoutes } from './routes/api/settings'; +import { registerIndicesRoutes } from './routes/api/indices'; +import { registerLicenseRoutes } from './routes/api/license'; +import { registerWatchesRoutes } from './routes/api/watches'; +import { registerWatchRoutes } from './routes/api/watch'; +import { registerListFieldsRoute } from './routes/api/register_list_fields_route'; +import { registerLoadHistoryRoute } from './routes/api/register_load_history_route'; + +export class WatcherServerPlugin implements Plugin { + log: Logger; + + private licenseStatus: LicenseStatus = { + hasRequired: false, + }; + + constructor(ctx: PluginInitializerContext) { + this.log = ctx.logger.get(); + } + + async setup( + { http, elasticsearch: elasticsearchService }: CoreSetup, + { licensing }: Dependencies + ) { + const elasticsearch = await elasticsearchService.adminClient; + const router = http.createRouter(); + const routeDependencies: RouteDependencies = { + elasticsearch, + elasticsearchService, + router, + getLicenseStatus: () => this.licenseStatus, + }; + + registerListFieldsRoute(routeDependencies); + registerLoadHistoryRoute(routeDependencies); + registerIndicesRoutes(routeDependencies); + registerLicenseRoutes(routeDependencies); + registerSettingsRoutes(routeDependencies); + registerWatchesRoutes(routeDependencies); + registerWatchRoutes(routeDependencies); + + licensing.license$.subscribe(async license => { + const { state, message } = license.check(PLUGIN.ID, PLUGIN.MINIMUM_LICENSE_REQUIRED); + const hasMinimumLicense = state === LICENSE_CHECK_STATE.Valid; + if (hasMinimumLicense && license.getFeature(PLUGIN.ID)) { + this.log.info('Enabling Watcher plugin.'); + this.licenseStatus = { + hasRequired: true, + }; + } else { + if (message) { + this.log.info(message); + } + this.licenseStatus = { + hasRequired: false, + message, + }; + } + }); + } + start() {} + stop() {} +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/indices/index.ts b/x-pack/plugins/watcher/server/routes/api/indices/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/indices/index.ts rename to x-pack/plugins/watcher/server/routes/api/indices/index.ts diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/indices/register_get_route.ts b/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts similarity index 91% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/indices/register_get_route.ts rename to x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts index 6b6b643dc4adf1..30607b82e32950 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/indices/register_get_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts @@ -5,12 +5,12 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { reduce, size } from 'lodash'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { isEsError } from '../../../lib/is_es_error'; +import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; function getIndexNamesFromAliasesResponse(json: Record) { return reduce( @@ -61,7 +61,7 @@ function getIndices(callWithRequest: any, pattern: string, limit = 10) { }); } -export function registerGetRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerGetRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const { pattern } = request.body; @@ -87,6 +87,6 @@ export function registerGetRoute(deps: RouteDependencies, legacy: ServerShim) { body: schema.object({}, { allowUnknowns: true }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/plugins/watcher/server/routes/api/indices/register_indices_routes.ts b/x-pack/plugins/watcher/server/routes/api/indices/register_indices_routes.ts new file mode 100644 index 00000000000000..db8dbdc8618d45 --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/indices/register_indices_routes.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { registerGetRoute } from './register_get_route'; +import { RouteDependencies } from '../../../types'; + +export function registerIndicesRoutes(deps: RouteDependencies) { + registerGetRoute(deps); +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/license/index.ts b/x-pack/plugins/watcher/server/routes/api/license/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/license/index.ts rename to x-pack/plugins/watcher/server/routes/api/license/index.ts diff --git a/x-pack/plugins/watcher/server/routes/api/license/register_license_routes.ts b/x-pack/plugins/watcher/server/routes/api/license/register_license_routes.ts new file mode 100644 index 00000000000000..9b7f6272442bd9 --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/license/register_license_routes.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { registerRefreshRoute } from './register_refresh_route'; +import { RouteDependencies } from '../../../types'; + +export function registerLicenseRoutes(deps: RouteDependencies) { + registerRefreshRoute(deps); +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/license/register_refresh_route.ts b/x-pack/plugins/watcher/server/routes/api/license/register_refresh_route.ts similarity index 78% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/license/register_refresh_route.ts rename to x-pack/plugins/watcher/server/routes/api/license/register_refresh_route.ts index 08f1f26a84a4fb..a61fd16e8be4ad 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/license/register_refresh_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/license/register_refresh_route.ts @@ -4,17 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; +import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; - /* In order for the client to have the most up-to-date snapshot of the current license, it needs to make a round-trip to the kibana server. This refresh endpoint is provided for when the client needs to check the license, but doesn't need to pull data from the server for any reason, i.e., when adding a new watch. */ -export function registerRefreshRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerRefreshRoute(deps: RouteDependencies) { const handler: RequestHandler = (ctx, request, response) => { return response.ok({ body: { success: true } }); }; @@ -24,6 +23,6 @@ export function registerRefreshRoute(deps: RouteDependencies, legacy: ServerShim path: '/api/watcher/license/refresh', validate: false, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/register_list_fields_route.ts b/x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts similarity index 86% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/register_list_fields_route.ts rename to x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts index f3222d24f0adf9..7c47379b875892 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/register_list_fields_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts @@ -5,13 +5,13 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { callWithRequestFactory } from '../../lib/call_with_request_factory'; import { isEsError } from '../../lib/is_es_error'; -import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory'; // @ts-ignore -import { Fields } from '../../models/fields'; -import { RouteDependencies, ServerShim } from '../../types'; +import { Fields } from '../../models/fields/index'; +import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory'; +import { RouteDependencies } from '../../types'; function fetchFields(callWithRequest: any, indexes: string[]) { const params = { @@ -25,7 +25,7 @@ function fetchFields(callWithRequest: any, indexes: string[]) { return callWithRequest('fieldCaps', params); } -export function registerListFieldsRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerListFieldsRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const { indexes } = request.body; @@ -60,6 +60,6 @@ export function registerListFieldsRoute(deps: RouteDependencies, legacy: ServerS }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/register_load_history_route.ts b/x-pack/plugins/watcher/server/routes/api/register_load_history_route.ts similarity index 90% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/register_load_history_route.ts rename to x-pack/plugins/watcher/server/routes/api/register_load_history_route.ts index d62e4f48c56296..1be8477df79bc7 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/register_load_history_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/register_load_history_route.ts @@ -6,14 +6,14 @@ import { schema } from '@kbn/config-schema'; import { get } from 'lodash'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { callWithRequestFactory } from '../../lib/call_with_request_factory'; import { isEsError } from '../../lib/is_es_error'; -import { INDEX_NAMES } from '../../../../common/constants'; +import { INDEX_NAMES } from '../../../common/constants'; +import { RouteDependencies } from '../../types'; import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../types'; // @ts-ignore -import { WatchHistoryItem } from '../../models/watch_history_item'; +import { WatchHistoryItem } from '../../models/watch_history_item/index'; function fetchHistoryItem(callWithRequest: any, watchHistoryItemId: string) { return callWithRequest('search', { @@ -28,7 +28,7 @@ function fetchHistoryItem(callWithRequest: any, watchHistoryItemId: string) { }); } -export function registerLoadHistoryRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerLoadHistoryRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const id = request.params.id; @@ -72,6 +72,6 @@ export function registerLoadHistoryRoute(deps: RouteDependencies, legacy: Server }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/settings/index.ts b/x-pack/plugins/watcher/server/routes/api/settings/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/settings/index.ts rename to x-pack/plugins/watcher/server/routes/api/settings/index.ts diff --git a/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.ts b/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.ts new file mode 100644 index 00000000000000..6c70c2d0d07b6a --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IClusterClient, RequestHandler } from 'kibana/server'; +import { isEsError } from '../../../lib/is_es_error'; +// @ts-ignore +import { Settings } from '../../../models/settings/index'; +import { RouteDependencies } from '../../../types'; +import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; + +function fetchClusterSettings(client: IClusterClient) { + return client.callAsInternalUser('cluster.getSettings', { + includeDefaults: true, + filterPath: '**.xpack.notification', + }); +} + +export function registerLoadRoute(deps: RouteDependencies) { + const handler: RequestHandler = async (ctx, request, response) => { + try { + const settings = await fetchClusterSettings(deps.elasticsearch); + return response.ok({ body: Settings.fromUpstreamJson(settings).downstreamJson }); + } catch (e) { + // Case: Error from Elasticsearch JS client + if (isEsError(e)) { + return response.customError({ statusCode: e.statusCode, body: e }); + } + + // Case: default + return response.internalError({ body: e }); + } + }; + deps.router.get( + { + path: '/api/watcher/settings', + validate: false, + }, + licensePreRoutingFactory(deps, handler) + ); +} diff --git a/x-pack/plugins/watcher/server/routes/api/settings/register_settings_routes.ts b/x-pack/plugins/watcher/server/routes/api/settings/register_settings_routes.ts new file mode 100644 index 00000000000000..ea4aa6ea4381d9 --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/settings/register_settings_routes.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { registerLoadRoute } from './register_load_route'; +import { RouteDependencies } from '../../../types'; + +export function registerSettingsRoutes(deps: RouteDependencies) { + registerLoadRoute(deps); +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/action/index.ts b/x-pack/plugins/watcher/server/routes/api/watch/action/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/action/index.ts rename to x-pack/plugins/watcher/server/routes/api/watch/action/index.ts diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/action/register_acknowledge_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.ts similarity index 88% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/action/register_acknowledge_route.ts rename to x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.ts index d0cc0a27e87ff1..08eec7456e3a57 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/action/register_acknowledge_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.ts @@ -6,13 +6,13 @@ import { schema } from '@kbn/config-schema'; import { get } from 'lodash'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { callWithRequestFactory } from '../../../../lib/call_with_request_factory'; import { isEsError } from '../../../../lib/is_es_error'; -import { licensePreRoutingFactory } from '../../../../lib/license_pre_routing_factory'; // @ts-ignore -import { WatchStatus } from '../../../../models/watch_status'; -import { RouteDependencies, ServerShim } from '../../../../types'; +import { WatchStatus } from '../../../../models/watch_status/index'; +import { RouteDependencies } from '../../../../types'; +import { licensePreRoutingFactory } from '../../../../lib/license_pre_routing_factory'; function acknowledgeAction(callWithRequest: any, watchId: string, actionId: string) { return callWithRequest('watcher.ackWatch', { @@ -21,7 +21,7 @@ function acknowledgeAction(callWithRequest: any, watchId: string, actionId: stri }); } -export function registerAcknowledgeRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerAcknowledgeRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const { watchId, actionId } = request.params; @@ -60,6 +60,6 @@ export function registerAcknowledgeRoute(deps: RouteDependencies, legacy: Server }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/plugins/watcher/server/routes/api/watch/action/register_action_routes.ts b/x-pack/plugins/watcher/server/routes/api/watch/action/register_action_routes.ts new file mode 100644 index 00000000000000..c3109e1d091c10 --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/watch/action/register_action_routes.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { registerAcknowledgeRoute } from './register_acknowledge_route'; +import { RouteDependencies } from '../../../../types'; + +export function registerActionRoutes(deps: RouteDependencies) { + registerAcknowledgeRoute(deps); +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/index.ts b/x-pack/plugins/watcher/server/routes/api/watch/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/index.ts rename to x-pack/plugins/watcher/server/routes/api/watch/index.ts diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_activate_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.ts similarity index 85% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_activate_route.ts rename to x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.ts index 28c482124aaee0..fdc20854ed8c22 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_activate_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.ts @@ -5,14 +5,14 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { get } from 'lodash'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { isEsError } from '../../../lib/is_es_error'; +import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; // @ts-ignore -import { WatchStatus } from '../../../models/watch_status'; +import { WatchStatus } from '../../../models/watch_status/index'; function activateWatch(callWithRequest: any, watchId: string) { return callWithRequest('watcher.activateWatch', { @@ -20,7 +20,7 @@ function activateWatch(callWithRequest: any, watchId: string) { }); } -export function registerActivateRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerActivateRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); @@ -61,6 +61,6 @@ export function registerActivateRoute(deps: RouteDependencies, legacy: ServerShi }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_deactivate_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.ts similarity index 85% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_deactivate_route.ts rename to x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.ts index ac87066379a20c..08d99f42df0540 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_deactivate_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { get } from 'lodash'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { isEsError } from '../../../lib/is_es_error'; +import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; // @ts-ignore -import { WatchStatus } from '../../../models/watch_status'; +import { WatchStatus } from '../../../models/watch_status/index'; function deactivateWatch(callWithRequest: any, watchId: string) { return callWithRequest('watcher.deactivateWatch', { @@ -19,7 +19,7 @@ function deactivateWatch(callWithRequest: any, watchId: string) { }); } -export function registerDeactivateRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerDeactivateRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); @@ -60,6 +60,6 @@ export function registerDeactivateRoute(deps: RouteDependencies, legacy: ServerS }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.ts new file mode 100644 index 00000000000000..6e95cf959bc9ca --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { RequestHandler } from 'kibana/server'; +import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; +import { isEsError } from '../../../lib/is_es_error'; +import { RouteDependencies } from '../../../types'; +import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; + +function deleteWatch(callWithRequest: any, watchId: string) { + return callWithRequest('watcher.deleteWatch', { + id: watchId, + }); +} + +export function registerDeleteRoute(deps: RouteDependencies) { + const handler: RequestHandler = async (ctx, request, response) => { + const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); + + const { watchId } = request.params; + + try { + return response.ok({ + body: await deleteWatch(callWithRequest, watchId), + }); + } catch (e) { + // Case: Error from Elasticsearch JS client + if (isEsError(e)) { + const body = e.statusCode === 404 ? `Watch with id = ${watchId} not found` : e; + return response.customError({ statusCode: e.statusCode, body }); + } + + // Case: default + return response.internalError({ body: e }); + } + }; + + deps.router.delete( + { + path: '/api/watcher/watch/{watchId}', + validate: { + params: schema.object({ + watchId: schema.string(), + }), + }, + }, + licensePreRoutingFactory(deps, handler) + ); +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_execute_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.ts similarity index 86% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_execute_route.ts rename to x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.ts index f3bce228653fe5..fef6d07317da5c 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_execute_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.ts @@ -5,19 +5,19 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { get } from 'lodash'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { isEsError } from '../../../lib/is_es_error'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; +import { RouteDependencies } from '../../../types'; // @ts-ignore -import { ExecuteDetails } from '../../../models/execute_details'; +import { ExecuteDetails } from '../../../models/execute_details/index'; // @ts-ignore -import { Watch } from '../../../models/watch'; +import { Watch } from '../../../models/watch/index'; // @ts-ignore -import { WatchHistoryItem } from '../../../models/watch_history_item'; +import { WatchHistoryItem } from '../../../models/watch_history_item/index'; function executeWatch(callWithRequest: any, executeDetails: any, watchJson: any) { const body = executeDetails; @@ -28,7 +28,7 @@ function executeWatch(callWithRequest: any, executeDetails: any, watchJson: any) }); } -export function registerExecuteRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerExecuteRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const executeDetails = ExecuteDetails.fromDownstreamJson(request.body.executeDetails); @@ -73,6 +73,6 @@ export function registerExecuteRoute(deps: RouteDependencies, legacy: ServerShim }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_history_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.ts similarity index 89% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_history_route.ts rename to x-pack/plugins/watcher/server/routes/api/watch/register_history_route.ts index e236d7dd642a39..7f0f1ac8d66a31 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_history_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.ts @@ -5,16 +5,16 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { get } from 'lodash'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { fetchAllFromScroll } from '../../../lib/fetch_all_from_scroll'; -import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../../../common/constants'; +import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../../common/constants'; import { isEsError } from '../../../lib/is_es_error'; +import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; // @ts-ignore -import { WatchHistoryItem } from '../../../models/watch_history_item'; +import { WatchHistoryItem } from '../../../models/watch_history_item/index'; function fetchHistoryItems(callWithRequest: any, watchId: any, startTime: any) { const params: any = { @@ -42,7 +42,7 @@ function fetchHistoryItems(callWithRequest: any, watchId: any, startTime: any) { ); } -export function registerHistoryRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerHistoryRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const { watchId } = request.params; @@ -92,6 +92,6 @@ export function registerHistoryRoute(deps: RouteDependencies, legacy: ServerShim }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.ts new file mode 100644 index 00000000000000..91d71cd737121f --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { RequestHandler } from 'kibana/server'; +import { get } from 'lodash'; +import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; +import { isEsError } from '../../../lib/is_es_error'; +import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; +// @ts-ignore +import { Watch } from '../../../models/watch/index'; +import { RouteDependencies } from '../../../types'; + +function fetchWatch(callWithRequest: any, watchId: string) { + return callWithRequest('watcher.getWatch', { + id: watchId, + }); +} + +export function registerLoadRoute(deps: RouteDependencies) { + const handler: RequestHandler = async (ctx, request, response) => { + const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); + + const id = request.params.id; + + try { + const hit = await fetchWatch(callWithRequest, id); + const watchJson = get(hit, 'watch'); + const watchStatusJson = get(hit, 'status'); + const json = { + id, + watchJson, + watchStatusJson, + }; + + const watch = Watch.fromUpstreamJson(json, { + throwExceptions: { + Action: false, + }, + }); + return response.ok({ + body: { watch: watch.downstreamJson }, + }); + } catch (e) { + // Case: Error from Elasticsearch JS client + if (isEsError(e)) { + const body = e.statusCode === 404 ? `Watch with id = ${id} not found` : e; + return response.customError({ statusCode: e.statusCode, body }); + } + + // Case: default + return response.internalError({ body: e }); + } + }; + deps.router.get( + { + path: '/api/watcher/watch/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + licensePreRoutingFactory(deps, handler) + ); +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_save_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.ts similarity index 84% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_save_route.ts rename to x-pack/plugins/watcher/server/routes/api/watch/register_save_route.ts index 5d22392d49ed8a..7986424e6229a7 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_save_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.ts @@ -5,17 +5,14 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { i18n } from '@kbn/i18n'; -import { WATCH_TYPES } from '../../../../../common/constants'; -import { - serializeJsonWatch, - serializeThresholdWatch, -} from '../../../../../common/lib/serialization'; +import { WATCH_TYPES } from '../../../../common/constants'; +import { serializeJsonWatch, serializeThresholdWatch } from '../../../../common/lib/serialization'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { isEsError } from '../../../lib/is_es_error'; +import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; function fetchWatch(callWithRequest: any, watchId: string) { return callWithRequest('watcher.getWatch', { @@ -30,7 +27,7 @@ function saveWatch(callWithRequest: any, id: string, body: any) { }); } -export function registerSaveRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerSaveRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const { id } = request.params; @@ -76,8 +73,9 @@ export function registerSaveRoute(deps: RouteDependencies, legacy: ServerShim) { try { // Create new watch - await saveWatch(callWithRequest, id, serializedWatch); - return response.noContent(); + return response.ok({ + body: await saveWatch(callWithRequest, id, serializedWatch), + }); } catch (e) { // Case: Error from Elasticsearch JS client if (isEsError(e)) { @@ -99,6 +97,6 @@ export function registerSaveRoute(deps: RouteDependencies, legacy: ServerShim) { body: schema.object({}, { allowUnknowns: true }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_visualize_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts similarity index 86% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_visualize_route.ts rename to x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts index d07a264b0b2b1f..f2110bcc0ebdbc 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watch/register_visualize_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts @@ -5,16 +5,16 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { isEsError } from '../../../lib/is_es_error'; +import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; // @ts-ignore -import { Watch } from '../../../models/watch'; +import { Watch } from '../../../models/watch/index'; // @ts-ignore -import { VisualizeOptions } from '../../../models/visualize_options'; +import { VisualizeOptions } from '../../../models/visualize_options/index'; function fetchVisualizeData(callWithRequest: any, index: any, body: any) { const params = { @@ -28,7 +28,7 @@ function fetchVisualizeData(callWithRequest: any, index: any, body: any) { return callWithRequest('search', params); } -export function registerVisualizeRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerVisualizeRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const watch = Watch.fromDownstreamJson(request.body.watch); @@ -65,6 +65,6 @@ export function registerVisualizeRoute(deps: RouteDependencies, legacy: ServerSh }), }, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_watch_routes.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_watch_routes.ts new file mode 100644 index 00000000000000..fd295ff81782c2 --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_watch_routes.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { registerDeleteRoute } from './register_delete_route'; +import { registerExecuteRoute } from './register_execute_route'; +import { registerLoadRoute } from './register_load_route'; +import { registerSaveRoute } from './register_save_route'; +import { registerHistoryRoute } from './register_history_route'; +import { registerActivateRoute } from './register_activate_route'; +import { registerDeactivateRoute } from './register_deactivate_route'; +import { registerVisualizeRoute } from './register_visualize_route'; +import { registerActionRoutes } from './action'; +import { RouteDependencies } from '../../../types'; + +export function registerWatchRoutes(deps: RouteDependencies) { + registerDeleteRoute(deps); + registerExecuteRoute(deps); + registerLoadRoute(deps); + registerSaveRoute(deps); + registerHistoryRoute(deps); + registerActivateRoute(deps); + registerDeactivateRoute(deps); + registerActionRoutes(deps); + registerVisualizeRoute(deps); +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/index.ts b/x-pack/plugins/watcher/server/routes/api/watches/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/index.ts rename to x-pack/plugins/watcher/server/routes/api/watches/index.ts diff --git a/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts b/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts new file mode 100644 index 00000000000000..2ac824529f9a6d --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { RequestHandler } from 'kibana/server'; +import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; +import { RouteDependencies } from '../../../types'; +import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; + +function deleteWatches(callWithRequest: any, watchIds: string[]) { + const deletePromises = watchIds.map(watchId => { + return callWithRequest('watcher.deleteWatch', { + id: watchId, + }) + .then((success: Array<{ _id: string }>) => ({ success })) + .catch((error: Array<{ _id: string }>) => ({ error })); + }); + + return Promise.all(deletePromises).then(results => { + const errors: Error[] = []; + const successes: boolean[] = []; + results.forEach(({ success, error }) => { + if (success) { + successes.push(success._id); + } else if (error) { + errors.push(error._id); + } + }); + + return { + successes, + errors, + }; + }); +} + +export function registerDeleteRoute(deps: RouteDependencies) { + const handler: RequestHandler = async (ctx, request, response) => { + const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); + + try { + const results = await deleteWatches(callWithRequest, request.body.watchIds); + return response.ok({ body: { results } }); + } catch (e) { + return response.internalError({ body: e }); + } + }; + + deps.router.post( + { + path: '/api/watcher/watches/delete', + validate: { + body: schema.object({ + watchIds: schema.arrayOf(schema.string()), + }), + }, + }, + licensePreRoutingFactory(deps, handler) + ); +} diff --git a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_list_route.ts b/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.ts similarity index 85% rename from x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_list_route.ts rename to x-pack/plugins/watcher/server/routes/api/watches/register_list_route.ts index b94c29e0f98926..fcbdf688a2ab40 100644 --- a/x-pack/legacy/plugins/watcher/server/np_ready/routes/api/watches/register_list_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.ts @@ -4,16 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandler } from 'src/core/server'; +import { RequestHandler } from 'kibana/server'; import { get } from 'lodash'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { fetchAllFromScroll } from '../../../lib/fetch_all_from_scroll'; -import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../../../common/constants'; +import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../../common/constants'; import { isEsError } from '../../../lib/is_es_error'; +import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { RouteDependencies, ServerShim } from '../../../types'; // @ts-ignore -import { Watch } from '../../../models/watch'; +import { Watch } from '../../../models/watch/index'; function fetchWatches(callWithRequest: any) { const params = { @@ -30,7 +30,7 @@ function fetchWatches(callWithRequest: any) { ); } -export function registerListRoute(deps: RouteDependencies, legacy: ServerShim) { +export function registerListRoute(deps: RouteDependencies) { const handler: RequestHandler = async (ctx, request, response) => { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); @@ -81,6 +81,6 @@ export function registerListRoute(deps: RouteDependencies, legacy: ServerShim) { path: '/api/watcher/watches', validate: false, }, - licensePreRoutingFactory(legacy, handler) + licensePreRoutingFactory(deps, handler) ); } diff --git a/x-pack/plugins/watcher/server/routes/api/watches/register_watches_routes.ts b/x-pack/plugins/watcher/server/routes/api/watches/register_watches_routes.ts new file mode 100644 index 00000000000000..b515b6264a544a --- /dev/null +++ b/x-pack/plugins/watcher/server/routes/api/watches/register_watches_routes.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { registerListRoute } from './register_list_route'; +import { registerDeleteRoute } from './register_delete_route'; +import { RouteDependencies } from '../../../types'; + +export function registerWatchesRoutes(deps: RouteDependencies) { + registerListRoute(deps); + registerDeleteRoute(deps); +} diff --git a/x-pack/plugins/watcher/server/types.ts b/x-pack/plugins/watcher/server/types.ts new file mode 100644 index 00000000000000..d9f2d3c3b1e7a6 --- /dev/null +++ b/x-pack/plugins/watcher/server/types.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IRouter, ElasticsearchServiceSetup, IClusterClient } from 'kibana/server'; +import { LicensingPluginSetup } from '../../licensing/server'; + +import { XPackMainPlugin } from '../../../legacy/plugins/xpack_main/server/xpack_main'; + +export interface Dependencies { + licensing: LicensingPluginSetup; +} + +export interface ServerShim { + route: any; + plugins: { + xpack_main: XPackMainPlugin; + watcher: any; + }; +} + +export interface RouteDependencies { + router: IRouter; + getLicenseStatus: () => LicenseStatus; + elasticsearchService: ElasticsearchServiceSetup; + elasticsearch: IClusterClient; +} + +export interface LicenseStatus { + hasRequired: boolean; + message?: string; +} diff --git a/x-pack/legacy/plugins/watcher/test/fixtures/execute_details.ts b/x-pack/plugins/watcher/test/fixtures/execute_details.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/test/fixtures/execute_details.ts rename to x-pack/plugins/watcher/test/fixtures/execute_details.ts diff --git a/x-pack/legacy/plugins/watcher/test/fixtures/index.ts b/x-pack/plugins/watcher/test/fixtures/index.ts similarity index 100% rename from x-pack/legacy/plugins/watcher/test/fixtures/index.ts rename to x-pack/plugins/watcher/test/fixtures/index.ts diff --git a/x-pack/legacy/plugins/watcher/test/fixtures/watch.ts b/x-pack/plugins/watcher/test/fixtures/watch.ts similarity index 95% rename from x-pack/legacy/plugins/watcher/test/fixtures/watch.ts rename to x-pack/plugins/watcher/test/fixtures/watch.ts index d948fddeefd588..3342ebc1497702 100644 --- a/x-pack/legacy/plugins/watcher/test/fixtures/watch.ts +++ b/x-pack/plugins/watcher/test/fixtures/watch.ts @@ -5,7 +5,7 @@ */ import { Moment } from 'moment'; -import { getRandomString } from '../../../../../test_utils'; +import { getRandomString } from '../../../../test_utils'; interface Watch { id: string; diff --git a/x-pack/legacy/plugins/watcher/test/fixtures/watch_history.ts b/x-pack/plugins/watcher/test/fixtures/watch_history.ts similarity index 93% rename from x-pack/legacy/plugins/watcher/test/fixtures/watch_history.ts rename to x-pack/plugins/watcher/test/fixtures/watch_history.ts index 70275e6e8869eb..b8f725aa84a18e 100644 --- a/x-pack/legacy/plugins/watcher/test/fixtures/watch_history.ts +++ b/x-pack/plugins/watcher/test/fixtures/watch_history.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getRandomString } from '../../../../../test_utils'; +import { getRandomString } from '../../../../test_utils'; interface WatchHistory { startTime: string; diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index f322945e236b8c..d23bd2ac4646d5 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -75,6 +75,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.alerting.enabled=true', + '--xpack.event_log.logEntries=true', ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'actions')}`, diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions/index.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions/index.ts index 02adae72db46f9..a872edfc171352 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions/index.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions/index.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import Hapi from 'hapi'; -import { ActionType } from '../../../../../../legacy/plugins/actions'; +import { PluginSetupContract as ActionsPluginSetupContract } from '../../../../../../plugins/actions/server/plugin'; +import { ActionType } from '../../../../../../plugins/actions/server'; import { initPlugin as initPagerduty } from './pagerduty_simulation'; import { initPlugin as initServiceNow } from './servicenow_simulation'; @@ -35,7 +36,7 @@ export function getAllExternalServiceSimulatorPaths(): string[] { // eslint-disable-next-line import/no-default-export export default function(kibana: any) { return new kibana.Plugin({ - require: ['actions'], + require: ['xpack_main', 'actions'], name: NAME, init: (server: Hapi.Server) => { // this action is specifically NOT enabled in ../../config.ts @@ -46,7 +47,9 @@ export default function(kibana: any) { return { status: 'ok', actionId: '' }; }, }; - server.plugins.actions!.setup.registerType(notEnabledActionType); + (server.newPlatform.setup.plugins.actions as ActionsPluginSetupContract).registerType( + notEnabledActionType + ); server.plugins.xpack_main.registerFeature({ id: 'actions', name: 'Actions', diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/index.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/index.ts index b5d201c1682bd4..6c2a22f2737fe9 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/index.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/index.ts @@ -6,12 +6,12 @@ import { schema } from '@kbn/config-schema'; import { AlertExecutorOptions, AlertType } from '../../../../../../legacy/plugins/alerting'; -import { ActionTypeExecutorOptions, ActionType } from '../../../../../../legacy/plugins/actions'; +import { ActionTypeExecutorOptions, ActionType } from '../../../../../../plugins/actions/server'; // eslint-disable-next-line import/no-default-export export default function(kibana: any) { return new kibana.Plugin({ - require: ['actions', 'alerting', 'elasticsearch'], + require: ['xpack_main', 'actions', 'alerting', 'elasticsearch'], name: 'alerts', init(server: any) { server.plugins.xpack_main.registerFeature({ @@ -62,8 +62,8 @@ export default function(kibana: any) { encrypted: schema.string(), }), }, - async executor({ config, secrets, params, services }: ActionTypeExecutorOptions) { - return await services.callCluster('index', { + async executor({ config, secrets, params, services, actionId }: ActionTypeExecutorOptions) { + await services.callCluster('index', { index: params.index, refresh: 'wait_for', body: { @@ -74,6 +74,7 @@ export default function(kibana: any) { source: 'action:test.index-record', }, }); + return { status: 'ok', actionId }; }, }; const failingActionType: ActionType = { @@ -97,7 +98,7 @@ export default function(kibana: any) { source: 'action:test.failing', }, }); - throw new Error('Failed to execute action type'); + throw new Error(`expected failure for ${params.index} ${params.reference}`); }, }; const rateLimitedActionType: ActionType = { @@ -141,7 +142,7 @@ export default function(kibana: any) { reference: schema.string(), }), }, - async executor({ params, services }: ActionTypeExecutorOptions) { + async executor({ params, services, actionId }: ActionTypeExecutorOptions) { // Call cluster let callClusterSuccess = false; let callClusterError; @@ -186,16 +187,16 @@ export default function(kibana: any) { }, }); return { + actionId, status: 'ok', - actionId: '', }; }, }; - server.plugins.actions.setup.registerType(noopActionType); - server.plugins.actions.setup.registerType(indexRecordActionType); - server.plugins.actions.setup.registerType(failingActionType); - server.plugins.actions.setup.registerType(rateLimitedActionType); - server.plugins.actions.setup.registerType(authorizationActionType); + server.newPlatform.setup.plugins.actions.registerType(noopActionType); + server.newPlatform.setup.plugins.actions.registerType(indexRecordActionType); + server.newPlatform.setup.plugins.actions.registerType(failingActionType); + server.newPlatform.setup.plugins.actions.registerType(rateLimitedActionType); + server.newPlatform.setup.plugins.actions.registerType(authorizationActionType); // Alert types const alwaysFiringAlertType: AlertType = { diff --git a/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts b/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts index b72960b162e76f..3a1d035a023c22 100644 --- a/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts +++ b/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts @@ -43,4 +43,37 @@ export class TaskManagerUtils { } }); } + + async waitForActionTaskParamsToBeCleanedUp(createdAtFilter: Date): Promise { + return await this.retry.try(async () => { + const searchResult = await this.es.search({ + index: '.kibana', + body: { + query: { + bool: { + must: [ + { + term: { + type: 'action_task_params', + }, + }, + { + range: { + updated_at: { + gte: createdAtFilter, + }, + }, + }, + ], + }, + }, + }, + }); + if (searchResult.hits.total.value) { + throw new Error( + `Expected 0 action_task_params objects but received ${searchResult.hits.total.value}` + ); + } + }); + } } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/create.ts index 32d419bb562b2d..1ce9a6ba3a0403 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/create.ts @@ -135,12 +135,7 @@ export default function createActionTests({ getService }: FtrProviderContext) { expect(response.body).to.eql({ statusCode: 400, error: 'Bad Request', - message: - 'child "name" fails because ["name" is required]. child "actionTypeId" fails because ["actionTypeId" is required]', - validation: { - source: 'payload', - keys: ['name', 'actionTypeId'], - }, + message: '[request body.name]: expected value of type [string] but got [undefined]', }); break; default: diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts index a8260d47714596..a58e14dd563ef8 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts @@ -311,11 +311,8 @@ export default function({ getService }: FtrProviderContext) { expect(response.body).to.eql({ statusCode: 400, error: 'Bad Request', - message: 'child "params" fails because ["params" is required]', - validation: { - source: 'payload', - keys: ['params'], - }, + message: + '[request body.params]: expected value of type [object] but got [undefined]', }); break; default: diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/update.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/update.ts index ed6a1bb3d14a9b..a792efede07ee0 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/update.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/update.ts @@ -170,11 +170,7 @@ export default function updateActionTests({ getService }: FtrProviderContext) { expect(response.body).to.eql({ statusCode: 400, error: 'Bad Request', - message: 'child "config" fails because ["config" must be an object]', - validation: { - source: 'payload', - keys: ['config'], - }, + message: '[request body.config]: expected value of type [object] but got [null]', }); break; default: @@ -246,8 +242,8 @@ export default function updateActionTests({ getService }: FtrProviderContext) { expect(response.body).to.eql({ statusCode: 400, error: 'Bad Request', - message: 'child "name" fails because ["name" is required]', - validation: { source: 'payload', keys: ['name'] }, + message: '[request body.name]: expected value of type [string] but got [undefined]', + // message: '[request body.config]: expected value of type [object] but got [null]', }); break; default: diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts index 08e6c90a1044ca..386ba0adf5aabb 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts @@ -147,6 +147,8 @@ export default function alertTests({ getService }: FtrProviderContext) { reference, source: 'action:test.index-record', }); + + await taskManagerUtils.waitForActionTaskParamsToBeCleanedUp(testStart); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts index fde4d0e880a81f..21f61eb713753a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/list_alert_types.ts @@ -40,6 +40,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) { (alertType: any) => alertType.id === 'test.noop' ); expect(fixtureAlertType).to.eql({ + actionGroups: ['default'], id: 'test.noop', name: 'Test: Noop', }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts index a0eac43d06c667..c2e5aa041055d8 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts @@ -88,6 +88,38 @@ export default function({ getService }: FtrProviderContext) { }); }); + it('should handle failed executions', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'failing action', + actionTypeId: 'test.failing', + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); + + const reference = `actions-failure-1:${Spaces.space1.id}`; + const response = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/action/${createdAction.id}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + reference, + index: ES_TEST_INDEX_NAME, + }, + }); + + expect(response.statusCode).to.eql(200); + expect(response.body).to.eql({ + actionId: createdAction.id, + status: 'error', + message: 'an error occurred while running the action executor', + serviceMessage: `expected failure for ${ES_TEST_INDEX_NAME} ${reference}`, + retry: false, + }); + }); + it(`shouldn't execute an action from another space`, async () => { const { body: createdAction } = await supertest .post(`${getUrlPrefix(Spaces.space1.id)}/api/action`) diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts index d9a58851afb31a..3c60d2779720a8 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts @@ -16,6 +16,7 @@ import { ObjectRemover, AlertUtils, ensureDatetimeIsWithinRange, + TaskManagerUtils, } from '../../../common/lib'; // eslint-disable-next-line import/no-default-export @@ -24,6 +25,7 @@ export function alertTests({ getService }: FtrProviderContext, space: Space) { const es = getService('legacyEs'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); + const taskManagerUtils = new TaskManagerUtils(es, retry); function getAlertingTaskById(taskId: string) { return supertestWithoutAuth @@ -73,6 +75,7 @@ export function alertTests({ getService }: FtrProviderContext, space: Space) { }); it('should schedule task, run alert and schedule actions', async () => { + const testStart = new Date(); const reference = alertUtils.generateReference(); const response = await alertUtils.createAlwaysFiringAction({ reference }); const alertId = response.body.id; @@ -121,6 +124,8 @@ export function alertTests({ getService }: FtrProviderContext, space: Space) { reference, source: 'action:test.index-record', }); + + await taskManagerUtils.waitForActionTaskParamsToBeCleanedUp(testStart); }); it('should reschedule failing alerts using the alerting interval and not the Task Manager retry logic', async () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts index 479b6621d3fcdd..efa9dbf507199e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/list_alert_types.ts @@ -20,6 +20,7 @@ export default function listAlertTypes({ getService }: FtrProviderContext) { expect(response.statusCode).to.eql(200); const fixtureAlertType = response.body.find((alertType: any) => alertType.id === 'test.noop'); expect(fixtureAlertType).to.eql({ + actionGroups: ['default'], id: 'test.noop', name: 'Test: Noop', }); diff --git a/x-pack/test/api_integration/apis/endpoint/endpoints.ts b/x-pack/test/api_integration/apis/endpoint/endpoints.ts index 32864489d37867..1c520fe92e38ee 100644 --- a/x-pack/test/api_integration/apis/endpoint/endpoints.ts +++ b/x-pack/test/api_integration/apis/endpoint/endpoints.ts @@ -12,7 +12,7 @@ export default function({ getService }: FtrProviderContext) { describe('test endpoints api', () => { describe('POST /api/endpoint/endpoints when index is empty', () => { it('endpoints api should return empty result when index is empty', async () => { - await esArchiver.unload('endpoint/endpoints'); + await esArchiver.unload('endpoint/endpoints/api_feature'); const { body } = await supertest .post('/api/endpoint/endpoints') .set('kbn-xsrf', 'xxx') @@ -21,13 +21,13 @@ export default function({ getService }: FtrProviderContext) { expect(body.total).to.eql(0); expect(body.endpoints.length).to.eql(0); expect(body.request_page_size).to.eql(10); - expect(body.request_index).to.eql(0); + expect(body.request_page_index).to.eql(0); }); }); describe('POST /api/endpoint/endpoints when index is not empty', () => { - before(() => esArchiver.load('endpoint/endpoints')); - after(() => esArchiver.unload('endpoint/endpoints')); + before(() => esArchiver.load('endpoint/endpoints/api_feature')); + after(() => esArchiver.unload('endpoint/endpoints/api_feature')); it('endpoints api should return one entry for each endpoint with default paging', async () => { const { body } = await supertest .post('/api/endpoint/endpoints') @@ -37,7 +37,7 @@ export default function({ getService }: FtrProviderContext) { expect(body.total).to.eql(3); expect(body.endpoints.length).to.eql(3); expect(body.request_page_size).to.eql(10); - expect(body.request_index).to.eql(0); + expect(body.request_page_index).to.eql(0); }); it('endpoints api should return page based on params passed.', async () => { @@ -58,7 +58,7 @@ export default function({ getService }: FtrProviderContext) { expect(body.total).to.eql(3); expect(body.endpoints.length).to.eql(1); expect(body.request_page_size).to.eql(1); - expect(body.request_index).to.eql(1); + expect(body.request_page_index).to.eql(1); }); /* test that when paging properties produces no result, the total should reflect the actual number of endpoints @@ -82,7 +82,7 @@ export default function({ getService }: FtrProviderContext) { expect(body.total).to.eql(3); expect(body.endpoints.length).to.eql(0); expect(body.request_page_size).to.eql(10); - expect(body.request_index).to.eql(30); + expect(body.request_page_index).to.eql(30); }); it('endpoints api should return 400 when pagingProperties is below boundaries.', async () => { diff --git a/x-pack/test/api_integration/apis/lens/existing_fields.ts b/x-pack/test/api_integration/apis/lens/existing_fields.ts index bceb8250edd2df..cf65e114d38965 100644 --- a/x-pack/test/api_integration/apis/lens/existing_fields.ts +++ b/x-pack/test/api_integration/apis/lens/existing_fields.ts @@ -94,6 +94,41 @@ const fieldsWithData = [ 'relatedContent.url.raw', ]; +const metricBeatData = [ + '@timestamp', + 'agent.ephemeral_id', + 'agent.hostname', + 'agent.id', + 'agent.type', + 'agent.version', + 'ecs.version', + 'event.dataset', + 'event.duration', + 'event.module', + 'host.architecture', + 'host.hostname', + 'host.id', + 'host.name', + 'host.os.build', + 'host.os.family', + 'host.os.kernel', + 'host.os.name', + 'host.os.platform', + 'host.os.version', + 'metricset.name', + 'service.type', + 'system.cpu.cores', + 'system.cpu.idle.pct', + 'system.cpu.iowait.pct', + 'system.cpu.irq.pct', + 'system.cpu.nice.pct', + 'system.cpu.softirq.pct', + 'system.cpu.steal.pct', + 'system.cpu.system.pct', + 'system.cpu.total.pct', + 'system.cpu.user.pct', +]; + // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); @@ -124,6 +159,20 @@ export default ({ getService }: FtrProviderContext) => { expect(body.existingFieldNames.sort()).to.eql(fieldsWithData.sort()); }); + it('should succeed for thousands of fields', async () => { + const { body } = await supertest + .get( + `/api/lens/existing_fields/${encodeURIComponent( + 'metricbeat-*' + )}?fromDate=${TEST_START_TIME}&toDate=${TEST_END_TIME}` + ) + .set(COMMON_HEADERS) + .expect(200); + + expect(body.indexPatternTitle).to.eql('metricbeat-*'); + expect(body.existingFieldNames.sort()).to.eql(metricBeatData.sort()); + }); + it('should throw a 404 for a non-existent index', async () => { await supertest .get( diff --git a/x-pack/test/api_integration/apis/siem/overview_host.ts b/x-pack/test/api_integration/apis/siem/overview_host.ts index f23d9047f97e95..d32eeaec884fa9 100644 --- a/x-pack/test/api_integration/apis/siem/overview_host.ts +++ b/x-pack/test/api_integration/apis/siem/overview_host.ts @@ -35,7 +35,8 @@ export default function({ getService }: FtrProviderContext) { endgameRegistry: 1, endgameSecurity: 4, filebeatSystemModule: 0, - winlogbeat: 1, + winlogbeatSecurity: 0, + winlogbeatMWSysmonOperational: 0, __typename: 'OverviewHostData', }; diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index ad4f81777e7804..2649c5d26309db 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -54,7 +54,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { expectSpaceSelector: false, } ); - await kibanaServer.uiSettings.replace({}); + await kibanaServer.uiSettings.replace({ pageNavigation: 'individual' }); await PageObjects.settings.navigateTo(); }); @@ -68,7 +68,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Management']); + expect(navLinks).to.eql(['Stack Management']); }); it(`allows settings to be changed`, async () => { @@ -124,7 +124,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows Management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Management']); + expect(navLinks).to.eql(['Stack Management']); }); it(`does not allow settings to be changed`, async () => { @@ -175,7 +175,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows Management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Discover', 'Management']); + expect(navLinks).to.eql(['Discover', 'Stack Management']); }); it(`does not allow navigation to advanced settings; redirects to Kibana home`, async () => { diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts index ee58be76928b3a..79bb10e0bded16 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_spaces.ts @@ -40,8 +40,9 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.contain('Management'); + expect(navLinks).to.contain('Stack Management'); }); it(`allows settings to be changed`, async () => { 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 e2d5efac4644cc..7c9c9f9c8c155a 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 @@ -60,7 +60,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows apm navlink', async () => { const navLinks = await appsMenu.readLinks(); - expect(navLinks.map(link => link.text)).to.eql(['APM', 'Management']); + expect(navLinks.map(link => link.text)).to.eql(['APM', 'Stack Management']); }); it('can navigate to APM app', async () => { @@ -109,7 +109,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows apm navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['APM', 'Management']); + expect(navLinks).to.eql(['APM', 'Stack Management']); }); it('can navigate to APM app', async () => { diff --git a/x-pack/test/functional/apps/apm/feature_controls/apm_spaces.ts b/x-pack/test/functional/apps/apm/feature_controls/apm_spaces.ts index 1ac1784e0e05db..474240b201face 100644 --- a/x-pack/test/functional/apps/apm/feature_controls/apm_spaces.ts +++ b/x-pack/test/functional/apps/apm/feature_controls/apm_spaces.ts @@ -8,7 +8,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'error', 'timePicker', 'security']); + const PageObjects = getPageObjects(['common', 'error', 'timePicker', 'security', 'settings']); const testSubjects = getService('testSubjects'); const appsMenu = getService('appsMenu'); @@ -30,6 +30,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('APM'); }); diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts index d0e37ec8e3f359..71c10bd8248be8 100644 --- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts +++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts @@ -66,7 +66,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows canvas navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Canvas', 'Management']); + expect(navLinks).to.eql(['Canvas', 'Stack Management']); }); it(`landing page shows "Create new workpad" button`, async () => { @@ -142,7 +142,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows canvas navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Canvas', 'Management']); + expect(navLinks).to.eql(['Canvas', 'Stack Management']); }); it(`landing page shows disabled "Create new workpad" button`, async () => { diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_spaces.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_spaces.ts index 28b572401892b5..5395f125bbd22b 100644 --- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_spaces.ts +++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_spaces.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'canvas', 'security', 'spaceSelector']); + const PageObjects = getPageObjects(['common', 'canvas', 'security', 'spaceSelector', 'settings']); const appsMenu = getService('appsMenu'); describe('spaces feature controls', function() { @@ -40,6 +40,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Canvas'); }); diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts index d25fae3c4894cd..6a6e2f23785e30 100644 --- a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts +++ b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts @@ -75,7 +75,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows dashboard navlink', async () => { const navLinks = await appsMenu.readLinks(); - expect(navLinks.map(link => link.text)).to.eql(['Dashboard', 'Management']); + expect(navLinks.map(link => link.text)).to.eql(['Dashboard', 'Stack Management']); }); it(`landing page shows "Create new Dashboard" button`, async () => { @@ -253,7 +253,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows dashboard navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Dashboard', 'Management']); + expect(navLinks).to.eql(['Dashboard', 'Stack Management']); }); it(`landing page doesn't show "Create new Dashboard" button`, async () => { diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts index ebe08a60c25636..002ae627c488de 100644 --- a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts +++ b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts @@ -13,7 +13,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'spaceSelector']); + const PageObjects = getPageObjects([ + 'common', + 'dashboard', + 'security', + 'spaceSelector', + 'settings', + ]); const appsMenu = getService('appsMenu'); const testSubjects = getService('testSubjects'); @@ -43,6 +49,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Dashboard'); }); diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js index bab798dacc453b..1189fe909ca320 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js @@ -39,6 +39,7 @@ export default function({ getService, getPageObjects }) { await esArchiver.load('dashboard_view_mode'); await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*', + pageNavigation: 'individual', }); await browser.setWindowSize(1600, 1000); @@ -199,7 +200,7 @@ export default function({ getService, getPageObjects }) { await PageObjects.security.forceLogout(); await PageObjects.security.login('mixeduser', '123456'); - if (await appsMenu.linkExists('Management')) { + if (await appsMenu.linkExists('Stack Management')) { throw new Error('Expected management nav link to not be shown'); } }); @@ -208,7 +209,7 @@ export default function({ getService, getPageObjects }) { await PageObjects.security.forceLogout(); await PageObjects.security.login('mysuperuser', '123456'); - if (!(await appsMenu.linkExists('Management'))) { + if (!(await appsMenu.linkExists('Stack Management'))) { throw new Error('Expected management nav link to be shown'); } }); 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 494fd71ea6f34a..9db9a913e9a4b5 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 @@ -63,7 +63,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows Dev Tools navlink', async () => { const navLinks = await appsMenu.readLinks(); - expect(navLinks.map(link => link.text)).to.eql(['Dev Tools', 'Management']); + expect(navLinks.map(link => link.text)).to.eql(['Dev Tools', 'Stack Management']); }); describe('console', () => { @@ -144,7 +144,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`shows 'Dev Tools' navlink`, async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Dev Tools', 'Management']); + expect(navLinks).to.eql(['Dev Tools', 'Stack Management']); }); describe('console', () => { diff --git a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts index 4184d223a96864..f917792eea027f 100644 --- a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts +++ b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_spaces.ts @@ -9,7 +9,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'spaceSelector']); + const PageObjects = getPageObjects([ + 'common', + 'dashboard', + 'security', + 'spaceSelector', + 'settings', + ]); const appsMenu = getService('appsMenu'); const testSubjects = getService('testSubjects'); const grokDebugger = getService('grokDebugger'); @@ -40,6 +46,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Dev Tools'); }); diff --git a/x-pack/test/functional/apps/dev_tools/searchprofiler_editor.ts b/x-pack/test/functional/apps/dev_tools/searchprofiler_editor.ts index f8eea76026cc2d..56d7a66930ebfb 100644 --- a/x-pack/test/functional/apps/dev_tools/searchprofiler_editor.ts +++ b/x-pack/test/functional/apps/dev_tools/searchprofiler_editor.ts @@ -51,7 +51,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await aceEditor.setValue(editorTestSubjectSelector, input); await retry.waitFor( - `parser errors to match expection: HAS ${expectation ? 'ERRORS' : 'NO ERRORS'}`, + `parser errors to match expectation: HAS ${expectation ? 'ERRORS' : 'NO ERRORS'}`, async () => { const actual = await aceEditor.hasParseErrors(editorTestSubjectSelector); return expectation === actual; diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts index 1912b16d96f36c..1796858165a2ba 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts @@ -81,7 +81,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows discover navlink', async () => { const navLinks = await appsMenu.readLinks(); - expect(navLinks.map(link => link.text)).to.eql(['Discover', 'Management']); + expect(navLinks.map(link => link.text)).to.eql(['Discover', 'Stack Management']); }); it('shows save button', async () => { @@ -168,7 +168,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows discover navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Discover', 'Management']); + expect(navLinks).to.eql(['Discover', 'Stack Management']); }); it(`doesn't show save button`, async () => { diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts index e6b6f28f8b92fc..c38dda536f2530 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts @@ -15,6 +15,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { 'timePicker', 'security', 'spaceSelector', + 'settings', ]); const testSubjects = getService('testSubjects'); const appsMenu = getService('appsMenu'); @@ -49,6 +50,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Discover'); }); diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts index a2b062e6ef84fb..37de93a0a7e910 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts @@ -64,7 +64,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows graph navlink', async () => { const navLinks = await appsMenu.readLinks(); - expect(navLinks.map(link => link.text)).to.eql(['Graph', 'Management']); + expect(navLinks.map(link => link.text)).to.eql(['Graph', 'Stack Management']); }); it('landing page shows "Create new graph" button', async () => { @@ -127,7 +127,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows graph navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Graph', 'Management']); + expect(navLinks).to.eql(['Graph', 'Stack Management']); }); it('does not show a "Create new Workspace" button', async () => { diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts index a0b0d5bef96680..d0d0232b5a8b14 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'graph', 'security', 'error']); + const PageObjects = getPageObjects(['common', 'graph', 'security', 'error', 'settings']); const testSubjects = getService('testSubjects'); const appsMenu = getService('appsMenu'); @@ -34,6 +34,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Graph'); }); diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts index 30cdc95b38e62e..ed25816e68712b 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts @@ -70,7 +70,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Management']); + expect(navLinks).to.eql(['Stack Management']); }); it(`index pattern listing shows create button`, async () => { @@ -113,7 +113,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { } ); - await kibanaServer.uiSettings.replace({}); + await kibanaServer.uiSettings.replace({ pageNavigation: 'individual' }); await PageObjects.settings.navigateTo(); }); @@ -124,7 +124,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Management']); + expect(navLinks).to.eql(['Stack Management']); }); it(`index pattern listing doesn't show create button`, async () => { @@ -176,7 +176,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows Management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Discover', 'Management']); + expect(navLinks).to.eql(['Discover', 'Stack Management']); }); it(`doesn't show Index Patterns in management side-nav`, async () => { diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts index 6a2b77de17f457..75020d6eab7e4a 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_spaces.ts @@ -40,8 +40,9 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.contain('Management'); + expect(navLinks).to.contain('Stack Management'); }); it(`index pattern listing shows create button`, async () => { 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 5062f094061c03..ac7bd66d3466f0 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 @@ -61,7 +61,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(['Metrics', 'Management']); + expect(navLinks).to.eql(['Metrics', 'Stack Management']); }); describe('infrastructure landing page without data', () => { @@ -104,12 +104,14 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`does not show link to view logs`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewLogsContextMenuItem'); + const link = await testSubjects.find('~viewLogsContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); it(`does not show link to view apm traces`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewApmTracesContextMenuItem'); + const link = await testSubjects.find('~viewApmTracesContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); }); @@ -174,7 +176,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(['Metrics', 'Management']); + expect(navLinks).to.eql(['Metrics', 'Stack Management']); }); describe('infrastructure landing page without data', () => { @@ -217,12 +219,14 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`does not show link to view logs`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewLogsContextMenuItem'); + const link = await testSubjects.find('~viewLogsContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); it(`does not show link to view apm traces`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewApmTracesContextMenuItem'); + const link = await testSubjects.find('~viewApmTracesContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); }); diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts index 7c2a11a542d66e..1d7ef9bea81e63 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts @@ -12,7 +12,13 @@ const DATE_WITH_DATA = DATES.metricsAndLogs.hosts.withData; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'infraHome', 'security', 'spaceSelector']); + const PageObjects = getPageObjects([ + 'common', + 'infraHome', + 'security', + 'spaceSelector', + 'settings', + ]); const testSubjects = getService('testSubjects'); const appsMenu = getService('appsMenu'); const retry = getService('retry'); @@ -31,7 +37,6 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { // we need to load the following in every situation as deleting // a space deletes all of the associated saved objects await esArchiver.load('empty_kibana'); - await spacesService.create({ id: 'custom_space', name: 'custom_space', @@ -48,6 +53,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Metrics'); }); @@ -185,7 +191,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`doesn't show link to view logs`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewLogsContextMenuItem'); + const link = await testSubjects.find('~viewLogsContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); it(`shows link to view apm traces`, async () => { @@ -233,7 +240,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it(`doesn't show link to view apm traces`, async () => { await retry.waitFor('context menu', () => testSubjects.exists('~nodeContextMenu')); - await testSubjects.missingOrFail('~viewApmTracesContextMenuItem'); + const link = await testSubjects.find('~viewApmTracesContextMenuItem'); + expect(await link.isEnabled()).to.be(false); }); }); }); 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 b9634c29dac1c9..5008f93feeb015 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 @@ -58,7 +58,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(['Logs', 'Management']); + expect(navLinks).to.eql(['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(['Logs', 'Management']); + expect(navLinks).to.eql(['Logs', 'Stack Management']); }); describe('logs landing page without data', () => { diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts b/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts index 6b078d2cfa71af..61a57e09f96c57 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/logs_spaces.ts @@ -9,7 +9,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'infraHome', 'security', 'spaceSelector']); + const PageObjects = getPageObjects([ + 'common', + 'infraHome', + 'security', + 'spaceSelector', + 'settings', + ]); const testSubjects = getService('testSubjects'); const appsMenu = getService('appsMenu'); @@ -36,6 +42,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Logs'); }); diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/advanced_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/advanced_job.ts index 386914b735554c..acb92b270c4a12 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/advanced_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/advanced_job.ts @@ -194,8 +194,8 @@ export default function({ getService }: FtrProviderContext) { }, modelSizeStats: { result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '10485760', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '10.0 MB', total_by_field_count: '37', total_over_field_count: '92', total_partition_field_count: '8', @@ -261,8 +261,8 @@ export default function({ getService }: FtrProviderContext) { }, modelSizeStats: { result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '104857600', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '100.0 MB', total_by_field_count: '994', total_over_field_count: '0', total_partition_field_count: '2', diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts index d41d96e40e2bee..6a12a28e8ac490 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts @@ -60,8 +60,8 @@ export default function({ getService }: FtrProviderContext) { return { job_id: expectedJobId, result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '20971520', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '20.0 MB', total_by_field_count: '59', total_over_field_count: '0', total_partition_field_count: '58', diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts index 296af3179ce3ee..6593dd10928b4b 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts @@ -74,8 +74,8 @@ export default function({ getService }: FtrProviderContext) { return { job_id: expectedJobId, result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '8388608', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '8.0 MB', total_by_field_count: '25', total_over_field_count: '92', total_partition_field_count: '3', diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts index 7d989bc6244b81..348910a2a8f84a 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts @@ -53,8 +53,8 @@ export default function({ getService }: FtrProviderContext) { }, modelSizeStats: { result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '20971520', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '20.0 MB', total_by_field_count: '3', total_over_field_count: '0', total_partition_field_count: '2', @@ -104,8 +104,8 @@ export default function({ getService }: FtrProviderContext) { }, modelSizeStats: { result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '20971520', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '20.0 MB', total_by_field_count: '7', total_over_field_count: '0', total_partition_field_count: '6', @@ -155,8 +155,8 @@ export default function({ getService }: FtrProviderContext) { }, modelSizeStats: { result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '20971520', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '20.0 MB', total_by_field_count: '7', total_over_field_count: '0', total_partition_field_count: '6', @@ -207,8 +207,8 @@ export default function({ getService }: FtrProviderContext) { }, modelSizeStats: { result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '20971520', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '20.0 MB', total_by_field_count: '3', total_over_field_count: '0', total_partition_field_count: '2', @@ -258,8 +258,8 @@ export default function({ getService }: FtrProviderContext) { }, modelSizeStats: { result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '20971520', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '20.0 MB', total_by_field_count: '3', total_over_field_count: '0', total_partition_field_count: '2', diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts index f6cd7b40bc7b1d..13cac36d99a1ba 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts @@ -59,8 +59,8 @@ export default function({ getService }: FtrProviderContext) { return { job_id: expectedJobId, result_type: 'model_size_stats', - model_bytes_exceeded: '0', - model_bytes_memory_limit: '15728640', + model_bytes_exceeded: '0.0 B', + model_bytes_memory_limit: '15.0 MB', total_by_field_count: '3', total_over_field_count: '0', total_partition_field_count: '2', diff --git a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts index 8fb6f21c778d3f..c25c1bfe4b7318 100644 --- a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts +++ b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts @@ -10,7 +10,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const security = getService('security'); const appsMenu = getService('appsMenu'); - const PageObjects = getPageObjects(['common', 'security']); + const PageObjects = getPageObjects(['common', 'security', 'settings']); describe('security', () => { before(async () => { @@ -94,6 +94,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); await PageObjects.security.login('machine_learning_user', 'machine_learning_user-password'); + await PageObjects.settings.setNavType('individual'); }); after(async () => { diff --git a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts index fc94688e98811b..c633852a2da0a7 100644 --- a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts +++ b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error']); + const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error', 'settings']); const appsMenu = getService('appsMenu'); const testSubjects = getService('testSubjects'); @@ -39,6 +39,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Machine Learning'); }); diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts index 804ad5725edfd3..ece162cbd96cc7 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts +++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts @@ -66,7 +66,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows maps navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Maps', 'Management']); + expect(navLinks).to.eql(['Maps', 'Stack Management']); }); it(`allows a map to be created`, async () => { @@ -153,7 +153,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows Maps navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Maps', 'Management']); + expect(navLinks).to.eql(['Maps', 'Stack Management']); }); it(`does not show create new button`, async () => { @@ -248,7 +248,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('does not show Maps navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Discover', 'Management']); + expect(navLinks).to.eql(['Discover', 'Stack Management']); }); it(`returns a 404`, async () => { diff --git a/x-pack/test/functional/apps/maps/import_geojson/add_layer_import_panel.js b/x-pack/test/functional/apps/maps/import_geojson/add_layer_import_panel.js index 05eee56e9d119a..5bad43779fe57b 100644 --- a/x-pack/test/functional/apps/maps/import_geojson/add_layer_import_panel.js +++ b/x-pack/test/functional/apps/maps/import_geojson/add_layer_import_panel.js @@ -28,7 +28,7 @@ export default function({ getPageObjects }) { }); afterEach(async () => { - await PageObjects.maps.cancelLayerAdd(); + await PageObjects.maps.closeOrCancelLayer(); }); it('should add GeoJSON file to map', async () => { diff --git a/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js b/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js index 9fbe16860bfaf0..218f74678001c3 100644 --- a/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js +++ b/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js @@ -45,7 +45,7 @@ export default function({ getService, getPageObjects }) { }); afterEach(async () => { - await PageObjects.maps.cancelLayerAdd(); + await PageObjects.maps.closeOrCancelLayer(); await PageObjects.maps.waitForLayerAddPanelClosed(); }); diff --git a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_security.ts b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_security.ts index d985da42ab5eda..130aefb3cae2ac 100644 --- a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_security.ts +++ b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_security.ts @@ -10,7 +10,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const security = getService('security'); const appsMenu = getService('appsMenu'); - const PageObjects = getPageObjects(['common', 'security']); + const PageObjects = getPageObjects(['common', 'security', 'settings']); describe('security', () => { before(async () => { @@ -97,6 +97,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); it('shows monitoring navlink', async () => { + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Stack Monitoring'); }); diff --git a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts index 7459b53ca4a32f..0465cbcf54541c 100644 --- a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts +++ b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error']); + const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error', 'settings']); const appsMenu = getService('appsMenu'); const find = getService('find'); @@ -37,10 +37,11 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await spacesService.delete('custom_space'); }); - it('shows Stack Monitoring navlink', async () => { + it('shows Stack Monitoring navlink fail', async () => { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Stack Monitoring'); }); diff --git a/x-pack/test/functional/apps/security/management.js b/x-pack/test/functional/apps/security/management.js index 45a35029ffba2e..8ab84126b2b30a 100644 --- a/x-pack/test/functional/apps/security/management.js +++ b/x-pack/test/functional/apps/security/management.js @@ -11,7 +11,7 @@ import { ROLES_PATH, EDIT_ROLES_PATH, CLONE_ROLES_PATH, -} from '../../../../legacy/plugins/security/public/views/management/management_urls'; +} from '../../../../plugins/security/public/management/management_urls'; export default function({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/x-pack/test/functional/apps/security/role_mappings.ts b/x-pack/test/functional/apps/security/role_mappings.ts index 5fed56ee79e3dd..a1517e1934a286 100644 --- a/x-pack/test/functional/apps/security/role_mappings.ts +++ b/x-pack/test/functional/apps/security/role_mappings.ts @@ -93,7 +93,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const url = parse(await browser.getCurrentUrl()); - expect(url.hash).to.eql('#/management/security/role_mappings?_g=()'); + expect(url.hash).to.eql('#/management/security/role_mappings'); }); describe('with role mappings', () => { diff --git a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts index 1e79c76bf83e5e..d71d197a6ea199 100644 --- a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts +++ b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts @@ -16,6 +16,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { describe('security feature controls', () => { before(async () => { await esArchiver.load('empty_kibana'); + await PageObjects.settings.setNavType('individual'); }); after(async () => { @@ -56,7 +57,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.contain('Management'); + expect(navLinks).to.contain('Stack Management'); }); it(`displays Spaces management section`, async () => { @@ -130,7 +131,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.contain('Management'); + expect(navLinks).to.contain('Stack Management'); }); it(`doesn't display Spaces management section`, async () => { diff --git a/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts b/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts index dea45f161e4510..62483a10552e34 100644 --- a/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts +++ b/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts @@ -60,7 +60,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows timelion navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Timelion', 'Management']); + expect(navLinks).to.eql(['Timelion', 'Stack Management']); }); it(`allows a timelion sheet to be created`, async () => { @@ -112,7 +112,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows timelion navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Timelion', 'Management']); + expect(navLinks).to.eql(['Timelion', 'Stack Management']); }); it(`does not allow a timelion sheet to be created`, async () => { diff --git a/x-pack/test/functional/apps/timelion/feature_controls/timelion_spaces.ts b/x-pack/test/functional/apps/timelion/feature_controls/timelion_spaces.ts index fb203a23359bdd..7e0fe731301a64 100644 --- a/x-pack/test/functional/apps/timelion/feature_controls/timelion_spaces.ts +++ b/x-pack/test/functional/apps/timelion/feature_controls/timelion_spaces.ts @@ -9,7 +9,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'timelion', 'security', 'spaceSelector']); + const PageObjects = getPageObjects([ + 'common', + 'timelion', + 'security', + 'spaceSelector', + 'settings', + ]); const appsMenu = getService('appsMenu'); describe('timelion', () => { @@ -38,6 +44,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Timelion'); }); 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 a004f8db66823c..4ff82484db91c4 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 @@ -64,7 +64,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows uptime navlink', async () => { const navLinks = await appsMenu.readLinks(); - expect(navLinks.map(link => link.text)).to.eql(['Uptime', 'Management']); + expect(navLinks.map(link => link.text)).to.eql(['Uptime', 'Stack Management']); }); it('can navigate to Uptime app', async () => { @@ -115,7 +115,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(['Uptime', 'Management']); + expect(navLinks).to.eql(['Uptime', 'Stack Management']); }); it('can navigate to Uptime app', async () => { diff --git a/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts b/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts index 77c5b323340bf8..c3dcb1b27771fb 100644 --- a/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts +++ b/x-pack/test/functional/apps/uptime/feature_controls/uptime_spaces.ts @@ -8,7 +8,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'error', 'timePicker', 'security']); + const PageObjects = getPageObjects(['common', 'error', 'timePicker', 'security', 'settings']); const testSubjects = getService('testSubjects'); const appsMenu = getService('appsMenu'); @@ -30,6 +30,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Uptime'); }); diff --git a/x-pack/test/functional/apps/uptime/overview.ts b/x-pack/test/functional/apps/uptime/overview.ts index ba701da6e517dd..2ef6a381a6a30e 100644 --- a/x-pack/test/functional/apps/uptime/overview.ts +++ b/x-pack/test/functional/apps/uptime/overview.ts @@ -50,13 +50,11 @@ export default ({ getPageObjects }: FtrProviderContext) => { ]); }); - // flakey see https://github.com/elastic/kibana/issues/54527 - it.skip('pagination is cleared when filter criteria changes', async () => { + it('pagination is cleared when filter criteria changes', async () => { await pageObjects.uptime.goToUptimePageAndSetDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); await pageObjects.uptime.changePage('next'); // there should now be pagination data in the URL - const contains = await pageObjects.uptime.pageUrlContains('pagination'); - expect(contains).to.be(true); + await pageObjects.uptime.pageUrlContains('pagination'); await pageObjects.uptime.pageHasExpectedIds([ '0010-down', '0011-up', @@ -71,8 +69,7 @@ export default ({ getPageObjects }: FtrProviderContext) => { ]); await pageObjects.uptime.setStatusFilter('up'); // ensure that pagination is removed from the URL - const doesNotContain = await pageObjects.uptime.pageUrlContains('pagination'); - expect(doesNotContain).to.be(false); + await pageObjects.uptime.pageUrlContains('pagination', false); await pageObjects.uptime.pageHasExpectedIds([ '0000-intermittent', '0001-up', diff --git a/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts b/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts index d55076cb0ab43b..767dbd71655672 100644 --- a/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts +++ b/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts @@ -75,7 +75,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows visualize navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Visualize', 'Management']); + expect(navLinks).to.eql(['Visualize', 'Stack Management']); }); it(`landing page shows "Create new Visualization" button`, async () => { @@ -189,7 +189,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('shows visualize navlink', async () => { const navLinks = (await appsMenu.readLinks()).map(link => link.text); - expect(navLinks).to.eql(['Visualize', 'Management']); + expect(navLinks).to.eql(['Visualize', 'Stack Management']); }); it(`landing page shows "Create new Visualization" button`, async () => { diff --git a/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts b/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts index 9193862d2ba9e4..066042896c122f 100644 --- a/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts +++ b/x-pack/test/functional/apps/visualize/feature_controls/visualize_spaces.ts @@ -10,7 +10,13 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); - const PageObjects = getPageObjects(['common', 'visualize', 'security', 'spaceSelector']); + const PageObjects = getPageObjects([ + 'common', + 'visualize', + 'security', + 'spaceSelector', + 'settings', + ]); const testSubjects = getService('testSubjects'); const appsMenu = getService('appsMenu'); @@ -40,6 +46,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); + await PageObjects.settings.setNavType('individual'); const navLinks = (await appsMenu.readLinks()).map(link => link.text); expect(navLinks).to.contain('Visualize'); }); diff --git a/x-pack/test/functional/apps/watcher/watcher_test.js b/x-pack/test/functional/apps/watcher/watcher_test.js index 20744d7a03817d..8f9dccf853e9e9 100644 --- a/x-pack/test/functional/apps/watcher/watcher_test.js +++ b/x-pack/test/functional/apps/watcher/watcher_test.js @@ -18,7 +18,8 @@ export default function({ getService, getPageObjects }) { const esSupertest = getService('esSupertest'); const PageObjects = getPageObjects(['security', 'common', 'header', 'settings', 'watcher']); - describe('watcher_test', function() { + // Failing: https://github.com/elastic/kibana/issues/56014 + describe.skip('watcher_test', function() { before('initialize tests', async () => { // There may be system watches if monitoring was previously enabled // These cannot be deleted via the UI, so we need to delete via the API diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 664bfdf8d2a746..913a8ea0c9dac0 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -143,14 +143,6 @@ export default async function({ readConfigFile }) { pathname: '/app/canvas', hash: '/', }, - code: { - pathname: '/app/code', - hash: '/admin', - }, - codeSearch: { - pathname: '/app/code', - hash: '/search', - }, uptime: { pathname: '/app/uptime', }, diff --git a/x-pack/test/functional/es_archives/endpoint/endpoints/api_feature/data.json b/x-pack/test/functional/es_archives/endpoint/endpoints/api_feature/data.json new file mode 100644 index 00000000000000..b481d56df4d526 --- /dev/null +++ b/x-pack/test/functional/es_archives/endpoint/endpoints/api_feature/data.json @@ -0,0 +1,364 @@ +{ + "type": "doc", + "value": { + "id": "3KVN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579881969541, + "agent": { + "id": "963b081e-60d1-482c-befd-a5815fa8290f", + "version": "6.6.1" + }, + "endpoint": { + "policy": { + "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" + } + }, + "event": { + "created": "2020-01-24T16:06:09.541Z" + }, + "host": { + "architecture": "x86", + "hostname": "cadmann-4.example.com", + "id": "1fb3e58f-6ab0-4406-9d2a-91911207a712", + "ip": [ + "10.192.213.130", + "10.70.28.129" + ], + "mac": [ + "a9-71-6a-cc-93-85", + "f7-31-84-d3-21-68", + "2-95-12-39-ca-71" + ], + "os": { + "full": "Windows 10", + "name": "windows 10.0", + "version": "10.0" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "3aVN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579881969541, + "agent": { + "id": "b3412d6f-b022-4448-8fee-21cc936ea86b", + "version": "6.0.0" + }, + "endpoint": { + "policy": { + "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" + } + }, + "event": { + "created": "2020-01-24T16:06:09.541Z" + }, + "host": { + "architecture": "x86_64", + "hostname": "thurlow-9.example.com", + "id": "2f735e3d-be14-483b-9822-bad06e9045ca", + "ip": [ + "10.46.229.234" + ], + "mac": [ + "30-8c-45-55-69-b8", + "e5-36-7e-8f-a3-84", + "39-a1-37-20-18-74" + ], + "os": { + "full": "Windows Server 2016", + "name": "windows 10.0", + "version": "10.0" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "3qVN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579881969541, + "agent": { + "id": "3838df35-a095-4af4-8fce-0b6d78793f2e", + "version": "6.8.0" + }, + "endpoint": { + "policy": { + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "event": { + "created": "2020-01-24T16:06:09.541Z" + }, + "host": { + "hostname": "rezzani-7.example.com", + "id": "fc0ff548-feba-41b6-8367-65e8790d0eaf", + "ip": [ + "10.101.149.26", + "10.12.85.216" + ], + "mac": [ + "e2-6d-f9-0-46-2e" + ], + "os": { + "full": "Windows 10", + "name": "windows 10.0", + "version": "10.0" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "36VN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579878369541, + "agent": { + "id": "963b081e-60d1-482c-befd-a5815fa8290f", + "version": "6.6.1" + }, + "endpoint": { + "policy": { + "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" + } + }, + "event": { + "created": "2020-01-24T15:06:09.541Z" + }, + "host": { + "architecture": "x86", + "hostname": "cadmann-4.example.com", + "id": "1fb3e58f-6ab0-4406-9d2a-91911207a712", + "ip": [ + "10.192.213.130", + "10.70.28.129" + ], + "mac": [ + "a9-71-6a-cc-93-85", + "f7-31-84-d3-21-68", + "2-95-12-39-ca-71" + ], + "os": { + "full": "Windows Server 2016", + "name": "windows 10.0", + "version": "10.0" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "4KVN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579878369541, + "agent": { + "id": "b3412d6f-b022-4448-8fee-21cc936ea86b", + "version": "6.0.0" + }, + "endpoint": { + "policy": { + "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" + } + }, + "event": { + "created": "2020-01-24T15:06:09.541Z" + }, + "host": { + "hostname": "thurlow-9.example.com", + "id": "2f735e3d-be14-483b-9822-bad06e9045ca", + "ip": [ + "10.46.229.234" + ], + "mac": [ + "30-8c-45-55-69-b8", + "e5-36-7e-8f-a3-84", + "39-a1-37-20-18-74" + ], + "os": { + "full": "Windows Server 2012", + "name": "windows 6.2", + "version": "6.2" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "4aVN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579878369541, + "agent": { + "id": "3838df35-a095-4af4-8fce-0b6d78793f2e", + "version": "6.8.0" + }, + "endpoint": { + "policy": { + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "event": { + "created": "2020-01-24T15:06:09.541Z" + }, + "host": { + "architecture": "x86", + "hostname": "rezzani-7.example.com", + "id": "fc0ff548-feba-41b6-8367-65e8790d0eaf", + "ip": [ + "10.101.149.26", + "10.12.85.216" + ], + "mac": [ + "e2-6d-f9-0-46-2e" + ], + "os": { + "full": "Windows Server 2012", + "name": "windows 6.2", + "version": "6.2" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "4qVN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579874769541, + "agent": { + "id": "963b081e-60d1-482c-befd-a5815fa8290f", + "version": "6.6.1" + }, + "endpoint": { + "policy": { + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "event": { + "created": "2020-01-24T14:06:09.541Z" + }, + "host": { + "hostname": "cadmann-4.example.com", + "id": "1fb3e58f-6ab0-4406-9d2a-91911207a712", + "ip": [ + "10.192.213.130", + "10.70.28.129" + ], + "mac": [ + "a9-71-6a-cc-93-85", + "f7-31-84-d3-21-68", + "2-95-12-39-ca-71" + ], + "os": { + "full": "Windows Server 2012R2", + "name": "windows 6.3", + "version": "6.3" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "46VN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579874769541, + "agent": { + "id": "b3412d6f-b022-4448-8fee-21cc936ea86b", + "version": "6.0.0" + }, + "endpoint": { + "policy": { + "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A" + } + }, + "event": { + "created": "2020-01-24T14:06:09.541Z" + }, + "host": { + "hostname": "thurlow-9.example.com", + "id": "2f735e3d-be14-483b-9822-bad06e9045ca", + "ip": [ + "10.46.229.234" + ], + "mac": [ + "30-8c-45-55-69-b8", + "e5-36-7e-8f-a3-84", + "39-a1-37-20-18-74" + ], + "os": { + "full": "Windows Server 2012R2", + "name": "windows 6.3", + "version": "6.3" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "5KVN2G8BYQH1gtPUuYk7", + "index": "endpoint-agent", + "source": { + "@timestamp": 1579874769541, + "agent": { + "id": "3838df35-a095-4af4-8fce-0b6d78793f2e", + "version": "6.8.0" + }, + "endpoint": { + "policy": { + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "event": { + "created": "2020-01-24T14:06:09.541Z" + }, + "host": { + "architecture": "x86", + "hostname": "rezzani-7.example.com", + "id": "fc0ff548-feba-41b6-8367-65e8790d0eaf", + "ip": [ + "10.101.149.26", + "10.12.85.216" + ], + "mac": [ + "e2-6d-f9-0-46-2e" + ], + "os": { + "full": "Windows Server 2012", + "name": "windows 6.2", + "version": "6.2" + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/functional/es_archives/endpoint/endpoints/api_feature/mappings.json b/x-pack/test/functional/es_archives/endpoint/endpoints/api_feature/mappings.json new file mode 100644 index 00000000000000..11766c12b8fff1 --- /dev/null +++ b/x-pack/test/functional/es_archives/endpoint/endpoints/api_feature/mappings.json @@ -0,0 +1,147 @@ +{ + "type": "index", + "value": { + "aliases": { + }, + "index": "endpoint-agent", + "mappings": { + "properties": { + "@timestamp": { + "type": "long" + }, + "agent": { + "properties": { + "id": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "version": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "endpoint": { + "properties": { + "policy": { + "properties": { + "id": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + } + } + }, + "event": { + "properties": { + "created": { + "type": "date" + } + } + }, + "host": { + "properties": { + "architecture": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "hostname": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "id": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "ip": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "mac": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "os": { + "properties": { + "full": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "name": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "version": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + } + } + } + } + }, + "settings": { + "index": { + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/functional/es_archives/endpoint/endpoints/data.json.gz b/x-pack/test/functional/es_archives/endpoint/endpoints/data.json.gz deleted file mode 100644 index fda46096e1ab24..00000000000000 Binary files a/x-pack/test/functional/es_archives/endpoint/endpoints/data.json.gz and /dev/null differ diff --git a/x-pack/test/functional/es_archives/endpoint/endpoints/mappings.json b/x-pack/test/functional/es_archives/endpoint/endpoints/mappings.json deleted file mode 100644 index 9544d05d706001..00000000000000 --- a/x-pack/test/functional/es_archives/endpoint/endpoints/mappings.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "type": "index", - "value": { - "aliases": { - }, - "index": "endpoint-agent", - "mappings": { - "properties": { - "created_at": { - "type": "date" - }, - "endpoint": { - "properties": { - "active_directory_distinguished_name": { - "type": "text" - }, - "active_directory_hostname": { - "type": "text" - }, - "domain": { - "type": "text" - }, - "is_base_image": { - "type": "boolean" - }, - "isolation": { - "properties": { - "status": { - "type": "boolean" - } - } - }, - "policy": { - "properties": { - "id": { - "ignore_above": 256, - "type": "keyword" - }, - "name": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "sensor": { - "properties": { - "persistence": { - "type": "boolean" - }, - "status": { - "type": "object" - } - } - }, - "upgrade": { - "type": "object" - } - } - }, - "host": { - "properties": { - "hostname": { - "type": "text" - }, - "ip": { - "ignore_above": 256, - "type": "keyword" - }, - "mac_address": { - "type": "text" - }, - "name": { - "type": "text" - }, - "os": { - "properties": { - "full": { - "type": "text" - }, - "name": { - "type": "text" - } - } - } - } - }, - "machine_id": { - "type": "keyword" - } - } - }, - "settings": { - "index": { - "number_of_replicas": "0", - "number_of_shards": "1" - } - } - } -} \ No newline at end of file diff --git a/x-pack/test/functional/es_archives/visualize/default/data.json b/x-pack/test/functional/es_archives/visualize/default/data.json index aa3428b62a6367..b9a6e2346b482e 100644 --- a/x-pack/test/functional/es_archives/visualize/default/data.json +++ b/x-pack/test/functional/es_archives/visualize/default/data.json @@ -19,6 +19,129 @@ } } +{ + "type": "doc", + "value": { + "index": "metricbeat-7", + "id": "asdf", + "source": { + "@timestamp" : "2015-09-20T21:43:43.104Z", + "event" : { + "dataset" : "system.cpu", + "module" : "system", + "duration" : 34818 + }, + "metricset" : { + "name" : "cpu" + }, + "service" : { + "type" : "system" + }, + "system" : { + "cpu" : { + "system" : { + "pct" : 0.16 + }, + "idle" : { + "pct" : 10.5088 + }, + "irq" : { + "pct" : 0 + }, + "cores" : 12, + "total" : { + "pct" : 1.4912 + }, + "iowait" : { + "pct" : 0 + }, + "softirq" : { + "pct" : 0 + }, + "user" : { + "pct" : 1.3312 + }, + "nice" : { + "pct" : 0 + }, + "steal" : { + "pct" : 0 + } + } + }, + "ecs" : { + "version" : "1.0.1" + }, + "host" : { + "name" : "my-host-name.local", + "os" : { + "name" : "Mac OS X", + "kernel" : "", + "build" : "", + "platform" : "darwin", + "version" : "", + "family" : "darwin" + }, + "id" : "", + "hostname" : "my-host-name.local", + "architecture" : "x86_64" + }, + "agent" : { + "id" : "aaaaa", + "version" : "7.6.0", + "type" : "metricbeat", + "ephemeral_id" : "bbbbb", + "hostname" : "my-host-name.local" + } + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "index-pattern:metricbeat-*", + "type": "_doc", + "source" : { + "index-pattern" : { + "fieldFormatMap" : "{\"aerospike.namespace.device.available.pct\":{\"id\":\"percent\",\"params\":{}},\"aerospike.namespace.device.free.pct\":{\"id\":\"percent\",\"params\":{}},\"aerospike.namespace.device.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.device.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.memory.free.pct\":{\"id\":\"percent\",\"params\":{}},\"aerospike.namespace.memory.used.data.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.memory.used.index.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.memory.used.sindex.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.memory.used.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.ec2.diskio.read.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.ec2.diskio.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.ec2.network.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.ec2.network.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.cpu.total.pct\":{\"id\":\"percent\",\"params\":{}},\"aws.rds.disk_usage.bin_log.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.free_local_storage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.free_storage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.freeable_memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.latency.commit\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.ddl\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.dml\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.insert\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.read\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.select\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.update\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.write\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.replica_lag.sec\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.swap_usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.volume_used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_daily_storage.bucket.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_request.downloaded.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_request.latency.first_byte.ms\":{\"id\":\"duration\",\"params\":{}},\"aws.s3_request.latency.total_request.ms\":{\"id\":\"duration\",\"params\":{}},\"aws.s3_request.requests.select_returned.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_request.requests.select_scanned.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_request.uploaded.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.sqs.oldest_message_age.sec\":{\"id\":\"duration\",\"params\":{}},\"aws.sqs.sent_message_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_disk.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_disk.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_disk.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.degraded.ratio\":{\"id\":\"percent\",\"params\":{}},\"ceph.cluster_status.misplace.ratio\":{\"id\":\"percent\",\"params\":{}},\"ceph.cluster_status.pg.avail_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.pg.data_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.pg.total_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.pg.used_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.traffic.read_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.traffic.write_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.monitor_health.store_stats.log.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.monitor_health.store_stats.misc.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.monitor_health.store_stats.sst.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.monitor_health.store_stats.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.osd_df.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.osd_df.total.byte\":{\"id\":\"bytes\",\"params\":{}},\"ceph.osd_df.used.byte\":{\"id\":\"bytes\",\"params\":{}},\"ceph.osd_df.used.pct\":{\"id\":\"percent\",\"params\":{}},\"ceph.pool_disk.stats.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.pool_disk.stats.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"client.bytes\":{\"id\":\"bytes\",\"params\":{}},\"client.nat.port\":{\"id\":\"string\",\"params\":{}},\"client.port\":{\"id\":\"string\",\"params\":{}},\"coredns.stats.dns.request.duration.ns.sum\":{\"id\":\"duration\",\"params\":{}},\"couchbase.bucket.data.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.bucket.disk.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.bucket.memory.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.bucket.quota.ram.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.bucket.quota.use.pct\":{\"id\":\"percent\",\"params\":{}},\"couchbase.cluster.hdd.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.hdd.quota.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.hdd.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.hdd.used.by_data.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.hdd.used.value.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.quota.total.per_node.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.quota.total.value.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.quota.used.per_node.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.quota.used.value.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.used.by_data.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.used.value.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.node.couch.docs.data_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.node.couch.docs.disk_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.node.mcd_memory.allocated.bytes\":{\"id\":\"bytes\",\"params\":{}},\"destination.bytes\":{\"id\":\"bytes\",\"params\":{}},\"destination.nat.port\":{\"id\":\"string\",\"params\":{}},\"destination.port\":{\"id\":\"string\",\"params\":{}},\"docker.cpu.core.*.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.cpu.kernel.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.cpu.system.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.cpu.total.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.cpu.user.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.diskio.read.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.diskio.summary.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.diskio.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.commit.peak\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.commit.total\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.limit\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.private_working_set.total\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.rss.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.memory.rss.total\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.usage.max\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.usage.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.memory.usage.total\":{\"id\":\"bytes\",\"params\":{}},\"docker.network.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.network.inbound.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.network.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.network.outbound.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.summary.primaries.segments.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.summary.primaries.store.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.summary.total.segments.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.summary.total.store.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.total.segments.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.total.store.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.jvm.memory.heap.init.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.jvm.memory.heap.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.jvm.memory.nonheap.init.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.jvm.memory.nonheap.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.fs.summary.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.fs.summary.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.fs.summary.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.indices.segments.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.old.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.old.peak.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.old.peak_max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.old.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.survivor.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.survivor.peak.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.survivor.peak_max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.survivor.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.young.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.young.peak.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.young.peak_max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.young.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"etcd.disk.mvcc_db_total_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"etcd.memory.go_memstats_alloc.bytes\":{\"id\":\"bytes\",\"params\":{}},\"etcd.network.client_grpc_received.bytes\":{\"id\":\"bytes\",\"params\":{}},\"etcd.network.client_grpc_sent.bytes\":{\"id\":\"bytes\",\"params\":{}},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\",\"params\":{}},\"event.severity\":{\"id\":\"string\",\"params\":{}},\"golang.heap.allocations.active\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.allocations.allocated\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.allocations.idle\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.allocations.total\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.gc.next_gc_limit\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.system.obtained\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.system.released\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.system.stack\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.system.total\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.info.idle.pct\":{\"id\":\"percent\",\"params\":{}},\"haproxy.info.memory.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.info.ssl.frontend.session_reuse.pct\":{\"id\":\"percent\",\"params\":{}},\"haproxy.stat.compressor.bypassed.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.compressor.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.compressor.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.compressor.response.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.throttle.pct\":{\"id\":\"percent\",\"params\":{}},\"http.request.body.bytes\":{\"id\":\"bytes\",\"params\":{}},\"http.request.bytes\":{\"id\":\"bytes\",\"params\":{}},\"http.response.body.bytes\":{\"id\":\"bytes\",\"params\":{}},\"http.response.bytes\":{\"id\":\"bytes\",\"params\":{}},\"http.response.status_code\":{\"id\":\"string\",\"params\":{}},\"kibana.stats.process.memory.heap.size_limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kibana.stats.process.memory.heap.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kibana.stats.process.memory.heap.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.apiserver.http.request.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.apiserver.http.response.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.apiserver.process.memory.resident.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.apiserver.process.memory.virtual.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.cpu.usage.limit.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.container.cpu.usage.node.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.container.logs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.logs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.logs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.request.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.usage.limit.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.container.memory.usage.node.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.container.memory.workingset.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.rootfs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.rootfs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.rootfs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.controllermanager.http.request.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.controllermanager.http.response.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.controllermanager.process.memory.resident.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.controllermanager.process.memory.virtual.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.fs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.fs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.fs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.allocatable.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.workingset.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.network.rx.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.network.tx.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.runtime.imagefs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.runtime.imagefs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.runtime.imagefs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.cpu.usage.limit.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.pod.cpu.usage.node.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.pod.memory.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.memory.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.memory.usage.limit.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.pod.memory.usage.node.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.pod.memory.working_set.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.network.rx.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.network.tx.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.proxy.http.request.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.proxy.http.response.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.proxy.process.memory.resident.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.proxy.process.memory.virtual.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.scheduler.http.request.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.scheduler.http.response.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.scheduler.process.memory.resident.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.scheduler.process.memory.virtual.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.system.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.system.memory.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.system.memory.workingset.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.volume.fs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.volume.fs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.volume.fs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.avg_obj_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.data_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.extent_free_list.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.file_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.index_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.storage_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.replstatus.headroom.max\":{\"id\":\"duration\",\"params\":{}},\"mongodb.replstatus.headroom.min\":{\"id\":\"duration\",\"params\":{}},\"mongodb.replstatus.lag.max\":{\"id\":\"duration\",\"params\":{}},\"mongodb.replstatus.lag.min\":{\"id\":\"duration\",\"params\":{}},\"mongodb.replstatus.oplog.size.allocated\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.replstatus.oplog.size.used\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.extra_info.heap_usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.network.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.network.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.cache.dirty.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.cache.maximum.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.cache.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.log.max_file_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.log.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.log.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mysql.status.bytes.received\":{\"id\":\"bytes\",\"params\":{}},\"mysql.status.bytes.sent\":{\"id\":\"bytes\",\"params\":{}},\"nats.stats.cpu\":{\"id\":\"percent\",\"params\":{}},\"nats.stats.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"nats.stats.mem.bytes\":{\"id\":\"bytes\",\"params\":{}},\"nats.stats.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"nats.stats.uptime\":{\"id\":\"duration\",\"params\":{}},\"nats.subscriptions.cache.hit_rate\":{\"id\":\"percent\",\"params\":{}},\"network.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.data_file.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.data_file.size.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.data_file.size.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.space.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.space.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.space.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"process.pgid\":{\"id\":\"string\",\"params\":{}},\"process.pid\":{\"id\":\"string\",\"params\":{}},\"process.ppid\":{\"id\":\"string\",\"params\":{}},\"process.thread.id\":{\"id\":\"string\",\"params\":{}},\"rabbitmq.connection.frame_max\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.disk.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.disk.free.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.gc.reclaimed.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.io.read.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.io.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.mem.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.queue.consumers.utilisation.pct\":{\"id\":\"percent\",\"params\":{}},\"rabbitmq.queue.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.active\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.allocated\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.fragmentation.bytes\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.resident\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.fragmentation.bytes\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.max.value\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.dataset\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.lua\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.peak\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.rss\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.value\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.buffer.size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.copy_on_write.last_size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.rewrite.buffer.size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.rewrite.current_time.sec\":{\"id\":\"duration\",\"params\":{}},\"redis.info.persistence.aof.rewrite.last_time.sec\":{\"id\":\"duration\",\"params\":{}},\"redis.info.persistence.aof.size.base\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.size.current\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.rdb.bgsave.current_time.sec\":{\"id\":\"duration\",\"params\":{}},\"redis.info.persistence.rdb.bgsave.last_time.sec\":{\"id\":\"duration\",\"params\":{}},\"redis.info.persistence.rdb.copy_on_write.last_size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.replication.backlog.size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.replication.master.last_io_seconds_ago\":{\"id\":\"duration\",\"params\":{}},\"redis.info.replication.master.sync.last_io_seconds_ago\":{\"id\":\"duration\",\"params\":{}},\"redis.info.replication.master.sync.left_bytes\":{\"id\":\"bytes\",\"params\":{}},\"server.bytes\":{\"id\":\"bytes\",\"params\":{}},\"server.nat.port\":{\"id\":\"string\",\"params\":{}},\"server.port\":{\"id\":\"string\",\"params\":{}},\"source.bytes\":{\"id\":\"bytes\",\"params\":{}},\"source.nat.port\":{\"id\":\"string\",\"params\":{}},\"source.port\":{\"id\":\"string\",\"params\":{}},\"system.core.idle.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.iowait.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.irq.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.nice.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.softirq.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.steal.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.system.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.user.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.idle.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.idle.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.iowait.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.iowait.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.irq.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.irq.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.nice.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.nice.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.softirq.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.softirq.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.steal.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.steal.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.system.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.system.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.total.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.total.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.user.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.user.pct\":{\"id\":\"percent\",\"params\":{}},\"system.diskio.iostat.read.per_sec.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.diskio.iostat.write.per_sec.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.diskio.read.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.diskio.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.entropy.pct\":{\"id\":\"percent\",\"params\":{}},\"system.filesystem.available\":{\"id\":\"bytes\",\"params\":{}},\"system.filesystem.free\":{\"id\":\"bytes\",\"params\":{}},\"system.filesystem.total\":{\"id\":\"bytes\",\"params\":{}},\"system.filesystem.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.filesystem.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.fsstat.total_size.free\":{\"id\":\"bytes\",\"params\":{}},\"system.fsstat.total_size.total\":{\"id\":\"bytes\",\"params\":{}},\"system.fsstat.total_size.used\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.actual.free\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.actual.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.actual.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.memory.free\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.hugepages.default_size\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.hugepages.free\":{\"id\":\"number\",\"params\":{}},\"system.memory.hugepages.reserved\":{\"id\":\"number\",\"params\":{}},\"system.memory.hugepages.surplus\":{\"id\":\"number\",\"params\":{}},\"system.memory.hugepages.total\":{\"id\":\"number\",\"params\":{}},\"system.memory.hugepages.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.hugepages.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.memory.swap.free\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.swap.total\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.swap.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.swap.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.memory.total\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.network.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.network.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.blkio.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem.usage.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem_tcp.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem_tcp.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem_tcp.usage.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.mem.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.mem.usage.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.memsw.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.memsw.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.memsw.usage.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.active_anon.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.active_file.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.cache.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.hierarchical_memory_limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.hierarchical_memsw_limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.inactive_anon.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.inactive_file.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.mapped_file.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.rss_huge.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.swap.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.unevictable.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.process.cpu.total.pct\":{\"id\":\"percent\",\"params\":{}},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.memory.rss.pct\":{\"id\":\"percent\",\"params\":{}},\"system.process.memory.share\":{\"id\":\"bytes\",\"params\":{}},\"system.process.memory.size\":{\"id\":\"bytes\",\"params\":{}},\"system.socket.summary.tcp.memory\":{\"id\":\"bytes\",\"params\":{}},\"system.socket.summary.udp.memory\":{\"id\":\"bytes\",\"params\":{}},\"system.uptime.duration.ms\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"milliseconds\"}},\"url.port\":{\"id\":\"string\",\"params\":{}},\"vsphere.datastore.capacity.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.datastore.capacity.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.datastore.capacity.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.datastore.capacity.used.pct\":{\"id\":\"percent\",\"params\":{}},\"vsphere.host.memory.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.host.memory.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.host.memory.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.virtualmachine.memory.free.guest.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.virtualmachine.memory.total.guest.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.virtualmachine.memory.used.guest.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.virtualmachine.memory.used.host.bytes\":{\"id\":\"bytes\",\"params\":{}},\"windows.service.uptime.ms\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"milliseconds\"}}}", + "fields" : "[{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"aerospike.namespace.client.delete.error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.delete.not_found\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.delete.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.delete.timeout\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.read.error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.read.not_found\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.read.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.read.timeout\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.write.error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.write.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.write.timeout\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.device.available.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.device.free.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.device.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.device.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.hwm_breached\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.free.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.used.data.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.used.index.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.used.sindex.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.used.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.node.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.objects.master\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.objects.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.stop_writes\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.ephemeral_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.bytes_per_request\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.connections.async.closing\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.connections.async.keep_alive\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.connections.async.writing\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.connections.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.children_system\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.children_user\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.load\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.system\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.user\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.load.1\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.load.15\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.load.5\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.requests_per_sec\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.closing_connection\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.dns_lookup\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.gracefully_finishing\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.idle_cleanup\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.keepalive\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.logging\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.open_slot\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.reading_request\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.sending_reply\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.starting_up\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.waiting_for_connection\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.total_accesses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.total_kbytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.uptime.server_uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.uptime.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.workers.busy\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.workers.idle\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.cloudwatch.namespace\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.credit_balance\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.credit_usage\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.surplus_credit_balance\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.surplus_credits_charged\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.read.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.read.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.read.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.write.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.write.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.write.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.core.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.image.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.monitoring.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.private.dns_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.private.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.public.dns_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.public.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.state.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.state.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.threads_per_core\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.in.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.in.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.in.packets_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.out.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.out.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.out.packets_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.status.check_failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.status.check_failed_instance\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.status.check_failed_system\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.cpu.credit_balance\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.cpu.credit_usage\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.database_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.db_instance.arn\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.db_instance.class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.db_instance.identifier\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.db_instance.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.deadlocks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.disk_queue_depth\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.disk_usage.bin_log.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.disk_usage.replication_slot.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.disk_usage.transaction_logs.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.failed_sql_server_agent_jobs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.free_local_storage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.free_storage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.freeable_memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.commit\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.ddl\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.dml\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.insert\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.read\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.select\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.update\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.write\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.login_failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.maximum_used_transaction_ids\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.oldest_replication_slot_lag.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.queries\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.read_io.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.replica_lag.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.swap_usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.commit\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.ddl\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.delete\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.dml\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.insert\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.network\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.network_receive\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.network_transmit\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.read\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.select\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.update\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.write\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.transaction_logs_generation\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.transactions.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.transactions.blocked\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.volume_used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.write_io.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_daily_storage.bucket.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_daily_storage.bucket.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_daily_storage.number_of_objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.bucket.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.downloaded.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.errors.4xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.errors.5xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.latency.first_byte.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.latency.total_request.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.get\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.head\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.list\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.post\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.put\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.select\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.select_returned.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.select_scanned.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.uploaded.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.empty_receives\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.delayed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.not_visible\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.visible\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.oldest_message_age.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.queue.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.sent_message_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.state.management.enabled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.state.module.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.state.output.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.state.queue.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.acked\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.batches\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.duplicates\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.toomany\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.read.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.write.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.runtime.goroutines\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.uptime.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_disk.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_disk.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_disk.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_health.overall_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_health.timechecks.epoch\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_health.timechecks.round.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_health.timechecks.round.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.degraded.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.degraded.ratio\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.degraded.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.misplace.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.misplace.ratio\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.misplace.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.epoch\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.full\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.nearfull\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.num_in_osds\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.num_osds\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.num_remapped_pgs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.num_up_osds\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg.avail_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg.data_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg.total_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg.used_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg_state.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg_state.state_name\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg_state.version\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.traffic.read_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.traffic.read_op_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.traffic.write_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.traffic.write_op_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.version\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.available.kb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.available.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.health\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.last_updated\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.last_updated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.log.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.misc.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.sst.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.total.kb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.used.kb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.device_class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.pg_num\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.total.byte\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.used.byte\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.children\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.crush_weight\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.depth\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.device_class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.exists\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.father\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.primary_affinity\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.reweight\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.type_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.stats.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.stats.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.stats.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.stats.used.kb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.account.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.availability_zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.image.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.instance.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.instance.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.machine.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.project.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.provider\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.region\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.autopilot.healthy\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.alloc.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.garbage_collector.pause.current.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.garbage_collector.pause.total.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.garbage_collector.runs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.goroutines\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.heap_objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.malloc_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.sys.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.image.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.image.tag\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.runtime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.cache.hits.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.cache.misses.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.do.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.duration.ns.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.duration.ns.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.type.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.response.rcode.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.panic.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.proto\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.rcode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.server\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.data.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.disk.fetches\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.disk.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.item_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.memory.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.quota.ram.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.quota.use.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.quota.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.used.by_data.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.used.value.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.max_bucket_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.quota.index_memory.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.quota.memory.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.quota.total.per_node.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.quota.total.value.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.quota.used.per_node.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.quota.used.value.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.used.by_data.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.used.value.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.cmd_get\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.docs.data_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.docs.disk_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.spatial.data_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.spatial.disk_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.views.data_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.views.disk_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.cpu_utilization_rate.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.current_items.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.current_items.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.ep_bg_fetched\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.get_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.mcd_memory.allocated.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.mcd_memory.reserved.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.memory.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.memory.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.memory.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.swap.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.swap.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.uptime.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.vb_replica_curr_items\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.auth_cache_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.auth_cache_misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.database_reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.database_writes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.open_databases\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.open_os_files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.request_time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.bulk_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.clients_requesting_changes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.temporary_view_reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.view_reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.COPY\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.DELETE\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.GET\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.HEAD\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.POST\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.PUT\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.200\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.201\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.202\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.301\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.304\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.400\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.401\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.403\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.404\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.405\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.409\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.412\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.500\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.data\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.ttl\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.header_flags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.op_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.registered_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.resolved_ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.response_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.command\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.ip_addresses\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.size.root_fs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.size.rw\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.tags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.kernel.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.kernel.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.system.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.system.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.user.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.user.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.read.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.read.rate\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.reads\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.summary.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.summary.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.summary.rate\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.total\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.write.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.write.rate\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.writes\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.action\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.actor.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.from\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.event.end_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.event.exit_code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.event.output\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.event.start_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.failingstreak\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.id.current\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.id.parent\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.size.regular\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.size.virtual\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.tags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.containers.paused\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.containers.running\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.containers.stopped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.containers.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.images\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.commit.peak\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.commit.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.fail.count\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.private_working_set.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.rss.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.rss.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.usage.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.usage.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.usage.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.in.dropped\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.in.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.in.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.inbound.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.inbound.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.inbound.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.inbound.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.interface\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.out.dropped\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.out.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.out.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.outbound.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.outbound.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.outbound.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.outbound.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ecs.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.global_checkpoint\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.index\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.operations_written\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.shard.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.time_since_last_read.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.leader.index\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.leader.max_seq_no\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.pending_task.insert_order\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.pending_task.priority\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.pending_task.source\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.pending_task.time_in_queue.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.state.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.indices.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.indices.fielddata.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.indices.shards.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.indices.shards.primaries\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.nodes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.nodes.data\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.nodes.master\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.primary\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.source.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.source.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.source.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.stage\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.target.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.target.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.target.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.docs.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.segments.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.segments.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.store.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.docs.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.segments.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.segments.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.store.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.docs.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.segments.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.segments.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.store.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ml.job.data_counts.invalid_date_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ml.job.data_counts.processed_record_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ml.job.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ml.job.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.memory.heap.init.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.memory.heap.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.memory.nonheap.init.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.memory.nonheap.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.process.mlockall\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.fs.summary.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.fs.summary.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.fs.summary.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.docs.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.segments.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.segments.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.store.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.gc.collectors.old.collection.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.gc.collectors.old.collection.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.gc.collectors.young.collection.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.gc.collectors.young.collection.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.old.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.old.peak.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.old.peak_max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.old.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.survivor.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.survivor.peak.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.survivor.peak_max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.survivor.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.young.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.young.peak.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.young.peak_max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.young.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.shard.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.shard.primary\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.shard.relocating_node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.shard.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.active_clusters\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.cluster_added\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.cluster_modified\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.cluster_removed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.warming_clusters\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.flushed_by_timer\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.reopen_failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.write_buffered\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.write_completed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.write_total_buffered\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.header_overflow\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.headers_cb_no_stream\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.rx_messaging_error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.rx_reset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.too_many_header_frames\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.trailers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.tx_reset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_added\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_create_failure\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_create_success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_modified\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_removed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.total_listeners_active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.total_listeners_draining\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.total_listeners_warming\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.admin_overrides_active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.load_error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.load_success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.num_keys\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.override_dir_exists\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.override_dir_not_exists\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.days_until_first_cert_expiring\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.hot_restart_epoch\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.live\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.memory_allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.memory_heap_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.parent_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.total_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.version\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.watchdog_mega_miss\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.watchdog_miss\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.stats.overflow\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.api_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.backend_commit_duration.ns.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.backend_commit_duration.ns.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.mvcc_db_total_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.wal_fsync_duration.ns.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.wal_fsync_duration.ns.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.counts.followers.counts.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.counts.followers.counts.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.follower.latency.standardDeviation\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.followers.latency.average\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.followers.latency.current\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.followers.latency.maximum\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.followers.latency.minimum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.leader\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.memory.go_memstats_alloc.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.network.client_grpc_received.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.network.client_grpc_sent.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.leaderinfo.leader\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.leaderinfo.starttime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.leaderinfo.uptime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.recv.appendrequest.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.recv.bandwidthrate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.recv.pkgrate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.send.appendrequest.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.send.bandwidthrate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.send.pkgrate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.starttime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.grpc_handled.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.grpc_started.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.has_leader\",\"type\":\"number\",\"esTypes\":[\"byte\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.leader_changes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.proposals_committed.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.proposals_failed.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.proposals_pending.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.compareanddelete.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.compareanddelete.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.compareandswap.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.compareandswap.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.create.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.create.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.delete.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.delete.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.expire.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.gets.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.gets.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.sets.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.sets.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.update.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.update.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.watchers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.action\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.dataset\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.duration\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.end\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.module\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.outcome\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.provider\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.risk_score\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.risk_score_norm\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.sequence\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.severity\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.timezone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.accessed\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.ctime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.device\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.directory\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.extension\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.gid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.group\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.inode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mtime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.owner\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.target_path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.expvar.cmdline\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.frees\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.idle\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.mallocs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.cmdline\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.cpu_fraction\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.next_gc_limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.pause.avg.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.pause.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.pause.max.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.pause.sum.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.total_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.total_pause.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.obtained\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.released\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.stack\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"graphite.server.example\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.compress.bps.in\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.compress.bps.out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.compress.bps.rate_limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.hard_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.rate.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.ssl.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.ssl.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.ssl.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.idle.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.memory.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.pipes.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.pipes.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.pipes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.process_num\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.processes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.requests.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.requests.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.run_queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.session.rate.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.session.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.session.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.sockets.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.backend.key_rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.backend.key_rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.cache_misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.cached_lookups\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.frontend.key_rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.frontend.key_rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.frontend.session_reuse.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.rate.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.tasks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ulimit_n\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.uptime.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.zlib_mem_usage.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.zlib_mem_usage.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.agent.last\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.down\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.duration\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.health.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.health.last\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.client.aborted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.component_type\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.compressor.bypassed.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.compressor.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.compressor.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.compressor.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.connection.retried\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.connection.time.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.connection.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.downtime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.last_change\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.proxy.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.proxy.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.queue.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.queue.time.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.connection.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.denied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.queued.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.queued.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.redispatched\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.denied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.1xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.2xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.3xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.4xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.5xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.other\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.time.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.selected.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.server.aborted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.server.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.server.backup\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.server.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.service_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.rate.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.throttle.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.tracked.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.weight\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.containerized\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.build\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.codename\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.content\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.referrer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.content\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.phrase\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.status_code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.agent.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.agent.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.secured\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.server.product\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.server.vendor\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.server.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.url\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.broker.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.broker.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.broker.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.broker.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.client.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.client.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.client.member_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.error.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.meta\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.partition\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.topic\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.broker.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.broker.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.offset.newest\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.offset.oldest\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.error.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.insync_replica\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.is_leader\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.isr\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.leader\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.replica\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.topic.error.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.topic.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.topic_broker_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.topic_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.topic.error.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.topic.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.concurrent_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.host.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.index\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.event_loop_delay.ms\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.memory.heap.size_limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.memory.heap.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.memory.heap.uptime.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.memory.heap.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.request.disconnects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.request.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.response_time.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.response_time.max.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.snapshot\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.metrics.concurrent_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.metrics.requests.disconnects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.metrics.requests.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.status.overall.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.audit.event.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.audit.rejected.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.client.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.etcd.object.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.cpu.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.fds.open.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.memory.resident.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.memory.virtual.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.started.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.client\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.component\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.content_type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.current.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.dry_run\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.group\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.handler\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.kind\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.latency.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.latency.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.longrunning.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.resource\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.scope\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.subresource\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.verb\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.limit.cores\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.limit.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.request.cores\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.request.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.usage.core.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.usage.limit.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.usage.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.usage.node.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.image\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.inodes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.inodes.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.inodes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.majorpagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.pagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.request.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.usage.limit.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.usage.node.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.workingset.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.rootfs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.rootfs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.rootfs.inodes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.rootfs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.status.phase\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.status.ready\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.status.reason\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.status.restarts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.client.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.handler\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.leader.is_master\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.node.collector.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.node.collector.eviction.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.node.collector.health.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.node.collector.unhealthy.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.cpu.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.fds.open.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.memory.resident.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.memory.virtual.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.started.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.adds.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.depth.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.longestrunning.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.retries.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.unfinished.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.active.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.concurrency\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.created.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.deadline.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.is_suspended\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.last_schedule.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.next_schedule.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.schedule\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.paused\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.replicas.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.replicas.desired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.replicas.unavailable\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.replicas.updated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.api_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.kind\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.resource_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.message\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.namespace\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.resource_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.self_link\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.timestamp.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.reason\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.timestamp.first_occurrence\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.timestamp.last_occurrence\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.namespace\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.cpu.allocatable.cores\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.cpu.capacity.cores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.cpu.usage.core.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.cpu.usage.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.inodes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.inodes.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.inodes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.allocatable.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.majorpagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.pagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.workingset.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.network.rx.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.network.rx.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.network.tx.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.network.tx.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.pod.allocatable.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.pod.capacity.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.runtime.imagefs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.runtime.imagefs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.runtime.imagefs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.status.ready\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.status.unschedulable\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.cpu.usage.limit.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.cpu.usage.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.cpu.usage.node.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.host_ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.major_page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.usage.limit.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.usage.node.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.working_set.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.network.rx.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.network.rx.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.network.tx.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.network.tx.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.status.phase\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.status.ready\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.status.scheduled\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.client.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.handler\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.cpu.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.fds.open.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.memory.resident.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.memory.virtual.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.started.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.sync.networkprogramming.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.sync.networkprogramming.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.sync.rules.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.sync.rules.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.desired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.labeled\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.observed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.ready\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.client.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.handler\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.leader.is_master\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.operation\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.cpu.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.fds.open.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.memory.resident.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.memory.virtual.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.started.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.result\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.duration.seconds.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.duration.seconds.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.e2e.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.e2e.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.pod.attempts.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.pod.preemption.victims.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.generation.desired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.generation.observed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.replicas.desired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.replicas.observed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.container\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.cpu.usage.core.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.cpu.usage.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.majorpagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.pagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.workingset.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.inodes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.inodes.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.inodes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kvm.dommemstat.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kvm.dommemstat.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kvm.dommemstat.stat.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kvm.dommemstat.stat.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.level\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.logger\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"logstash.node.jvm.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"logstash.node.stats.events.filtered\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"logstash.node.stats.events.in\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"logstash.node.stats.events.out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.bytes.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.bytes.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.cmd.get\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.cmd.set\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.connections.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.connections.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.evictions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.get.hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.get.misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.items.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.items.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.threads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.uptime.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.written.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"metricset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"metricset.period\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.collection\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.commands.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.commands.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.db\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.getmore.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.getmore.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.insert.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.insert.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.lock.read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.lock.read.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.lock.write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.lock.write.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.queries.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.queries.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.remove.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.remove.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.total.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.total.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.update.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.update.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.avg_obj_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.collections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.data_file_version.major\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.data_file_version.minor\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.data_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.db\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.extent_free_list.num\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.extent_free_list.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.file_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.index_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.indexes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.ns_size_mb.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.num_extents\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.storage_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.aggregate.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.aggregate.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.build_info.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.build_info.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.coll_stats.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.coll_stats.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.connection_pool_stats.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.connection_pool_stats.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.count.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.count.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.db_stats.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.db_stats.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.distinct.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.distinct.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.find.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.find.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_cmd_line_opts.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_cmd_line_opts.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_last_error.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_last_error.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_log.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_log.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_more.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_more.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_parameter.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_parameter.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.host_info.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.host_info.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.insert.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.insert.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.is_master.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.is_master.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.is_self.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.is_self.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.last_collections.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.last_collections.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.last_commands.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.last_commands.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.list_databased.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.list_databased.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.list_indexes.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.list_indexes.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.ping.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.ping.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.profile.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.profile.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_get_rbid.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_get_rbid.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_get_status.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_get_status.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_heartbeat.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_heartbeat.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_update_position.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_update_position.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.server_status.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.server_status.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.update.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.update.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.whatsmyuri.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.whatsmyuri.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.cursor.open.no_timeout\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.cursor.open.pinned\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.cursor.open.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.cursor.timed_out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.document.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.document.inserted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.document.returned\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.document.updated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.get_last_error.write_timeouts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.get_last_error.write_wait.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.get_last_error.write_wait.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.operation.scan_and_order\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.operation.write_conflicts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.query_executor.scanned_documents\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.query_executor.scanned_indexes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.apply.attempts_to_become_secondary\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.apply.batches.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.apply.batches.time.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.apply.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.buffer.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.buffer.max_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.buffer.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.cancels\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.event_created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.event_wait\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.dbwork\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.exclusive\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.netcmd\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.work\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.work_at\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.waits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.event_waiters\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.network_interface\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.in_progress.dbwork\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.in_progress.exclusive\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.in_progress.network\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.ready\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.sleepers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.shutting_down\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.unsignaled_events\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.initial_sync.completed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.initial_sync.failed_attempts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.initial_sync.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.getmores.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.getmores.time.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.reders_created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.preload.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.preload.docs.time.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.preload.indexes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.preload.indexes.time.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.storage.free_list.search.bucket_exhausted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.storage.free_list.search.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.storage.free_list.search.scanned\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.ttl.deleted_documents\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.ttl.passes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.headroom.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.headroom.min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.lag.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.lag.min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.arbiter.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.arbiter.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.down.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.down.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.primary.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.primary.optime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.recovering.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.recovering.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.rollback.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.rollback.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.secondary.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.secondary.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.secondary.optimes\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.startup2.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.startup2.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.unhealthy.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.unhealthy.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.unknown.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.unknown.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.first.timestamp\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.last.timestamp\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.size.allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.size.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.window\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.optimes.applied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.optimes.durable\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.optimes.last_committed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.server_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.set_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.msg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.regular\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.rollovers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.user\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.warning\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.average.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.flushes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.last.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.last_finished\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.total.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.connections.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.connections.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.connections.total_created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.extra_info.heap_usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.extra_info.page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.active_clients.readers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.active_clients.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.active_clients.writers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.current_queue.readers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.current_queue.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.current_queue.writers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.total_time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.commits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.commits_in_write_lock\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.compression\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.early_commits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.journaled.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.commits.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.commits_in_write_lock.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.dt.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.prep_log_buffer.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.remap_private_view.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.write_to_data_files.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.write_to_journal.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.write_to_data_files.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.local_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.bits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.mapped.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.mapped_with_journal.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.resident.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.virtual.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.network.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.network.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.network.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.command\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.getmore\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.insert\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.query\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.update\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.commands.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.commands.latency\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.reads.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.reads.latency\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.writes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.writes.latency\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.command\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.getmore\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.insert\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.query\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.update\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.process\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.storage_engine.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.uptime.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.dirty.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.maximum.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.pages.evicted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.pages.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.pages.write\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.read.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.read.out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.read.total_tickets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.write.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.write.out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.write.total_tickets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.flushes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.max_file_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.scans\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.syncs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.writes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.write_backs_queued\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.database.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.database.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.active_temp_tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.batch_requests_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.cache_hit.pct\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.checkpoint_pages_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.database_pages\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.page_life_expectancy.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.target_pages\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.compilations_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.connections_reset_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.lock_waits_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.logins_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.logouts_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.page_splits_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.recompilations_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.transactions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.user_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.space_usage.since_last_backup.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.space_usage.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.space_usage.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.space_usage.used.pct\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.active_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.backup_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.recovery_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.since_last_checkpoint.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.total_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"munin.plugin.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.apply.oooe\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.apply.oool\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.apply.window\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cert.deps_distance\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cert.index_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cert.interval\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cluster.conf_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cluster.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cluster.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.commit.oooe\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.commit.window\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.connected\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.evs.evict\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.evs.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.flow_ctl.paused\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.flow_ctl.paused_ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.flow_ctl.recv\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.flow_ctl.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.last_committed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.bf_aborts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.cert_failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.commits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.recv.queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.recv.queue_avg\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.recv.queue_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.recv.queue_min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.replays\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.send.queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.send.queue_avg\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.send.queue_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.send.queue_min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.ready\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.received.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.received.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.data_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.keys\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.keys_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.other_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.aborted.clients\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.aborted.connects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.binlog.cache.disk_use\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.binlog.cache.use\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.bytes.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.bytes.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.command.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.command.insert\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.command.select\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.command.update\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.created.tmp.disk_tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.created.tmp.files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.created.tmp.tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.delayed.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.delayed.insert_threads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.delayed.writes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.flush_commands\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.commit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.external_lock\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.mrr_init\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.prepare\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.first\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.key\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.last\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.next\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.prev\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.rnd\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.rnd_next\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.rollback\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.savepoint\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.savepoint_rollback\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.update\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.write\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.bytes.data\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.bytes.dirty\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.dump_status\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.load_status\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.data\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.dirty\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.flushed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.latched\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.misc\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pool.reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pool.resize_status\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pool.wait_free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.read.ahead\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.read.ahead_evicted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.read.ahead_rnd\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.read.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.write_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.max_used_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.open.files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.open.streams\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.open.tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.opened_tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.queries\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.questions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.threads.cached\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.threads.connected\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.threads.created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.threads.running\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.connections.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.routes.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.server.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.server.time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.cores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.cpu\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.connz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.root\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.routez\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.subsz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.varz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.in.messages\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.mem.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.out.messages\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.remotes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.slow_consumers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.total_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.cache.fanout.avg\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.cache.fanout.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.cache.hit_rate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.cache.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.inserts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.matches\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.removes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.application\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.community_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.direction\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.forwarded_ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.iana_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.protocol\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.transport\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.accepts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.handled\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.reading\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.waiting\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.writing\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.vendor\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.buffer_pool\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cache.buffer.hit.pct\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cache.get.consistent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cache.get.db_blocks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cache.physical_reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.avg\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.cache_hit.pct\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.max\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.opened.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.opened.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.parse.real\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.parse.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.session.cache_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.total\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.io_reloads\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.lock_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.machine\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.pin_requests\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.username\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.online_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.size.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.size.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.space.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.space.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.space.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"organization.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.connections.accepted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.connections.listen_queue_len\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.connections.max_listen_queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.connections.queued\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.process_manager\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.idle\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.max_active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.max_children_reached\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.slow_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.start_since\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.last_request_cpu\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.last_request_memory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.request_duration\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.script\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.start_since\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.application_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.backend_start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.client.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.client.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.client.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.database.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.database.oid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.query\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.query_start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.state_change\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.transaction_start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.user.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.waiting\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.backend\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.backend_fsync\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.checkpoints\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.clean\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.clean_full\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.checkpoints.requested\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.checkpoints.scheduled\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.checkpoints.times.sync.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.checkpoints.times.write.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.stats_reset\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.blocks.hit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.blocks.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.blocks.time.read.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.blocks.time.write.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.conflicts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.deadlocks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.number_of_backends\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.oid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.fetched\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.inserted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.returned\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.updated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.stats_reset\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.temporary.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.temporary.files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.transactions.commit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.transactions.rollback\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.database.oid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.calls\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.local.dirtied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.local.hit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.local.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.local.written\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.shared.dirtied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.shared.hit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.shared.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.shared.written\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.temp.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.temp.written\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.rows\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.text\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.max.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.mean.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.min.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.stddev.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.total.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.user.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.args\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.executable\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pgid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.ppid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.title\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.working_directory\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.channel_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.channels\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.client_provided.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.frame_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.octet_count.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.octet_count.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.packet_count.pending\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.packet_count.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.packet_count.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.peer.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.peer.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.auto_delete\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.durable\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.internal\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.messages.publish_in.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.messages.publish_in.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.messages.publish_out.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.messages.publish_out.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.disk.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.disk.free.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.fd.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.fd.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.gc.num.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.gc.reclaimed.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.file_handle.open_attempt.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.file_handle.open_attempt.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.read.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.reopen.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.seek.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.seek.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.sync.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.sync.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.write.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.mem.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.mem.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.mnesia.disk.tx.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.mnesia.ram.tx.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.msg.store_read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.msg.store_write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.proc.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.proc.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.processors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.queue.index.journal_write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.queue.index.read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.queue.index.write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.run.queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.socket.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.socket.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.arguments.max_priority\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.auto_delete\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.consumers.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.consumers.utilisation.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.disk.reads.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.disk.writes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.durable\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.exclusive\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.persistent.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.ready.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.ready.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.total.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.total.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.unacknowledged.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.unacknowledged.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.vhost\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.biggest_input_buf\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.blocked\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.connected\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.longest_output_list\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.max_input_buffer\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.max_output_buffer\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cluster.enabled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cpu.used.sys\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cpu.used.sys_children\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cpu.used.user\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cpu.used.user_children\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.active_defrag.is_running\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.fragmentation.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.fragmentation.ratio\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.resident\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.rss.ratio\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.fragmentation.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.fragmentation.ratio\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.max.policy\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.max.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.dataset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.lua\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.peak\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.rss\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.bgrewrite.last_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.buffer.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.copy_on_write.last_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.enabled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.fsync.delayed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.fsync.pending\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.buffer.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.current_time.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.in_progress\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.last_time.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.scheduled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.size.base\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.size.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.write.last_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.loading\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.bgsave.current_time.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.bgsave.in_progress\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.bgsave.last_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.bgsave.last_time.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.copy_on_write.last_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.last_save.changes_since\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.last_save.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.backlog.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.backlog.first_byte_offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.backlog.histlen\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.backlog.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.connected_slaves\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.last_io_seconds_ago\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.link_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.second_offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.sync.in_progress\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.sync.last_io_seconds_ago\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.sync.left_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master_offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.role\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.slave.is_readonly\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.slave.offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.slave.priority\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.arch_bits\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.build_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.config_file\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.gcc_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.git_dirty\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.git_sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.hz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.lru_clock\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.mode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.multiplexing_api\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.run_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.tcp_port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.slowlog.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.active_defrag.hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.active_defrag.key_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.active_defrag.key_misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.active_defrag.misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.commands_processed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.connections.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.connections.rejected\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.instantaneous.input_kbps\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.instantaneous.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.instantaneous.output_kbps\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.keys.evicted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.keys.expired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.keyspace.hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.keyspace.misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.latest_fork_usec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.migrate_cached_sockets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.net.input.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.net.output.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.pubsub.channels\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.pubsub.patterns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.slave_expires_tracked_keys\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.sync.full\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.sync.partial.err\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.sync.partial.ok\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.expire.ttl\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.length\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.keyspace.avg_ttl\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.keyspace.expires\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.keyspace.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.keyspace.keys\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"related.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.ephemeral_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.idle.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.idle.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.iowait.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.iowait.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.irq.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.irq.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.nice.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.nice.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.softirq.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.softirq.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.steal.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.steal.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.system.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.system.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.user.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.user.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.cores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.idle.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.idle.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.idle.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.iowait.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.iowait.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.iowait.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.irq.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.irq.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.irq.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.nice.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.nice.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.nice.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.softirq.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.softirq.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.softirq.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.steal.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.steal.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.steal.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.system.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.system.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.system.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.total.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":3,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.user.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.user.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.user.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.io.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.await\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.busy\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.queue.avg_size\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.read.await\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.read.per_sec.bytes\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.read.request.merges_per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.read.request.per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.request.avg_size\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.service_time\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.write.await\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.write.per_sec.bytes\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.write.request.merges_per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.write.request.per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.read.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.write.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.entropy.available_bits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.entropy.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.device_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.free_files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.mount_point\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.total_files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.total_size.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.total_size.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.total_size.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.1\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.15\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.5\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.cores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.norm.1\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.norm.15\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.norm.5\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.actual.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.actual.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.actual.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.default_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.reserved\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.surplus\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.used.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.swap.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.swap.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.swap.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.swap.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.in.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.in.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.in.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.out.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.out.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.out.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.blkio.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.blkio.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.blkio.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.blkio.total.ios\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.cfs.period.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.cfs.quota.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.cfs.shares\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.rt.period.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.rt.runtime.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.stats.periods\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.stats.throttled.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.stats.throttled.periods\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.stats.system.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.stats.user.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.total.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem.usage.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem_tcp.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem_tcp.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem_tcp.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem_tcp.usage.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.usage.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.memsw.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.memsw.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.memsw.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.memsw.usage.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.active_anon.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.active_file.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.cache.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.hierarchical_memory_limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.hierarchical_memsw_limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.inactive_anon.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.inactive_file.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.major_page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.mapped_file.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.pages_in\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.pages_out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.rss_huge.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.swap.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.unevictable.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cmdline\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.system.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.user.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.fd.limit.hard\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.fd.limit.soft\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.fd.open\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.rss.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.share\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.dead\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.idle\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.running\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.sleeping\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.stopped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.unknown\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.zombie\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.blocks.synced\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.blocks.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.disks.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.disks.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.disks.spare\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.disks.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.level\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.sync_action\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.local.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.local.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.process.cmdline\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.etld_plus_one\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.host_error\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.all.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.all.listening\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.close_wait\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.established\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.listening\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.orphan\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.time_wait\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.memory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.udp.all.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.udp.memory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.uptime.duration.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"timeseries.instance\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tracing.trace.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tracing.transaction.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"traefik.health.response.avg_time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"traefik.health.response.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"traefik.health.uptime.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.fragment\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.password\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.query\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.scheme\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.username\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.device.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.read_errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.requests.offloaded\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.requests.routed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.requests.static\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.requests.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.worker_pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.write_errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.exceptions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.read_errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.write_errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.accepting\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.avg_rt\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.delta_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.exceptions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.harakiri_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.respawn_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.rss\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.running_time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.signal_queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.signals\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.tx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.vsz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.capacity.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.capacity.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.capacity.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.capacity.used.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.fstype\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.cpu.free.mhz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.cpu.total.mhz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.cpu.used.mhz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.memory.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.memory.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.memory.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.network_names\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.cpu.used.mhz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.memory.free.guest.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.memory.total.guest.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.memory.used.guest.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.memory.used.host.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.network_names\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.os\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.display_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.exit_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.path_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.start_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.start_type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.uptime.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.connection.interest_ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.connection.queued\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.connection.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.connection.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.approximate_data_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.ephemerals_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.followers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.latency.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.latency.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.latency.min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.max_file_descriptor_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.num_alive_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.open_file_descriptor_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.outstanding_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.packets.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.packets.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.pending_syncs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.server_state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.synced_followers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.watch_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.znode_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.epoch\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.latency.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.latency.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.latency.min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.mode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.node_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.outstanding\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.version_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.zxid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName" : "@timestamp", + "title" : "metricbeat-*" + }, + "type" : "index-pattern", + "migrationVersion" : { + "index-pattern" : "7.6.0" + }, + "updated_at" : "2020-01-22T15:34:59.061Z" + } + } +} + +{ + "type": "doc", + "value": { + "type": "_doc", + "index" : ".kibana", + "type": "doc", + "id" : "custom-space:index-pattern:metricbeat-*", + "source" : { + "index-pattern" : { + "fieldFormatMap" : "{\"aerospike.namespace.device.available.pct\":{\"id\":\"percent\",\"params\":{}},\"aerospike.namespace.device.free.pct\":{\"id\":\"percent\",\"params\":{}},\"aerospike.namespace.device.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.device.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.memory.free.pct\":{\"id\":\"percent\",\"params\":{}},\"aerospike.namespace.memory.used.data.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.memory.used.index.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.memory.used.sindex.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aerospike.namespace.memory.used.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.ec2.diskio.read.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.ec2.diskio.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.ec2.network.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.ec2.network.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.cpu.total.pct\":{\"id\":\"percent\",\"params\":{}},\"aws.rds.disk_usage.bin_log.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.free_local_storage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.free_storage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.freeable_memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.latency.commit\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.ddl\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.dml\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.insert\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.read\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.select\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.update\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.latency.write\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.replica_lag.sec\":{\"id\":\"duration\",\"params\":{}},\"aws.rds.swap_usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.rds.volume_used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_daily_storage.bucket.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_request.downloaded.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_request.latency.first_byte.ms\":{\"id\":\"duration\",\"params\":{}},\"aws.s3_request.latency.total_request.ms\":{\"id\":\"duration\",\"params\":{}},\"aws.s3_request.requests.select_returned.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_request.requests.select_scanned.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.s3_request.uploaded.bytes\":{\"id\":\"bytes\",\"params\":{}},\"aws.sqs.oldest_message_age.sec\":{\"id\":\"duration\",\"params\":{}},\"aws.sqs.sent_message_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_disk.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_disk.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_disk.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.degraded.ratio\":{\"id\":\"percent\",\"params\":{}},\"ceph.cluster_status.misplace.ratio\":{\"id\":\"percent\",\"params\":{}},\"ceph.cluster_status.pg.avail_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.pg.data_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.pg.total_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.pg.used_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.traffic.read_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.cluster_status.traffic.write_bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.monitor_health.store_stats.log.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.monitor_health.store_stats.misc.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.monitor_health.store_stats.sst.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.monitor_health.store_stats.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.osd_df.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.osd_df.total.byte\":{\"id\":\"bytes\",\"params\":{}},\"ceph.osd_df.used.byte\":{\"id\":\"bytes\",\"params\":{}},\"ceph.osd_df.used.pct\":{\"id\":\"percent\",\"params\":{}},\"ceph.pool_disk.stats.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"ceph.pool_disk.stats.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"client.bytes\":{\"id\":\"bytes\",\"params\":{}},\"client.nat.port\":{\"id\":\"string\",\"params\":{}},\"client.port\":{\"id\":\"string\",\"params\":{}},\"coredns.stats.dns.request.duration.ns.sum\":{\"id\":\"duration\",\"params\":{}},\"couchbase.bucket.data.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.bucket.disk.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.bucket.memory.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.bucket.quota.ram.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.bucket.quota.use.pct\":{\"id\":\"percent\",\"params\":{}},\"couchbase.cluster.hdd.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.hdd.quota.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.hdd.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.hdd.used.by_data.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.hdd.used.value.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.quota.total.per_node.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.quota.total.value.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.quota.used.per_node.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.quota.used.value.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.used.by_data.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.cluster.ram.used.value.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.node.couch.docs.data_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.node.couch.docs.disk_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"couchbase.node.mcd_memory.allocated.bytes\":{\"id\":\"bytes\",\"params\":{}},\"destination.bytes\":{\"id\":\"bytes\",\"params\":{}},\"destination.nat.port\":{\"id\":\"string\",\"params\":{}},\"destination.port\":{\"id\":\"string\",\"params\":{}},\"docker.cpu.core.*.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.cpu.kernel.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.cpu.system.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.cpu.total.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.cpu.user.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.diskio.read.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.diskio.summary.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.diskio.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.commit.peak\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.commit.total\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.limit\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.private_working_set.total\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.rss.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.memory.rss.total\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.usage.max\":{\"id\":\"bytes\",\"params\":{}},\"docker.memory.usage.pct\":{\"id\":\"percent\",\"params\":{}},\"docker.memory.usage.total\":{\"id\":\"bytes\",\"params\":{}},\"docker.network.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.network.inbound.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.network.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"docker.network.outbound.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.summary.primaries.segments.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.summary.primaries.store.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.summary.total.segments.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.summary.total.store.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.total.segments.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.index.total.store.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.jvm.memory.heap.init.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.jvm.memory.heap.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.jvm.memory.nonheap.init.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.jvm.memory.nonheap.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.fs.summary.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.fs.summary.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.fs.summary.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.indices.segments.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.old.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.old.peak.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.old.peak_max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.old.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.survivor.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.survivor.peak.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.survivor.peak_max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.survivor.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.young.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.young.peak.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.young.peak_max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"elasticsearch.node.stats.jvm.mem.pools.young.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"etcd.disk.mvcc_db_total_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"etcd.memory.go_memstats_alloc.bytes\":{\"id\":\"bytes\",\"params\":{}},\"etcd.network.client_grpc_received.bytes\":{\"id\":\"bytes\",\"params\":{}},\"etcd.network.client_grpc_sent.bytes\":{\"id\":\"bytes\",\"params\":{}},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\",\"params\":{}},\"event.severity\":{\"id\":\"string\",\"params\":{}},\"golang.heap.allocations.active\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.allocations.allocated\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.allocations.idle\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.allocations.total\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.gc.next_gc_limit\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.system.obtained\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.system.released\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.system.stack\":{\"id\":\"bytes\",\"params\":{}},\"golang.heap.system.total\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.info.idle.pct\":{\"id\":\"percent\",\"params\":{}},\"haproxy.info.memory.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.info.ssl.frontend.session_reuse.pct\":{\"id\":\"percent\",\"params\":{}},\"haproxy.stat.compressor.bypassed.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.compressor.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.compressor.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.compressor.response.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"haproxy.stat.throttle.pct\":{\"id\":\"percent\",\"params\":{}},\"http.request.body.bytes\":{\"id\":\"bytes\",\"params\":{}},\"http.request.bytes\":{\"id\":\"bytes\",\"params\":{}},\"http.response.body.bytes\":{\"id\":\"bytes\",\"params\":{}},\"http.response.bytes\":{\"id\":\"bytes\",\"params\":{}},\"http.response.status_code\":{\"id\":\"string\",\"params\":{}},\"kibana.stats.process.memory.heap.size_limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kibana.stats.process.memory.heap.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kibana.stats.process.memory.heap.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.apiserver.http.request.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.apiserver.http.response.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.apiserver.process.memory.resident.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.apiserver.process.memory.virtual.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.cpu.usage.limit.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.container.cpu.usage.node.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.container.logs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.logs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.logs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.request.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.memory.usage.limit.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.container.memory.usage.node.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.container.memory.workingset.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.rootfs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.rootfs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.container.rootfs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.controllermanager.http.request.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.controllermanager.http.response.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.controllermanager.process.memory.resident.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.controllermanager.process.memory.virtual.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.fs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.fs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.fs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.allocatable.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.memory.workingset.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.network.rx.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.network.tx.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.runtime.imagefs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.runtime.imagefs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.node.runtime.imagefs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.cpu.usage.limit.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.pod.cpu.usage.node.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.pod.memory.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.memory.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.memory.usage.limit.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.pod.memory.usage.node.pct\":{\"id\":\"percent\",\"params\":{}},\"kubernetes.pod.memory.working_set.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.network.rx.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.pod.network.tx.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.proxy.http.request.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.proxy.http.response.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.proxy.process.memory.resident.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.proxy.process.memory.virtual.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.scheduler.http.request.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.scheduler.http.response.size.bytes.sum\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.scheduler.process.memory.resident.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.scheduler.process.memory.virtual.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.system.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.system.memory.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.system.memory.workingset.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.volume.fs.available.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.volume.fs.capacity.bytes\":{\"id\":\"bytes\",\"params\":{}},\"kubernetes.volume.fs.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.avg_obj_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.data_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.extent_free_list.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.file_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.index_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.dbstats.storage_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.replstatus.headroom.max\":{\"id\":\"duration\",\"params\":{}},\"mongodb.replstatus.headroom.min\":{\"id\":\"duration\",\"params\":{}},\"mongodb.replstatus.lag.max\":{\"id\":\"duration\",\"params\":{}},\"mongodb.replstatus.lag.min\":{\"id\":\"duration\",\"params\":{}},\"mongodb.replstatus.oplog.size.allocated\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.replstatus.oplog.size.used\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.extra_info.heap_usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.network.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.network.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.cache.dirty.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.cache.maximum.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.cache.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.log.max_file_size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.log.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mongodb.status.wired_tiger.log.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"mysql.status.bytes.received\":{\"id\":\"bytes\",\"params\":{}},\"mysql.status.bytes.sent\":{\"id\":\"bytes\",\"params\":{}},\"nats.stats.cpu\":{\"id\":\"percent\",\"params\":{}},\"nats.stats.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"nats.stats.mem.bytes\":{\"id\":\"bytes\",\"params\":{}},\"nats.stats.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"nats.stats.uptime\":{\"id\":\"duration\",\"params\":{}},\"nats.subscriptions.cache.hit_rate\":{\"id\":\"percent\",\"params\":{}},\"network.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.data_file.size.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.data_file.size.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.data_file.size.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.space.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.space.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"oracle.tablespace.space.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"process.pgid\":{\"id\":\"string\",\"params\":{}},\"process.pid\":{\"id\":\"string\",\"params\":{}},\"process.ppid\":{\"id\":\"string\",\"params\":{}},\"process.thread.id\":{\"id\":\"string\",\"params\":{}},\"rabbitmq.connection.frame_max\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.disk.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.disk.free.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.gc.reclaimed.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.io.read.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.io.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.node.mem.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"rabbitmq.queue.consumers.utilisation.pct\":{\"id\":\"percent\",\"params\":{}},\"rabbitmq.queue.memory.bytes\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.active\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.allocated\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.fragmentation.bytes\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.resident\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.allocator_stats.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.fragmentation.bytes\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.max.value\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.dataset\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.lua\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.peak\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.rss\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.memory.used.value\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.buffer.size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.copy_on_write.last_size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.rewrite.buffer.size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.rewrite.current_time.sec\":{\"id\":\"duration\",\"params\":{}},\"redis.info.persistence.aof.rewrite.last_time.sec\":{\"id\":\"duration\",\"params\":{}},\"redis.info.persistence.aof.size.base\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.aof.size.current\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.persistence.rdb.bgsave.current_time.sec\":{\"id\":\"duration\",\"params\":{}},\"redis.info.persistence.rdb.bgsave.last_time.sec\":{\"id\":\"duration\",\"params\":{}},\"redis.info.persistence.rdb.copy_on_write.last_size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.replication.backlog.size\":{\"id\":\"bytes\",\"params\":{}},\"redis.info.replication.master.last_io_seconds_ago\":{\"id\":\"duration\",\"params\":{}},\"redis.info.replication.master.sync.last_io_seconds_ago\":{\"id\":\"duration\",\"params\":{}},\"redis.info.replication.master.sync.left_bytes\":{\"id\":\"bytes\",\"params\":{}},\"server.bytes\":{\"id\":\"bytes\",\"params\":{}},\"server.nat.port\":{\"id\":\"string\",\"params\":{}},\"server.port\":{\"id\":\"string\",\"params\":{}},\"source.bytes\":{\"id\":\"bytes\",\"params\":{}},\"source.nat.port\":{\"id\":\"string\",\"params\":{}},\"source.port\":{\"id\":\"string\",\"params\":{}},\"system.core.idle.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.iowait.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.irq.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.nice.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.softirq.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.steal.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.system.pct\":{\"id\":\"percent\",\"params\":{}},\"system.core.user.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.idle.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.idle.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.iowait.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.iowait.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.irq.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.irq.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.nice.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.nice.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.softirq.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.softirq.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.steal.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.steal.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.system.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.system.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.total.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.total.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.user.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.cpu.user.pct\":{\"id\":\"percent\",\"params\":{}},\"system.diskio.iostat.read.per_sec.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.diskio.iostat.write.per_sec.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.diskio.read.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.diskio.write.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.entropy.pct\":{\"id\":\"percent\",\"params\":{}},\"system.filesystem.available\":{\"id\":\"bytes\",\"params\":{}},\"system.filesystem.free\":{\"id\":\"bytes\",\"params\":{}},\"system.filesystem.total\":{\"id\":\"bytes\",\"params\":{}},\"system.filesystem.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.filesystem.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.fsstat.total_size.free\":{\"id\":\"bytes\",\"params\":{}},\"system.fsstat.total_size.total\":{\"id\":\"bytes\",\"params\":{}},\"system.fsstat.total_size.used\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.actual.free\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.actual.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.actual.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.memory.free\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.hugepages.default_size\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.hugepages.free\":{\"id\":\"number\",\"params\":{}},\"system.memory.hugepages.reserved\":{\"id\":\"number\",\"params\":{}},\"system.memory.hugepages.surplus\":{\"id\":\"number\",\"params\":{}},\"system.memory.hugepages.total\":{\"id\":\"number\",\"params\":{}},\"system.memory.hugepages.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.hugepages.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.memory.swap.free\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.swap.total\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.swap.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.swap.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.memory.total\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.memory.used.pct\":{\"id\":\"percent\",\"params\":{}},\"system.network.in.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.network.out.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.blkio.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem.usage.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem_tcp.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem_tcp.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.kmem_tcp.usage.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.mem.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.mem.usage.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.memsw.limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.memsw.usage.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.memsw.usage.max.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.active_anon.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.active_file.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.cache.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.hierarchical_memory_limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.hierarchical_memsw_limit.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.inactive_anon.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.inactive_file.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.mapped_file.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.rss_huge.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.swap.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cgroup.memory.stats.unevictable.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\",\"params\":{}},\"system.process.cpu.total.pct\":{\"id\":\"percent\",\"params\":{}},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\",\"params\":{}},\"system.process.memory.rss.pct\":{\"id\":\"percent\",\"params\":{}},\"system.process.memory.share\":{\"id\":\"bytes\",\"params\":{}},\"system.process.memory.size\":{\"id\":\"bytes\",\"params\":{}},\"system.socket.summary.tcp.memory\":{\"id\":\"bytes\",\"params\":{}},\"system.socket.summary.udp.memory\":{\"id\":\"bytes\",\"params\":{}},\"system.uptime.duration.ms\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"milliseconds\"}},\"url.port\":{\"id\":\"string\",\"params\":{}},\"vsphere.datastore.capacity.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.datastore.capacity.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.datastore.capacity.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.datastore.capacity.used.pct\":{\"id\":\"percent\",\"params\":{}},\"vsphere.host.memory.free.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.host.memory.total.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.host.memory.used.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.virtualmachine.memory.free.guest.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.virtualmachine.memory.total.guest.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.virtualmachine.memory.used.guest.bytes\":{\"id\":\"bytes\",\"params\":{}},\"vsphere.virtualmachine.memory.used.host.bytes\":{\"id\":\"bytes\",\"params\":{}},\"windows.service.uptime.ms\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"milliseconds\"}}}", + "fields" : "[{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"aerospike.namespace.client.delete.error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.delete.not_found\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.delete.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.delete.timeout\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.read.error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.read.not_found\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.read.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.read.timeout\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.write.error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.write.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.client.write.timeout\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.device.available.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.device.free.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.device.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.device.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.hwm_breached\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.free.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.used.data.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.used.index.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.used.sindex.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.memory.used.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.node.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.objects.master\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.objects.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aerospike.namespace.stop_writes\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.ephemeral_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.bytes_per_request\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.connections.async.closing\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.connections.async.keep_alive\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.connections.async.writing\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.connections.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.children_system\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.children_user\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.load\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.system\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.cpu.user\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.load.1\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.load.15\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.load.5\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.requests_per_sec\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.closing_connection\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.dns_lookup\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.gracefully_finishing\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.idle_cleanup\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.keepalive\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.logging\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.open_slot\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.reading_request\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.sending_reply\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.starting_up\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.scoreboard.waiting_for_connection\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.total_accesses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.total_kbytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.uptime.server_uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.uptime.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.workers.busy\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"apache.status.workers.idle\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.cloudwatch.namespace\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.credit_balance\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.credit_usage\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.surplus_credit_balance\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.surplus_credits_charged\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.read.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.read.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.read.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.write.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.write.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.diskio.write.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.core.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.image.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.monitoring.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.private.dns_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.private.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.public.dns_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.public.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.state.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.state.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.instance.threads_per_core\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.in.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.in.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.in.packets_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.out.bytes_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.out.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.network.out.packets_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.status.check_failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.status.check_failed_instance\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.ec2.status.check_failed_system\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.cpu.credit_balance\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.cpu.credit_usage\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.database_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.db_instance.arn\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.db_instance.class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.db_instance.identifier\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.db_instance.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.deadlocks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.disk_queue_depth\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.disk_usage.bin_log.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.disk_usage.replication_slot.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.disk_usage.transaction_logs.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.failed_sql_server_agent_jobs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.free_local_storage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.free_storage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.freeable_memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.commit\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.ddl\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.dml\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.insert\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.read\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.select\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.update\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.latency.write\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.login_failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.maximum_used_transaction_ids\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.oldest_replication_slot_lag.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.queries\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.read_io.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.replica_lag.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.swap_usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.commit\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.ddl\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.delete\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.dml\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.insert\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.network\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.network_receive\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.network_transmit\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.read\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.select\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.update\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.throughput.write\",\"type\":\"number\",\"esTypes\":[\"float\",\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.transaction_logs_generation\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.transactions.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.transactions.blocked\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.volume_used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.rds.write_io.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_daily_storage.bucket.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_daily_storage.bucket.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_daily_storage.number_of_objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.bucket.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.downloaded.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.errors.4xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.errors.5xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.latency.first_byte.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.latency.total_request.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.get\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.head\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.list\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.post\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.put\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.select\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.select_returned.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.select_scanned.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.requests.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.s3_request.uploaded.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.empty_receives\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.delayed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.not_visible\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.messages.visible\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.oldest_message_age.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.queue.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"aws.sqs.sent_message_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.state.management.enabled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.state.module.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.state.output.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.state.queue.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.acked\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.batches\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.duplicates\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.toomany\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.events.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.read.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.libbeat.output.write.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.runtime.goroutines\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.stats.uptime.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"beat.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_disk.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_disk.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_disk.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_health.overall_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_health.timechecks.epoch\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_health.timechecks.round.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_health.timechecks.round.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.degraded.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.degraded.ratio\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.degraded.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.misplace.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.misplace.ratio\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.misplace.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.epoch\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.full\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.nearfull\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.num_in_osds\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.num_osds\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.num_remapped_pgs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.osd.num_up_osds\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg.avail_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg.data_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg.total_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg.used_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg_state.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg_state.state_name\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.pg_state.version\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.traffic.read_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.traffic.read_op_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.traffic.write_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.traffic.write_op_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.cluster_status.version\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.available.kb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.available.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.health\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.last_updated\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.last_updated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.log.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.misc.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.sst.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.store_stats.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.total.kb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.monitor_health.used.kb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.device_class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.pg_num\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.total.byte\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.used.byte\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_df.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.children\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.crush_weight\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.depth\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.device_class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.exists\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.father\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.primary_affinity\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.reweight\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.osd_tree.type_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.stats.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.stats.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.stats.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ceph.pool_disk.stats.used.kb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.account.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.availability_zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.image.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.instance.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.instance.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.machine.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.project.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.provider\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.region\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.autopilot.healthy\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.alloc.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.garbage_collector.pause.current.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.garbage_collector.pause.total.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.garbage_collector.runs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.goroutines\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.heap_objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.malloc_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"consul.agent.runtime.sys.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.image.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.image.tag\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.runtime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.cache.hits.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.cache.misses.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.do.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.duration.ns.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.duration.ns.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.request.type.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.response.rcode.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.dns.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.panic.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.proto\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.rcode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.server\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"coredns.stats.zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.data.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.disk.fetches\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.disk.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.item_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.memory.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.quota.ram.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.quota.use.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.bucket.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.quota.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.used.by_data.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.hdd.used.value.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.max_bucket_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.quota.index_memory.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.quota.memory.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.quota.total.per_node.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.quota.total.value.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.quota.used.per_node.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.quota.used.value.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.used.by_data.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.cluster.ram.used.value.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.cmd_get\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.docs.data_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.docs.disk_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.spatial.data_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.spatial.disk_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.views.data_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.couch.views.disk_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.cpu_utilization_rate.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.current_items.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.current_items.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.ep_bg_fetched\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.get_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.mcd_memory.allocated.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.mcd_memory.reserved.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.memory.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.memory.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.memory.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.swap.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.swap.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.uptime.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchbase.node.vb_replica_curr_items\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.auth_cache_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.auth_cache_misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.database_reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.database_writes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.open_databases\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.open_os_files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.couchdb.request_time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.bulk_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.clients_requesting_changes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.temporary_view_reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd.view_reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.COPY\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.DELETE\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.GET\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.HEAD\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.POST\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_request_methods.PUT\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.200\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.201\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.202\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.301\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.304\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.400\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.401\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.403\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.404\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.405\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.409\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.412\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"couchdb.server.httpd_status_codes.500\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.data\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.ttl\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.header_flags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.op_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.registered_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.resolved_ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.response_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.command\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.ip_addresses\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.size.root_fs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.size.rw\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.container.tags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.kernel.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.kernel.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.system.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.system.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.user.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.cpu.user.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.read.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.read.rate\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.reads\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.summary.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.summary.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.summary.rate\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.total\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.write.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.write.rate\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.diskio.writes\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.action\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.actor.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.from\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.event.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.event.end_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.event.exit_code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.event.output\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.event.start_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.failingstreak\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.healthcheck.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.id.current\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.id.parent\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.size.regular\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.size.virtual\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.image.tags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.containers.paused\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.containers.running\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.containers.stopped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.containers.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.info.images\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.commit.peak\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.commit.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.fail.count\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.private_working_set.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.rss.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.rss.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.usage.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.usage.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.memory.usage.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.in.dropped\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.in.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.in.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.inbound.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.inbound.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.inbound.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.inbound.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.interface\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.out.dropped\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.out.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.out.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.outbound.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.outbound.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.outbound.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"docker.network.outbound.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ecs.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.global_checkpoint\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.index\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.operations_written\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.shard.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.follower.time_since_last_read.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.leader.index\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ccr.leader.max_seq_no\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.pending_task.insert_order\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.pending_task.priority\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.pending_task.source\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.pending_task.time_in_queue.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.state.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.indices.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.indices.fielddata.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.indices.shards.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.indices.shards.primaries\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.nodes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.nodes.data\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.nodes.master\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.cluster.stats.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.primary\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.source.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.source.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.source.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.stage\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.target.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.target.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.target.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.recovery.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.docs.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.segments.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.segments.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.primaries.store.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.docs.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.segments.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.segments.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.summary.total.store.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.docs.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.segments.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.segments.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.index.total.store.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ml.job.data_counts.invalid_date_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ml.job.data_counts.processed_record_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ml.job.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.ml.job.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.memory.heap.init.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.memory.heap.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.memory.nonheap.init.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.memory.nonheap.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.jvm.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.process.mlockall\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.fs.summary.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.fs.summary.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.fs.summary.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.docs.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.segments.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.segments.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.indices.store.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.gc.collectors.old.collection.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.gc.collectors.old.collection.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.gc.collectors.young.collection.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.gc.collectors.young.collection.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.old.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.old.peak.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.old.peak_max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.old.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.survivor.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.survivor.peak.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.survivor.peak_max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.survivor.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.young.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.young.peak.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.young.peak_max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.stats.jvm.mem.pools.young.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.node.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.shard.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.shard.primary\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.shard.relocating_node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elasticsearch.shard.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.active_clusters\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.cluster_added\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.cluster_modified\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.cluster_removed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.cluster_manager.warming_clusters\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.flushed_by_timer\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.reopen_failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.write_buffered\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.write_completed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.filesystem.write_total_buffered\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.header_overflow\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.headers_cb_no_stream\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.rx_messaging_error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.rx_reset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.too_many_header_frames\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.trailers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.http2.tx_reset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_added\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_create_failure\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_create_success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_modified\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.listener_removed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.total_listeners_active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.total_listeners_draining\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.listener_manager.total_listeners_warming\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.admin_overrides_active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.load_error\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.load_success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.num_keys\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.override_dir_exists\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.runtime.override_dir_not_exists\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.days_until_first_cert_expiring\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.hot_restart_epoch\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.live\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.memory_allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.memory_heap_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.parent_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.total_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.version\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.watchdog_mega_miss\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.server.watchdog_miss\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"envoyproxy.server.stats.overflow\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.api_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.backend_commit_duration.ns.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.backend_commit_duration.ns.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.mvcc_db_total_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.wal_fsync_duration.ns.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.disk.wal_fsync_duration.ns.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.counts.followers.counts.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.counts.followers.counts.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.follower.latency.standardDeviation\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.followers.latency.average\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.followers.latency.current\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.followers.latency.maximum\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.followers.latency.followers.latency.minimum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.leader.leader\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.memory.go_memstats_alloc.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.network.client_grpc_received.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.network.client_grpc_sent.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.leaderinfo.leader\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.leaderinfo.starttime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.leaderinfo.uptime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.recv.appendrequest.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.recv.bandwidthrate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.recv.pkgrate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.send.appendrequest.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.send.bandwidthrate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.send.pkgrate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.starttime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.self.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.grpc_handled.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.grpc_started.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.has_leader\",\"type\":\"number\",\"esTypes\":[\"byte\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.leader_changes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.proposals_committed.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.proposals_failed.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.server.proposals_pending.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.compareanddelete.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.compareanddelete.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.compareandswap.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.compareandswap.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.create.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.create.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.delete.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.delete.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.expire.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.gets.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.gets.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.sets.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.sets.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.update.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.update.success\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"etcd.store.watchers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.action\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.dataset\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.duration\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.end\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.module\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.outcome\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.provider\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.risk_score\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.risk_score_norm\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.sequence\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.severity\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.timezone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.accessed\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.ctime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.device\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.directory\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.extension\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.gid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.group\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.inode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mtime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.owner\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.target_path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.expvar.cmdline\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.frees\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.idle\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.mallocs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.cmdline\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.cpu_fraction\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.next_gc_limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.pause.avg.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.pause.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.pause.max.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.pause.sum.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.total_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.total_pause.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.obtained\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.released\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.stack\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"graphite.server.example\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.compress.bps.in\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.compress.bps.out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.compress.bps.rate_limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.hard_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.rate.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.ssl.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.ssl.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.ssl.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.connection.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.idle.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.memory.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.pipes.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.pipes.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.pipes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.process_num\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.processes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.requests.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.requests.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.run_queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.session.rate.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.session.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.session.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.sockets.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.backend.key_rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.backend.key_rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.cache_misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.cached_lookups\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.frontend.key_rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.frontend.key_rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.frontend.session_reuse.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.rate.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ssl.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.tasks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.ulimit_n\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.uptime.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.zlib_mem_usage.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.info.zlib_mem_usage.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.agent.last\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.down\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.duration\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.health.fail\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.health.last\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.check.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.client.aborted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.component_type\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.compressor.bypassed.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.compressor.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.compressor.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.compressor.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.connection.retried\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.connection.time.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.connection.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.downtime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.last_change\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.proxy.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.proxy.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.queue.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.queue.time.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.connection.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.denied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.queued.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.queued.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.redispatched\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.request.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.denied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.1xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.2xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.3xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.4xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.5xx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.http.other\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.response.time.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.selected.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.server.aborted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.server.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.server.backup\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.server.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.service_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.rate.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.rate.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.session.rate.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.throttle.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.tracked.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"haproxy.stat.weight\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.containerized\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.build\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.codename\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.content\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.referrer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.content\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.phrase\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.status_code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.agent.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.agent.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.secured\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.server.product\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.server.vendor\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.server.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jolokia.url\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.broker.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.broker.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.broker.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.broker.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.client.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.client.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.client.member_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.error.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.meta\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.partition\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.consumergroup.topic\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.broker.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.broker.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.offset.newest\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.offset.oldest\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.error.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.insync_replica\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.is_leader\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.isr\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.leader\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.partition.replica\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.topic.error.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.topic.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.topic_broker_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.partition.topic_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.topic.error.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kafka.topic.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.concurrent_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.host.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.index\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.event_loop_delay.ms\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.memory.heap.size_limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.memory.heap.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.memory.heap.uptime.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.process.memory.heap.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.request.disconnects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.request.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.response_time.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.response_time.max.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.snapshot\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.stats.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.metrics.concurrent_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.metrics.requests.disconnects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.metrics.requests.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kibana.status.status.overall.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.audit.event.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.audit.rejected.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.client.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.etcd.object.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.http.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.cpu.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.fds.open.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.memory.resident.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.memory.virtual.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.process.started.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.client\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.component\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.content_type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.current.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.dry_run\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.group\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.handler\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.kind\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.latency.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.latency.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.longrunning.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.resource\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.scope\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.subresource\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.verb\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.apiserver.request.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.limit.cores\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.limit.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.request.cores\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.request.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.usage.core.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.usage.limit.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.usage.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.cpu.usage.node.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.image\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.inodes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.inodes.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.inodes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.logs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.majorpagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.pagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.request.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.usage.limit.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.usage.node.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.memory.workingset.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.rootfs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.rootfs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.rootfs.inodes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.rootfs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.status.phase\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.status.ready\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.status.reason\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.status.restarts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.client.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.handler\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.http.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.leader.is_master\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.node.collector.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.node.collector.eviction.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.node.collector.health.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.node.collector.unhealthy.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.cpu.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.fds.open.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.memory.resident.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.memory.virtual.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.process.started.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.adds.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.depth.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.longestrunning.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.retries.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.workqueue.unfinished.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.controllermanager.zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.active.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.concurrency\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.created.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.deadline.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.is_suspended\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.last_schedule.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.next_schedule.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.cronjob.schedule\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.paused\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.replicas.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.replicas.desired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.replicas.unavailable\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.replicas.updated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.api_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.kind\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.resource_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.involved_object.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.message\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.namespace\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.resource_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.self_link\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.timestamp.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.metadata.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.reason\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.timestamp.first_occurrence\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.timestamp.last_occurrence\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.event.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.namespace\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.cpu.allocatable.cores\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.cpu.capacity.cores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.cpu.usage.core.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.cpu.usage.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.inodes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.inodes.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.inodes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.fs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.allocatable.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.majorpagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.pagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.memory.workingset.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.network.rx.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.network.rx.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.network.tx.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.network.tx.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.pod.allocatable.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.pod.capacity.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.runtime.imagefs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.runtime.imagefs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.runtime.imagefs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.status.ready\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.status.unschedulable\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.cpu.usage.limit.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.cpu.usage.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.cpu.usage.node.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.host_ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.major_page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.usage.limit.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.usage.node.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.memory.working_set.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.network.rx.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.network.rx.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.network.tx.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.network.tx.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.status.phase\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.status.ready\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.status.scheduled\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.client.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.handler\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.http.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.cpu.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.fds.open.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.memory.resident.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.memory.virtual.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.process.started.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.sync.networkprogramming.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.sync.networkprogramming.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.sync.rules.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.proxy.sync.rules.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.desired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.labeled\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.observed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.replicas.ready\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.client.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.handler\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.request.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.response.size.bytes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.http.response.size.bytes.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.leader.is_master\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.operation\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.cpu.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.fds.open.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.memory.resident.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.memory.virtual.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.process.started.sec\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.result\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.duration.seconds.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.duration.seconds.sum\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.e2e.duration.us.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.e2e.duration.us.sum\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.pod.attempts.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.scheduler.scheduling.pod.preemption.victims.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.generation.desired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.generation.observed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.replicas.desired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.replicas.observed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.container\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.cpu.usage.core.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.cpu.usage.nanocores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.majorpagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.pagefaults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.memory.workingset.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.system.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.available.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.capacity.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.inodes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.inodes.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.inodes.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.fs.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.volume.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kvm.dommemstat.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kvm.dommemstat.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kvm.dommemstat.stat.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kvm.dommemstat.stat.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.level\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.logger\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"logstash.node.jvm.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"logstash.node.stats.events.filtered\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"logstash.node.stats.events.in\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"logstash.node.stats.events.out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.bytes.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.bytes.limit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.cmd.get\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.cmd.set\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.connections.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.connections.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.evictions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.get.hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.get.misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.items.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.items.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.threads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.uptime.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memcached.stats.written.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"metricset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"metricset.period\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.collection\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.commands.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.commands.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.db\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.getmore.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.getmore.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.insert.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.insert.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.lock.read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.lock.read.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.lock.write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.lock.write.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.queries.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.queries.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.remove.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.remove.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.total.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.total.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.update.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.collstats.update.time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.avg_obj_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.collections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.data_file_version.major\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.data_file_version.minor\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.data_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.db\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.extent_free_list.num\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.extent_free_list.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.file_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.index_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.indexes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.ns_size_mb.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.num_extents\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.dbstats.storage_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.aggregate.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.aggregate.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.build_info.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.build_info.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.coll_stats.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.coll_stats.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.connection_pool_stats.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.connection_pool_stats.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.count.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.count.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.db_stats.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.db_stats.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.distinct.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.distinct.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.find.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.find.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_cmd_line_opts.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_cmd_line_opts.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_last_error.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_last_error.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_log.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_log.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_more.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_more.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_parameter.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.get_parameter.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.host_info.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.host_info.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.insert.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.insert.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.is_master.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.is_master.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.is_self.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.is_self.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.last_collections.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.last_collections.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.last_commands.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.last_commands.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.list_databased.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.list_databased.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.list_indexes.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.list_indexes.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.ping.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.ping.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.profile.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.profile.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_get_rbid.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_get_rbid.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_get_status.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_get_status.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_heartbeat.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_heartbeat.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_update_position.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.replset_update_position.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.server_status.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.server_status.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.update.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.update.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.whatsmyuri.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.commands.whatsmyuri.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.cursor.open.no_timeout\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.cursor.open.pinned\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.cursor.open.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.cursor.timed_out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.document.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.document.inserted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.document.returned\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.document.updated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.get_last_error.write_timeouts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.get_last_error.write_wait.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.get_last_error.write_wait.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.operation.scan_and_order\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.operation.write_conflicts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.query_executor.scanned_documents\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.query_executor.scanned_indexes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.apply.attempts_to_become_secondary\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.apply.batches.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.apply.batches.time.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.apply.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.buffer.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.buffer.max_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.buffer.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.cancels\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.event_created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.event_wait\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.dbwork\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.exclusive\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.netcmd\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.work\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.scheduled.work_at\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.counters.waits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.event_waiters\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.network_interface\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.in_progress.dbwork\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.in_progress.exclusive\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.in_progress.network\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.ready\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.queues.sleepers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.shutting_down\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.executor.unsignaled_events\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.initial_sync.completed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.initial_sync.failed_attempts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.initial_sync.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.getmores.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.getmores.time.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.network.reders_created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.preload.docs.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.preload.docs.time.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.preload.indexes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.replication.preload.indexes.time.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.storage.free_list.search.bucket_exhausted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.storage.free_list.search.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.storage.free_list.search.scanned\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.ttl.deleted_documents\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.metrics.ttl.passes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.headroom.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.headroom.min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.lag.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.lag.min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.arbiter.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.arbiter.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.down.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.down.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.primary.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.primary.optime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.recovering.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.recovering.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.rollback.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.rollback.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.secondary.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.secondary.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.secondary.optimes\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.startup2.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.startup2.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.unhealthy.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.unhealthy.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.unknown.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.members.unknown.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.first.timestamp\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.last.timestamp\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.size.allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.size.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.oplog.window\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.optimes.applied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.optimes.durable\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.optimes.last_committed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.server_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.replstatus.set_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.msg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.regular\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.rollovers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.user\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.asserts.warning\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.average.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.flushes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.last.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.last_finished\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.background_flushing.total.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.connections.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.connections.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.connections.total_created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.extra_info.heap_usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.extra_info.page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.active_clients.readers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.active_clients.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.active_clients.writers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.current_queue.readers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.current_queue.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.current_queue.writers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.global_lock.total_time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.commits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.commits_in_write_lock\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.compression\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.early_commits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.journaled.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.commits.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.commits_in_write_lock.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.dt.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.prep_log_buffer.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.remap_private_view.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.write_to_data_files.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.times.write_to_journal.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.journaling.write_to_data_files.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.local_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.collection.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.database.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.global.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.meta_data.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.acquire.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.acquire.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.acquire.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.acquire.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.deadlock.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.deadlock.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.deadlock.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.deadlock.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.count.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.count.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.count.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.count.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.us.R\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.us.W\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.us.r\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.locks.oplog.wait.us.w\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.bits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.mapped.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.mapped_with_journal.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.resident.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.memory.virtual.mb\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.network.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.network.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.network.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.command\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.getmore\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.insert\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.query\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.counters.update\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.commands.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.commands.latency\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.reads.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.reads.latency\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.writes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.latencies.writes.latency\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.command\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.getmore\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.insert\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.query\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.ops.replicated.update\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.process\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.storage_engine.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.uptime.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.dirty.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.maximum.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.pages.evicted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.pages.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.pages.write\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.cache.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.read.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.read.out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.read.total_tickets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.write.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.write.out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.concurrent_transactions.write.total_tickets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.flushes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.max_file_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.scans\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.syncs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.wired_tiger.log.writes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mongodb.status.write_backs_queued\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.database.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.database.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.active_temp_tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.batch_requests_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.cache_hit.pct\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.checkpoint_pages_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.database_pages\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.page_life_expectancy.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.buffer.target_pages\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.compilations_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.connections_reset_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.lock_waits_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.logins_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.logouts_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.page_splits_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.recompilations_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.transactions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.performance.user_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.space_usage.since_last_backup.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.space_usage.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.space_usage.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.space_usage.used.pct\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.active_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.backup_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.recovery_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.since_last_checkpoint.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mssql.transaction_log.stats.total_size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"munin.plugin.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.apply.oooe\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.apply.oool\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.apply.window\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cert.deps_distance\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cert.index_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cert.interval\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cluster.conf_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cluster.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.cluster.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.commit.oooe\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.commit.window\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.connected\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.evs.evict\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.evs.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.flow_ctl.paused\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.flow_ctl.paused_ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.flow_ctl.recv\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.flow_ctl.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.last_committed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.bf_aborts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.cert_failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.commits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.recv.queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.recv.queue_avg\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.recv.queue_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.recv.queue_min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.replays\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.send.queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.send.queue_avg\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.send.queue_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.send.queue_min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.local.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.ready\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.received.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.received.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.data_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.keys\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.keys_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.galera_status.repl.other_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.aborted.clients\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.aborted.connects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.binlog.cache.disk_use\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.binlog.cache.use\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.bytes.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.bytes.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.command.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.command.insert\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.command.select\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.command.update\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.created.tmp.disk_tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.created.tmp.files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.created.tmp.tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.delayed.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.delayed.insert_threads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.delayed.writes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.flush_commands\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.commit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.delete\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.external_lock\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.mrr_init\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.prepare\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.first\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.key\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.last\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.next\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.prev\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.rnd\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.read.rnd_next\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.rollback\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.savepoint\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.savepoint_rollback\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.update\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.handler.write\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.bytes.data\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.bytes.dirty\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.dump_status\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.load_status\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.data\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.dirty\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.flushed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.latched\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.misc\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pages.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pool.reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pool.resize_status\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.pool.wait_free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.read.ahead\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.read.ahead_evicted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.read.ahead_rnd\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.read.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.innodb.buffer_pool.write_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.max_used_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.open.files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.open.streams\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.open.tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.opened_tables\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.queries\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.questions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.threads.cached\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.threads.connected\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.threads.created\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"mysql.status.threads.running\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.connections.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.routes.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.server.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.server.time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.cores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.cpu\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.connz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.root\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.routez\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.subsz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.http.req_stats.uri.varz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.in.messages\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.mem.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.out.messages\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.remotes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.slow_consumers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.total_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.stats.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.cache.fanout.avg\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.cache.fanout.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.cache.hit_rate\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.cache.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.inserts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.matches\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.removes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nats.subscriptions.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.application\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.community_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.direction\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.forwarded_ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.iana_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.protocol\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.transport\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.accepts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.handled\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.reading\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.waiting\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nginx.stubstatus.writing\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.vendor\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.buffer_pool\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cache.buffer.hit.pct\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cache.get.consistent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cache.get.db_blocks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cache.physical_reads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.avg\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.cache_hit.pct\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.max\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.opened.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.opened.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.parse.real\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.parse.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.session.cache_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.cursors.total\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.io_reloads\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.lock_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.machine\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.pin_requests\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.performance.username\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.online_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.size.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.size.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.size.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.data_file.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.space.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.space.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"oracle.tablespace.space.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"organization.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.connections.accepted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.connections.listen_queue_len\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.connections.max_listen_queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.connections.queued\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.process_manager\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.idle\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.max_active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.max_children_reached\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.processes.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.slow_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.start_since\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.pool.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.last_request_cpu\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.last_request_memory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.request_duration\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.script\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.start_since\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"php_fpm.process.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.application_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.backend_start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.client.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.client.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.client.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.database.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.database.oid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.query\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.query_start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.state_change\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.transaction_start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.user.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.activity.waiting\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.backend\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.backend_fsync\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.checkpoints\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.clean\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.buffers.clean_full\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.checkpoints.requested\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.checkpoints.scheduled\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.checkpoints.times.sync.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.checkpoints.times.write.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.bgwriter.stats_reset\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.blocks.hit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.blocks.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.blocks.time.read.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.blocks.time.write.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.conflicts\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.deadlocks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.number_of_backends\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.oid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.deleted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.fetched\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.inserted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.returned\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.rows.updated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.stats_reset\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.temporary.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.temporary.files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.transactions.commit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.database.transactions.rollback\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.database.oid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.calls\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.local.dirtied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.local.hit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.local.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.local.written\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.shared.dirtied\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.shared.hit\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.shared.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.shared.written\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.temp.read\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.memory.temp.written\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.rows\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.text\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.max.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.mean.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.min.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.stddev.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.query.time.total.ms\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"postgresql.statement.user.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.args\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.executable\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pgid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.ppid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.title\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.working_directory\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.channel_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.channels\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.client_provided.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.frame_max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.octet_count.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.octet_count.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.packet_count.pending\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.packet_count.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.packet_count.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.peer.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.peer.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.connection.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.auto_delete\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.durable\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.internal\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.messages.publish_in.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.messages.publish_in.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.messages.publish_out.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.messages.publish_out.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.exchange.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.disk.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.disk.free.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.fd.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.fd.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.gc.num.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.gc.reclaimed.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.file_handle.open_attempt.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.file_handle.open_attempt.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.read.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.reopen.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.seek.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.seek.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.sync.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.sync.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.write.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.io.write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.mem.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.mem.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.mnesia.disk.tx.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.mnesia.ram.tx.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.msg.store_read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.msg.store_write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.proc.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.proc.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.processors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.queue.index.journal_write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.queue.index.read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.queue.index.write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.run.queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.socket.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.socket.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.node.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.arguments.max_priority\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.auto_delete\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.consumers.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.consumers.utilisation.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.disk.reads.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.disk.writes.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.durable\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.exclusive\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.memory.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.persistent.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.ready.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.ready.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.total.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.total.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.unacknowledged.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.messages.unacknowledged.details.rate\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.queue.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rabbitmq.vhost\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.biggest_input_buf\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.blocked\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.connected\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.longest_output_list\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.max_input_buffer\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.clients.max_output_buffer\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cluster.enabled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cpu.used.sys\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cpu.used.sys_children\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cpu.used.user\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.cpu.used.user_children\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.active_defrag.is_running\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.allocated\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.fragmentation.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.fragmentation.ratio\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.resident\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.allocator_stats.rss.ratio\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.fragmentation.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.fragmentation.ratio\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.max.policy\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.max.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.dataset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.lua\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.peak\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.rss\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.memory.used.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.bgrewrite.last_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.buffer.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.copy_on_write.last_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.enabled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.fsync.delayed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.fsync.pending\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.buffer.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.current_time.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.in_progress\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.last_time.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.rewrite.scheduled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.size.base\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.size.current\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.aof.write.last_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.loading\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.bgsave.current_time.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.bgsave.in_progress\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.bgsave.last_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.bgsave.last_time.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.copy_on_write.last_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.last_save.changes_since\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.persistence.rdb.last_save.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.backlog.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.backlog.first_byte_offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.backlog.histlen\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.backlog.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.connected_slaves\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.last_io_seconds_ago\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.link_status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.second_offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.sync.in_progress\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.sync.last_io_seconds_ago\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master.sync.left_bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.master_offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.role\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.slave.is_readonly\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.slave.offset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.replication.slave.priority\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.arch_bits\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.build_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.config_file\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.gcc_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.git_dirty\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.git_sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.hz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.lru_clock\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.mode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.multiplexing_api\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.run_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.tcp_port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.server.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.slowlog.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.active_defrag.hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.active_defrag.key_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.active_defrag.key_misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.active_defrag.misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.commands_processed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.connections.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.connections.rejected\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.instantaneous.input_kbps\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.instantaneous.ops_per_sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.instantaneous.output_kbps\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.keys.evicted\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.keys.expired\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.keyspace.hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.keyspace.misses\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.latest_fork_usec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.migrate_cached_sockets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.net.input.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.net.output.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.pubsub.channels\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.pubsub.patterns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.slave_expires_tracked_keys\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.sync.full\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.sync.partial.err\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.info.stats.sync.partial.ok\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.expire.ttl\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.length\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.key.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.keyspace.avg_ttl\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.keyspace.expires\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.keyspace.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"redis.keyspace.keys\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"related.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.ephemeral_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.idle.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.idle.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.iowait.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.iowait.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.irq.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.irq.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.nice.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.nice.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.softirq.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.softirq.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.steal.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.steal.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.system.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.system.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.user.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.core.user.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.cores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.idle.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.idle.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.idle.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.iowait.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.iowait.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.iowait.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.irq.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.irq.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.irq.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.nice.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.nice.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.nice.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.softirq.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.softirq.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.softirq.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.steal.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.steal.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.steal.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.system.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.system.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.system.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.total.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":3,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.user.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.user.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.user.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.io.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.await\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.busy\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.queue.avg_size\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.read.await\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.read.per_sec.bytes\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.read.request.merges_per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.read.request.per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.request.avg_size\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.service_time\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.write.await\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.write.per_sec.bytes\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.write.request.merges_per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.iostat.write.request.per_sec\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.read.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.read.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.read.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.write.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.write.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.diskio.write.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.entropy.available_bits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.entropy.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.available\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.device_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.free_files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.mount_point\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.filesystem.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.total_files\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.total_size.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.total_size.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.fsstat.total_size.used\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.1\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.15\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.5\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.cores\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.norm.1\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.norm.15\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.load.norm.5\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.actual.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.actual.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.actual.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.default_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.reserved\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.surplus\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.hugepages.used.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.swap.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.swap.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.swap.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.swap.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.used.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.in.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.in.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.in.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.in.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.out.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.out.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.out.errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.network.out.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.blkio.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.blkio.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.blkio.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.blkio.total.ios\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.cfs.period.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.cfs.quota.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.cfs.shares\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.rt.period.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.rt.runtime.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.stats.periods\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.stats.throttled.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpu.stats.throttled.periods\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.stats.system.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.stats.user.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.cpuacct.total.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem.usage.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem_tcp.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem_tcp.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem_tcp.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.kmem_tcp.usage.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.usage.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.memsw.failures\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.memsw.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.memsw.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.memsw.usage.max.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.active_anon.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.active_file.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.cache.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.hierarchical_memory_limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.hierarchical_memsw_limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.inactive_anon.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.inactive_file.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.major_page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.mapped_file.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.page_faults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.pages_in\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.pages_out\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.rss_huge.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.swap.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.unevictable.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cmdline\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.start_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.system.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.value\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.user.ticks\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.fd.limit.hard\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.fd.limit.soft\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.fd.open\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.rss.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.share\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.dead\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.idle\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.running\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.sleeping\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.stopped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.unknown\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.summary.zombie\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.blocks.synced\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.blocks.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.disks.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.disks.failed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.disks.spare\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.disks.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.level\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.raid.sync_action\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.local.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.local.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.process.cmdline\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.etld_plus_one\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.host_error\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.remote.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.all.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.all.listening\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.close_wait\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.established\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.listening\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.orphan\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.all.time_wait\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.tcp.memory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.udp.all.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.socket.summary.udp.memory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.uptime.duration.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"timeseries.instance\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tracing.trace.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tracing.transaction.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"traefik.health.response.avg_time.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"traefik.health.response.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"traefik.health.uptime.sec\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.fragment\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.password\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.query\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.scheme\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.username\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.device.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.read_errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.requests.offloaded\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.requests.routed\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.requests.static\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.requests.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.worker_pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.core.write_errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.exceptions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.read_errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.total.write_errors\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.accepting\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.avg_rt\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.delta_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.exceptions\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.harakiri_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.respawn_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.rss\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.running_time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.signal_queue\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.signals\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.tx\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"uwsgi.status.worker.vsz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.capacity.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.capacity.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.capacity.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.capacity.used.pct\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.fstype\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.datastore.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.cpu.free.mhz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.cpu.total.mhz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.cpu.used.mhz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.memory.free.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.memory.total.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.memory.used.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.host.network_names\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.cpu.used.mhz\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.host\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.memory.free.guest.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.memory.total.guest.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.memory.used.guest.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.memory.used.host.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.network_names\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vsphere.virtualmachine.os\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.display_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.exit_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.path_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.start_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.start_type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"windows.service.uptime.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.connection.interest_ops\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.connection.queued\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.connection.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.connection.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.approximate_data_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.ephemerals_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.followers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.latency.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.latency.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.latency.min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.max_file_descriptor_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.num_alive_connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.open_file_descriptor_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.outstanding_requests\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.packets.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.packets.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.pending_syncs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.server_state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.synced_followers\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.watch_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.mntr.znode_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.connections\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.epoch\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.latency.avg\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.latency.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.latency.min\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.mode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.node_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.outstanding\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.received\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.sent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.version_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"zookeeper.server.zxid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName" : "@timestamp", + "title" : "metricbeat-*" + }, + "type" : "index-pattern", + "migrationVersion" : { + "index-pattern" : "7.6.0" + }, + "updated_at" : "2020-01-22T15:34:59.061Z" + } + } +} + { "type": "doc", "value": { diff --git a/x-pack/test/functional/page_objects/code_page.ts b/x-pack/test/functional/page_objects/code_page.ts deleted file mode 100644 index 4a5cabe38de450..00000000000000 --- a/x-pack/test/functional/page_objects/code_page.ts +++ /dev/null @@ -1,47 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -// import testSubjSelector from '@kbn/test-subj-selector'; -// import Keys from 'leadfoot/keys'; -// import moment from 'moment'; - -import { FtrProviderContext } from '../ftr_provider_context'; - -export function CodeHomePageProvider({ getService }: FtrProviderContext) { - const testSubjects = getService('testSubjects'); - const log = getService('log'); - const queryBar = getService('queryBar'); - - return { - async fillImportRepositoryUrlInputBox(repoUrl: string) { - return await testSubjects.setValue('importRepositoryUrlInputBox', repoUrl); - }, - - async fillSearchQuery(query: string) { - // return await testSubjects.setValue('queryInput', query); - await queryBar.setQuery(query); - }, - - async submitSearchQuery() { - await queryBar.submitQuery(); - }, - - async clickImportRepositoryButton() { - log.info('Click import repository button.'); - return await testSubjects.click('importRepositoryButton'); - }, - - async clickIndexRepositoryButton() { - log.info('Click index repository button.'); - return await testSubjects.click('indexRepositoryButton'); - }, - - async clickDeleteRepositoryButton() { - log.info('Click delete repository button.'); - return await testSubjects.click('deleteRepositoryButton'); - }, - }; -} diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.js index 16cf665bf82eeb..b78ec6a477e1f8 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.js @@ -388,6 +388,27 @@ export function GisPageProvider({ getService, getPageObjects }) { } } + async closeOrCancelLayer(layerName) { + log.debug(`Close or cancel layer add`); + const cancelExists = await testSubjects.exists('layerAddCancelButton'); + const closeExists = await testSubjects.exists('layerPanelCancelButton'); + if (cancelExists) { + log.debug(`Cancel layer add.`); + await testSubjects.click('layerAddCancelButton'); + } else if (closeExists) { + log.debug(`Close layer add.`); + await testSubjects.click('layerPanelCancelButton'); + } else { + log.debug(`No need to close or cancel.`); + return; + } + + await this.waitForLayerAddPanelClosed(); + if (layerName) { + await this.waitForLayerDeleted(layerName); + } + } + async importFileButtonEnabled() { log.debug(`Check "Import file" button enabled`); const importFileButton = await testSubjects.find('importFileButton'); diff --git a/x-pack/test/functional/page_objects/index.ts b/x-pack/test/functional/page_objects/index.ts index 18ea515a73147c..91d4a3663fa659 100644 --- a/x-pack/test/functional/page_objects/index.ts +++ b/x-pack/test/functional/page_objects/index.ts @@ -33,7 +33,6 @@ import { GisPageProvider } from './gis_page'; import { StatusPagePageProvider } from './status_page'; // @ts-ignore not ts yet import { UpgradeAssistantProvider } from './upgrade_assistant'; -import { CodeHomePageProvider } from './code_page'; // @ts-ignore not ts yet import { RollupPageProvider } from './rollup_page'; import { UptimePageProvider } from './uptime_page'; @@ -68,7 +67,6 @@ export const pageObjects = { maps: GisPageProvider, statusPage: StatusPagePageProvider, upgradeAssistant: UpgradeAssistantProvider, - code: CodeHomePageProvider, uptime: UptimePageProvider, rollup: RollupPageProvider, licenseManagement: LicenseManagementPageProvider, diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts index f04f96148583fa..2ae0ea38c957bb 100644 --- a/x-pack/test/functional/page_objects/uptime_page.ts +++ b/x-pack/test/functional/page_objects/uptime_page.ts @@ -4,11 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; export function UptimePageProvider({ getPageObjects, getService }: FtrProviderContext) { const pageObjects = getPageObjects(['common', 'timePicker']); const uptimeService = getService('uptime'); + const retry = getService('retry'); return new (class UptimePage { public async goToUptimePageAndSetDateRange( @@ -51,8 +53,10 @@ export function UptimePageProvider({ getPageObjects, getService }: FtrProviderCo await Promise.all(monitorIdsToCheck.map(id => uptimeService.monitorPageLinkExists(id))); } - public async pageUrlContains(value: string) { - return await uptimeService.urlContains(value); + public async pageUrlContains(value: string, expected: boolean = true) { + retry.try(async () => { + expect(await uptimeService.urlContains(value)).to.eql(expected); + }); } public async changePage(direction: 'next' | 'prev') { diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts index 4fdfe0d32ace3d..0276ca81097320 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts @@ -40,8 +40,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('alerts', function() { before(async () => { await pageObjects.common.navigateToApp('triggersActions'); - const alertsTab = await testSubjects.find('alertsTab'); - await alertsTab.click(); + await testSubjects.click('alertsTab'); }); it('should search for alert', async () => { @@ -76,123 +75,100 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { ]); }); - // Flaky until https://github.com/elastic/eui/issues/2612 fixed - it.skip('should disable single alert', async () => { + it('should disable single alert', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); - const enableSwitch = await testSubjects.find('enableSwitch'); - await enableSwitch.click(); + await pageObjects.triggersActionsUI.toggleSwitch('enableSwitch'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActionsAfterDisable = await testSubjects.find('collapsedItemActions'); - await collapsedItemActionsAfterDisable.click(); + await testSubjects.click('collapsedItemActions'); const enableSwitchAfterDisable = await testSubjects.find('enableSwitch'); const isChecked = await enableSwitchAfterDisable.getAttribute('aria-checked'); expect(isChecked).to.eql('false'); }); - // Flaky until https://github.com/elastic/eui/issues/2612 fixed - it.skip('should re-enable single alert', async () => { + it('should re-enable single alert', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); - const enableSwitch = await testSubjects.find('enableSwitch'); - await enableSwitch.click(); + await pageObjects.triggersActionsUI.toggleSwitch('enableSwitch'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActionsAfterDisable = await testSubjects.find('collapsedItemActions'); - await collapsedItemActionsAfterDisable.click(); + await testSubjects.click('collapsedItemActions'); - const enableSwitchAfterDisable = await testSubjects.find('enableSwitch'); - await enableSwitchAfterDisable.click(); + await pageObjects.triggersActionsUI.toggleSwitch('enableSwitch'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActionsAfterReEnable = await testSubjects.find('collapsedItemActions'); - await collapsedItemActionsAfterReEnable.click(); + await testSubjects.click('collapsedItemActions'); const enableSwitchAfterReEnable = await testSubjects.find('enableSwitch'); const isChecked = await enableSwitchAfterReEnable.getAttribute('aria-checked'); expect(isChecked).to.eql('true'); }); - // Flaky until https://github.com/elastic/eui/issues/2612 fixed - it.skip('should mute single alert', async () => { + it('should mute single alert', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); - const muteSwitch = await testSubjects.find('muteSwitch'); - await muteSwitch.click(); + await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActionsAfterMute = await testSubjects.find('collapsedItemActions'); - await collapsedItemActionsAfterMute.click(); + await testSubjects.click('collapsedItemActions'); const muteSwitchAfterMute = await testSubjects.find('muteSwitch'); const isChecked = await muteSwitchAfterMute.getAttribute('aria-checked'); expect(isChecked).to.eql('true'); }); - // Flaky until https://github.com/elastic/eui/issues/2612 fixed - it.skip('should unmute single alert', async () => { + it('should unmute single alert', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); - const muteSwitch = await testSubjects.find('muteSwitch'); - await muteSwitch.click(); + await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActionsAfterMute = await testSubjects.find('collapsedItemActions'); - await collapsedItemActionsAfterMute.click(); + await testSubjects.click('collapsedItemActions'); - const muteSwitchAfterMute = await testSubjects.find('muteSwitch'); - await muteSwitchAfterMute.click(); + await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActionsAfterUnmute = await testSubjects.find('collapsedItemActions'); - await collapsedItemActionsAfterUnmute.click(); + await testSubjects.click('collapsedItemActions'); const muteSwitchAfterUnmute = await testSubjects.find('muteSwitch'); const isChecked = await muteSwitchAfterUnmute.getAttribute('aria-checked'); expect(isChecked).to.eql('false'); }); - // Flaky, will be fixed with https://github.com/elastic/kibana/issues/53956 - it.skip('should delete single alert', async () => { + it('should delete single alert', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); - const deleteBtn = await testSubjects.find('deleteAlert'); - await deleteBtn.click(); + await testSubjects.click('deleteAlert'); - retry.try(async () => { + await retry.try(async () => { await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); const searchResults = await pageObjects.triggersActionsUI.getAlertsList(); @@ -200,140 +176,114 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); - // Flaky, will be fixed with https://github.com/elastic/kibana/issues/49830 - it.skip('should mute all selection', async () => { + it('should mute all selection', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const checkbox = await testSubjects.find(`checkboxSelectRow-${createdAlert.id}`); - await checkbox.click(); + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - const bulkActionBtn = await testSubjects.find('bulkAction'); - await bulkActionBtn.click(); + await testSubjects.click('bulkAction'); - const muteAllBtn = await testSubjects.find('muteAll'); - await muteAllBtn.click(); + await testSubjects.click('muteAll'); // Unmute all button shows after clicking mute all await testSubjects.existOrFail('unmuteAll'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); const muteSwitch = await testSubjects.find('muteSwitch'); const isChecked = await muteSwitch.getAttribute('aria-checked'); expect(isChecked).to.eql('true'); }); - // Flaky, will be fixed with https://github.com/elastic/kibana/issues/49830 - it.skip('should unmute all selection', async () => { + it('should unmute all selection', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const checkbox = await testSubjects.find(`checkboxSelectRow-${createdAlert.id}`); - await checkbox.click(); + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - const bulkActionBtn = await testSubjects.find('bulkAction'); - await bulkActionBtn.click(); + await testSubjects.click('bulkAction'); - const muteAllBtn = await testSubjects.find('muteAll'); - await muteAllBtn.click(); + await testSubjects.click('muteAll'); - const unmuteAllBtn = await testSubjects.find('unmuteAll'); - await unmuteAllBtn.click(); + await testSubjects.click('unmuteAll'); // Mute all button shows after clicking unmute all await testSubjects.existOrFail('muteAll'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); const muteSwitch = await testSubjects.find('muteSwitch'); const isChecked = await muteSwitch.getAttribute('aria-checked'); expect(isChecked).to.eql('false'); }); - // Flaky, will be fixed with https://github.com/elastic/kibana/issues/49830 - it.skip('should disable all selection', async () => { + it('should disable all selection', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const checkbox = await testSubjects.find(`checkboxSelectRow-${createdAlert.id}`); - await checkbox.click(); + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - const bulkActionBtn = await testSubjects.find('bulkAction'); - await bulkActionBtn.click(); + await testSubjects.click('bulkAction'); - const disableAllBtn = await testSubjects.find('disableAll'); - await disableAllBtn.click(); + await testSubjects.click('disableAll'); // Enable all button shows after clicking disable all await testSubjects.existOrFail('enableAll'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); const enableSwitch = await testSubjects.find('enableSwitch'); const isChecked = await enableSwitch.getAttribute('aria-checked'); expect(isChecked).to.eql('false'); }); - // Flaky, will be fixed with https://github.com/elastic/kibana/issues/49830 - it.skip('should enable all selection', async () => { + it('should enable all selection', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const checkbox = await testSubjects.find(`checkboxSelectRow-${createdAlert.id}`); - await checkbox.click(); + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - const bulkActionBtn = await testSubjects.find('bulkAction'); - await bulkActionBtn.click(); + await testSubjects.click('bulkAction'); - const disableAllBtn = await testSubjects.find('disableAll'); - await disableAllBtn.click(); + await testSubjects.click('disableAll'); - const enableAllBtn = await testSubjects.find('enableAll'); - await enableAllBtn.click(); + await testSubjects.click('enableAll'); // Disable all button shows after clicking enable all await testSubjects.existOrFail('disableAll'); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const collapsedItemActions = await testSubjects.find('collapsedItemActions'); - await collapsedItemActions.click(); + await testSubjects.click('collapsedItemActions'); const enableSwitch = await testSubjects.find('enableSwitch'); const isChecked = await enableSwitch.getAttribute('aria-checked'); expect(isChecked).to.eql('true'); }); - // Flaky, will be fixed with https://github.com/elastic/kibana/issues/53956 - it.skip('should delete all selection', async () => { + it('should delete all selection', async () => { const createdAlert = await createAlert(); await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - const checkbox = await testSubjects.find(`checkboxSelectRow-${createdAlert.id}`); - await checkbox.click(); + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - const bulkActionBtn = await testSubjects.find('bulkAction'); - await bulkActionBtn.click(); + await testSubjects.click('bulkAction'); - const deleteAllBtn = await testSubjects.find('deleteAll'); - await deleteAllBtn.click(); + await testSubjects.click('deleteAll'); - retry.try(async () => { + await retry.try(async () => { await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); const searchResults = await pageObjects.triggersActionsUI.getAlertsList(); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts index 7b60685225ac6c..d037155a29e12c 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts @@ -20,8 +20,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('Connectors', function() { before(async () => { await pageObjects.common.navigateToApp('triggersActions'); - const alertsTab = await testSubjects.find('connectorsTab'); - await alertsTab.click(); + await testSubjects.click('connectorsTab'); }); it('should create a connector', async () => { @@ -29,18 +28,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.triggersActionsUI.clickCreateConnectorButton(); - const serverLogCard = await testSubjects.find('.server-log-card'); - await serverLogCard.click(); + await testSubjects.click('.server-log-card'); const nameInput = await testSubjects.find('nameInput'); await nameInput.click(); await nameInput.clearValue(); await nameInput.type(connectorName); - const saveButton = await find.byCssSelector( - '[data-test-subj="saveActionButton"]:not(disabled)' - ); - await saveButton.click(); + await find.clickByCssSelector('[data-test-subj="saveActionButton"]:not(disabled)'); const toastTitle = await pageObjects.common.closeToast(); expect(toastTitle).to.eql(`Created '${connectorName}'`); @@ -63,18 +58,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.triggersActionsUI.clickCreateConnectorButton(); - const serverLogCard = await testSubjects.find('.server-log-card'); - await serverLogCard.click(); + await testSubjects.click('.server-log-card'); const nameInput = await testSubjects.find('nameInput'); await nameInput.click(); await nameInput.clearValue(); await nameInput.type(connectorName); - const saveButton = await find.byCssSelector( - '[data-test-subj="saveActionButton"]:not(disabled)' - ); - await saveButton.click(); + await find.clickByCssSelector('[data-test-subj="saveActionButton"]:not(disabled)'); await pageObjects.common.closeToast(); @@ -83,20 +74,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const searchResultsBeforeEdit = await pageObjects.triggersActionsUI.getConnectorsList(); expect(searchResultsBeforeEdit.length).to.eql(1); - const editConnectorBtn = await find.byCssSelector( - '[data-test-subj="connectorsTableCell-name"] button' - ); - await editConnectorBtn.click(); + await find.clickByCssSelector('[data-test-subj="connectorsTableCell-name"] button'); const nameInputToUpdate = await testSubjects.find('nameInput'); await nameInputToUpdate.click(); await nameInputToUpdate.clearValue(); await nameInputToUpdate.type(updatedConnectorName); - const saveEditButton = await find.byCssSelector( - '[data-test-subj="saveActionButton"]:not(disabled)' - ); - await saveEditButton.click(); + await find.clickByCssSelector('[data-test-subj="saveActionButton"]:not(disabled)'); const toastTitle = await pageObjects.common.closeToast(); expect(toastTitle).to.eql(`Updated '${updatedConnectorName}'`); @@ -117,18 +102,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { async function createConnector(connectorName: string) { await pageObjects.triggersActionsUI.clickCreateConnectorButton(); - const serverLogCard = await testSubjects.find('.server-log-card'); - await serverLogCard.click(); + await testSubjects.click('.server-log-card'); const nameInput = await testSubjects.find('nameInput'); await nameInput.click(); await nameInput.clearValue(); await nameInput.type(connectorName); - const saveButton = await find.byCssSelector( - '[data-test-subj="saveActionButton"]:not(disabled)' - ); - await saveButton.click(); + await find.clickByCssSelector('[data-test-subj="saveActionButton"]:not(disabled)'); await pageObjects.common.closeToast(); } const connectorName = generateUniqueKey(); @@ -141,12 +122,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const searchResultsBeforeDelete = await pageObjects.triggersActionsUI.getConnectorsList(); expect(searchResultsBeforeDelete.length).to.eql(1); - const deleteConnectorBtn = await testSubjects.find('deleteConnector'); - await deleteConnectorBtn.click(); + await testSubjects.click('deleteConnector'); await testSubjects.existOrFail('deleteConnectorsConfirmation'); await testSubjects.click('deleteConnectorsConfirmation > confirmModalConfirmButton'); await testSubjects.missingOrFail('deleteConnectorsConfirmation'); + const toastTitle = await pageObjects.common.closeToast(); + expect(toastTitle).to.eql('Deleted 1 connector'); + await pageObjects.triggersActionsUI.searchConnectors(connectorName); const searchResultsAfterDelete = await pageObjects.triggersActionsUI.getConnectorsList(); @@ -157,18 +140,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { async function createConnector(connectorName: string) { await pageObjects.triggersActionsUI.clickCreateConnectorButton(); - const serverLogCard = await testSubjects.find('.server-log-card'); - await serverLogCard.click(); + await testSubjects.click('.server-log-card'); const nameInput = await testSubjects.find('nameInput'); await nameInput.click(); await nameInput.clearValue(); await nameInput.type(connectorName); - const saveButton = await find.byCssSelector( - '[data-test-subj="saveActionButton"]:not(disabled)' - ); - await saveButton.click(); + await find.clickByCssSelector('[data-test-subj="saveActionButton"]:not(disabled)'); await pageObjects.common.closeToast(); } @@ -182,17 +161,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const searchResultsBeforeDelete = await pageObjects.triggersActionsUI.getConnectorsList(); expect(searchResultsBeforeDelete.length).to.eql(1); - const deleteCheckbox = await find.byCssSelector( - '.euiTableRowCellCheckbox .euiCheckbox__input' - ); - await deleteCheckbox.click(); + await find.clickByCssSelector('.euiTableRowCellCheckbox .euiCheckbox__input'); - const bulkDeleteBtn = await testSubjects.find('bulkDelete'); - await bulkDeleteBtn.click(); + await testSubjects.click('bulkDelete'); await testSubjects.existOrFail('deleteConnectorsConfirmation'); await testSubjects.click('deleteConnectorsConfirmation > confirmModalConfirmButton'); await testSubjects.missingOrFail('deleteConnectorsConfirmation'); + const toastTitle = await pageObjects.common.closeToast(); + expect(toastTitle).to.eql('Deleted 1 connector'); + await pageObjects.triggersActionsUI.searchConnectors(connectorName); const searchResultsAfterDelete = await pageObjects.triggersActionsUI.getConnectorsList(); diff --git a/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts b/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts index ce68109771487b..a04ecc969a7e1f 100644 --- a/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts +++ b/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts @@ -4,12 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; const ENTER_KEY = '\uE007'; export function TriggersActionsPageProvider({ getService }: FtrProviderContext) { const find = getService('find'); + const retry = getService('retry'); const testSubjects = getService('testSubjects'); return { @@ -93,5 +95,15 @@ export function TriggersActionsPageProvider({ getService }: FtrProviderContext) async changeTabs(tab: 'alertsTab' | 'connectorsTab') { return await testSubjects.click(tab); }, + async toggleSwitch(testSubject: string) { + const switchBtn = await testSubjects.find(testSubject); + const valueBefore = await switchBtn.getAttribute('aria-checked'); + await switchBtn.click(); + await retry.try(async () => { + const switchBtnAfter = await testSubjects.find(testSubject); + const valueAfter = await switchBtnAfter.getAttribute('aria-checked'); + expect(valueAfter).not.to.eql(valueBefore); + }); + }, }; } diff --git a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts index bd35f21d8f428b..0346da334d2f2d 100644 --- a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts +++ b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts @@ -344,8 +344,7 @@ export default function({ getService }: FtrProviderContext) { }); }); - // FAILING: https://github.com/elastic/kibana/issues/52969 - describe.skip('API access with missing access token document or expired refresh token.', () => { + describe('API access with missing access token document or expired refresh token.', () => { let sessionCookie: Cookie; beforeEach(async () => { diff --git a/x-pack/test/ui_capabilities/common/nav_links_builder.ts b/x-pack/test/ui_capabilities/common/nav_links_builder.ts index 8b7741469362e8..aaeb22852bcc09 100644 --- a/x-pack/test/ui_capabilities/common/nav_links_builder.ts +++ b/x-pack/test/ui_capabilities/common/nav_links_builder.ts @@ -13,7 +13,7 @@ export class NavLinksBuilder { ...features, // management isn't a first-class "feature", but it makes our life easier here to pretend like it is management: { - navLinkId: 'kibana:management', + navLinkId: 'kibana:stack_management', }, }; } diff --git a/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts b/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts index 4af7d81e5a7b4f..5c13e6b0eb51eb 100644 --- a/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts +++ b/x-pack/test/ui_capabilities/common/services/ui_capabilities.ts @@ -68,7 +68,7 @@ export class UICapabilitiesService { : {}; const response = await this.axios.post( `${spaceUrlPrefix}/api/core/capabilities`, - { applications: [...applications, 'kibana:management'] }, + { applications: [...applications, 'kibana:stack_management'] }, { headers: requestHeaders, } diff --git a/x-pack/typings/hapi.d.ts b/x-pack/typings/hapi.d.ts index a739d5f884f6e9..8d54d28794351d 100644 --- a/x-pack/typings/hapi.d.ts +++ b/x-pack/typings/hapi.d.ts @@ -8,7 +8,7 @@ import 'hapi'; import { XPackMainPlugin } from '../legacy/plugins/xpack_main/server/xpack_main'; import { SecurityPlugin } from '../legacy/plugins/security'; -import { ActionsPlugin, ActionsClient } from '../legacy/plugins/actions'; +import { ActionsPlugin, ActionsClient } from '../plugins/actions/server'; import { AlertingPlugin, AlertsClient } from '../legacy/plugins/alerting'; import { LegacyTaskManagerApi } from '../legacy/plugins/task_manager/server'; diff --git a/x-pack/yarn.lock b/x-pack/yarn.lock new file mode 120000 index 00000000000000..1fe23b6e377dd4 --- /dev/null +++ b/x-pack/yarn.lock @@ -0,0 +1 @@ +../yarn.lock \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b534a7a4fcb799..3563ee3fc2733f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4828,6 +4828,11 @@ resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.25.tgz#b6f55062827a4787fe4ab151cf3412a468e65271" integrity sha512-ShHzHkYD+Ldw3eyttptCpUhF1/mkInWwasQkCNXZHOsJMJ/UMa8wXrxSrTJaVk0r4pLK/VnESVM0wFsfQzNEKQ== +"@types/numeral@^0.0.26": + version "0.0.26" + resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.26.tgz#cfab9842ef9349ce714b06722940ca7ebf8a6298" + integrity sha512-DwCsRqeOWopdEsm5KLTxKVKDSDoj+pzZD1vlwu1GQJ6IF3RhjuleYlRwyRH6MJLGaf3v8wFTnC6wo3yYfz0bnA== + "@types/object-hash@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@types/object-hash/-/object-hash-1.3.0.tgz#b20db2074129f71829d61ff404e618c4ac3d73cf" @@ -13303,17 +13308,7 @@ fancy-log@^1.3.2: color-support "^1.1.3" time-stamp "^1.0.0" -fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8= - -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= - -fast-deep-equal@^3.1.1: +fast-deep-equal@^1.0.0, fast-deep-equal@^2.0.1, fast-deep-equal@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==